;**********************************************************************
; This file is part of the Fresh project,
;
; Virtual file library.
; The routines in this library simulates file access using memory.
;**********************************************************************

uglobal
  ptrCash  dd ?
endg

;----------------------------------------------------------------------
; Creates virtual file cash with files that are open in editor.
; ---------------------------------------------------------------------
proc InitVCash
.tab TEditorTab
begin
        push    esi edi ebx
        cmp     [ptrCash], 0
        je      @f

        stdcall DestroyVCash

@@:
        stdcall CreateArray, sizeof.TVFile
        mov     [ptrCash], eax

        stdcall EnumOpenFiles, _AppendVirtFile, 0

        pop     ebx edi esi
        return
endp




proc _AppendVirtFile, .ptrOpenFile, .lparam
.file TInMemoryFile
begin
        push    edi ebx
        mov     esi, [.ptrOpenFile]

        cmp     [esi+TOpenFile.fNeverSaved], FALSE
        jne     .addit

        stdcall GetModified, esi
        test    eax, eax
        jz      .finish

.addit:
        cmp     [esi+TOpenFile.hEditor], 0
        je      .finish

        lea     eax, [.file]
        invoke  SendMessageW, [esi+TOpenFile.hEditor], _CEM_GETTEXT, 0, eax
        test    eax, eax
        jnz     .finish         ; error geting the file

        mov     eax, [.file.ptrBuffer]

        stdcall AddArrayItems, [ptrCash], 1
        mov     [ptrCash], edx
        mov     edi, eax

        mov     edx, [esi+TOpenFile.hFileName]
        mov     ecx, [esi+TOpenFile.hashFileName]
        mov     [edi+TVFile.hFileName], edx
        mov     [edi+TVFile.hashName], ecx
        mov     [edi+TVFile.pos], 0

        mov     ecx, [.file.fileSize]
        mov     edx, [.file.ptrBuffer]
        mov     [edi+TVFile.size], ecx
        mov     [edi+TVFile.buffer], edx

.finish:
        pop     ebx edi
        clc
        return
endp




proc DestroyVCash
begin
        push    esi ebx
        mov     esi, [ptrCash]
        test    esi, esi
        jz      .cashfree

        mov     ebx, [esi+TArray.count]
        test    ebx, ebx
        jz      .emptycash

        lea     esi, [esi+TArray.array]

.loop:
        stdcall FreeMem, [esi+TVFile.buffer]
;        stdcall StrDel, [esi+TVFile.hFileName]         ; Don't delete filename string it is shared...
        add     esi, sizeof.TVFile
        dec     ebx
        jnz     .loop

.emptycash:
        stdcall FreeMem, [ptrCash]
        mov     [ptrCash], 0

.cashfree:
        pop     ebx esi
        return
endp




proc CheckCash, .hFileName
begin
        push    esi edi ebx edx

        mov     esi, [ptrCash]
        test    esi, esi
        jz      .notfound

        stdcall HashFilename, [.hFileName]

        mov     ecx, [esi+TArray.count]
        lea     esi, [esi+TArray.array]

        jecxz   .notfound

.seek:                                         ; Should be binary  search, but for now the count will be small...
        cmp     [esi+TVFile.hashName], eax
        je      .found

        add     esi, sizeof.TVFile
        loop    .seek

.notfound:
        xor     eax, eax
        pop     edx ebx edi esi
        return

.found:
        mov     eax, esi
        pop     edx ebx edi esi
        return

endp


;--------------------------------------------------------------------
; Reads from virtual file. Returns count of bytes realy readed.
;--------------------------------------------------------------------
proc VReadFile, .ptrVFile, .ptrBuffer, .NumBytes
begin
        push    esi edi ebx

        mov     edx, [.ptrVFile]

        mov     ebx, [edx+TVFile.pos]

        mov     esi, [edx+TVFile.buffer]
        mov     ecx, [.NumBytes]
        mov     edi, [.ptrBuffer]

        cmp     [edx+TVFile.size], 0
        je      .error

        mov     eax, [edx+TVFile.size]
        sub     eax, ebx
        jle     .error

        cmp     eax, ecx        ; remaining size of the file.
        jge     .loop

        mov     ecx, eax

.loop:
        mov     al, [esi+ebx]
        inc     ebx
        mov     [edi], al
        inc     edi
        loop    .loop

.endloop:
        mov     eax, [.NumBytes]
        sub     eax, ecx
        mov     [edx+TVFile.pos], ebx
        jmp     .finish

.error:
        xor     eax,eax
.finish:
        pop     ebx edi esi
        return
endp



; Moves the file pointer to the given location in the virtual file.
proc VSetFilePointer, .ptrVFile, .Distance, .Method
begin
        push    esi edi ebx

        mov     esi, [.ptrVFile]
        mov     ecx, [esi+TVFile.size]
        mov     ebx, [esi+TVFile.pos]

        cmp     [.Method], FILE_BEGIN
        je      .begin
        cmp     [.Method], FILE_END
        je      .end

        add     ebx, [.Distance]
        jmp     .norm

.begin:
        mov     ebx, [.Distance]
        jmp     .norm

.end:
        sub     ecx, [.Distance]
        mov     ebx, ecx

.norm:
        test    ebx,ebx
        jns     @f
        xor     ebx,ebx
@@:
        cmp     ebx, [esi+TVFile.size]
        jl      @f
        mov     ebx, [esi+TVFile.size]
@@:
        mov     [esi+TVFile.pos], ebx
        mov     eax,ebx
        pop     ebx edi esi
        return
endp



