Fresh IDE . Artifact [f470fdd5fa]
Not logged in

This repository is a mirror!

The original is located on: https://fresh.flatassembler.net/fossil/repo/fresh
If you want to follow the project, please update your remote-url

Artifact f470fdd5fa03a6937232065e8c326666f1224f14:


;***************************************************
; The file manager is a part of Fresh IDE
; that control all files Fresh working with.
; It supersedes most of the functionality
; of project manager and source editor that is
; related to managing any type of files.
;***************************************************

iglobal

FileTypes:
  ; Project file type.
  ftProject         TFileType CreateProjectManager,     \
                              ProjFilter,               \
                              -1,                       \
                              NULL

  ; Usual text source file.
  ftCommonSource    TFileType CreateSourceEditor,       \
                              FileFilter,               \
                              0,                        \
                              fasm_syntax

  ; Main source file.
  ftMainSource      TFileType CreateSourceEditor,       \
                              FileFilter,               \
                              1,                        \
                              fasm_syntax

  ; File containing Form template and form handling source file.
  ftFormSource      TFileType CreateFormEditor,         \
                              FormFilter,               \
                              3,                        \
                              fasm_syntax

  ; Text document without syntax highlighter.
  ftTextDocument    TFileType CreateSourceEditor,       \
                              FileFilter,               \
                              2,                        \
                              NULL

  ; graphic file
  ftGraphic         TFileType CreateGraphicEditor,      \
                              GraphicFilter,            \
                              4,                        \
                              NULL

;  ftWatch           TFileType CreateMemWatch,           \
;                              WatchFilter,              \
;                              5,                        \
;                              NULL

  FileTypeNames:
        StrList                               \
          'Project',                          \
          'Source file',                      \
          'Main file',                        \
          'Form',                             \
          'Text document',                    \
          'Image';,                            \
;          'Memory watch table'

  FileTypeExt  dd '.fpr', '.asm', '.asm', '.frm', '.txt', '.bmp';, '.mwt'

endg


uglobal
  ptrCurrentFile dd ?   ; TOpenFile descendent that have the focus in that moment.
  listFiles      dd ?   ; TArray with all open files.
endg


;-------------------------------------------------
; Prepares file manager for work.
; Call this procedure only once at the begining.
;-------------------------------------------------
proc InitFileManager
begin
        stdcall CreateArray, 4
        mov     [listFiles], eax
        return
endp


;-------------------------------------------------
; Closes all still open files and finalizes the
; file manager. Call it once on close of Fresh
;-------------------------------------------------
proc CloseFileManager
begin
; Close and free all open files.
        stdcall ListFree, [listFiles], _FreeFileProc
        mov     [listFiles], 0
        return
endp


    proc _FreeFileProc, .ptrOpenFile
    begin
            push    esi
            mov     esi, [.ptrOpenFile]
            mov     [esi+TOpenFile.projectID], 0
            stdcall CloseFile, esi
            pop     esi
            return
    endp


proc OpenFileByNameEdit, .hFileName, .dummy
begin
        stdcall OpenFileByName, [.hFileName], NULL, TRUE
        return
endp


proc OpenFileByName, .hFileName, .hTemplate, .fLoadInEditor
begin
        push    ebx

; log the active file state before changing focus...
        cmp     [fLogFileLock], 0
        jne     @f
        cmp     [.fLoadInEditor], 0
        je      @f
        stdcall LogInHistory, ptrBackHistory
@@:

        stdcall IsFileOpen, [.hFileName]
        mov     ebx, eax
        test    eax, eax
        jnz     .focus

        stdcall DetectFileType, [.hFileName]
        mov     ebx, eax
        test    eax, eax
        jz      .unknowntype

.doopen:
        stdcall CreateFStruct, [.hFileName], ebx
        mov     ebx, eax

.focus:
        cmp     [ebx+TOpenFile.hEditor], 0
        jne     .dofocus

        cmp     [.fLoadInEditor], FALSE
        je      .finish

        stdcall LoadFile, ebx, [.hTemplate]
        test    eax, eax
        jz      .error

.dofocus:
        stdcall FocusFile, ebx

.finish:
        mov     eax, ebx
        pop     ebx
        return

.unknowntype:
        mov     ebx, ftTextDocument
        invoke  MessageBoxA, [hApplication], cWarningUnknownType, NULL, MB_YESNO or MB_ICONQUESTION
        cmp     eax, IDYES
        je      .doopen

        xor     eax, eax
        pop     ebx
        return

.error:
        stdcall FreeFStruct, ebx
        xor     eax, eax
        pop     ebx
        return
endp

iglobal
  cWarningUnknownType text 'Unknown file type.', 13, 10,      \
                             'Do you want to open it as text?'
endg



;--------------------------------------------------------------------
; Check whether the file is already open in the coresponding editor.
; Returns:
; eax:
;   NULL - the file is not open.
;   ptrOpenFile - the file is open.
;--------------------------------------------------------------------
proc IsFileOpen, .hFileName
.str rb 512
.ptr dd ?
begin
        push    esi ebx

        stdcall StrPtr, [.hFileName]
        lea     ebx, [.str]
        lea     edx, [.ptr]
        invoke  GetFullPathNameA, eax, 512, ebx, edx

        stdcall HashFilename, ebx
        mov     edx, eax

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

.while:
        dec     ecx
        js      .notfound
        lodsd
        cmp     edx, [eax+TOpenFile.hashFileName]
        jne     .while

        stdcall StrCompNoCase, [eax+TOpenFile.hFileName], ebx
        jnc     .while

; Found:
        pop     ebx esi
        return

.notfound:
        xor     eax, eax
        pop     ebx esi
        return
endp



;----------------------------------------------------------------------
; Detects the proper type of the file from it's extension.
; Returns valid pointer to TFileType structure or NULL for error.
;----------------------------------------------------------------------
proc DetectFileType, .hFileName
begin
        stdcall StrLen, [.hFileName]
        mov     ecx, eax
        stdcall StrPtr, [.hFileName]

.extloop:
        dec     ecx
        js      .error

        cmp     byte [eax+ecx], '.'
        jne     .extloop

        mov     ecx, dword [eax+ecx]    ; get the extension
        or      ecx, $20202000          ; case insensitive

        mov     eax, ftCommonSource
        cmp     ecx, '.asm'
        je      .typeok

        cmp     ecx, '.inc'
        je      .typeok

        mov     eax, ftFormSource
        cmp     ecx, '.frm'
        je      .typeok

        mov     eax, ftProject
        cmp     ecx, '.fpr'
        je      .typeok

        mov     eax, ftTextDocument
        cmp     ecx, '.txt'
        je      .typeok

        mov     eax, ftGraphic
        cmp     ecx, '.bmp'
        je      .typeok

.error:
        xor     eax, eax
.typeok:
        return
endp




;----------------------------------------------------------------------
; Creates the file structure for given file type.
; If in some of the editors, the file with the same name is
; already open, returns the pointer to the existing file.
;
; In the case if new file is created:
; Set the values for following fields:
;   .type         = needed type value.
;   .hFileName    = full filename of the file.
;   .hashFileName = hash value of the filename.
;   .fNeverSaved  = FALSE if the file with given name exists
;                   TRUE otherwize.
;
;  Returns the pointer to the TOpenFile in the eax register.
;----------------------------------------------------------------------
proc CreateFStruct, .hFileName, .type
.str  rb  512
.ptr  dd  ?
begin
        push    ebx esi

        mov     ebx, [.type]
        test    ebx, ebx
        jnz     .typeok

        mov     ebx, ftTextDocument

.typeok:
        stdcall IsFileOpen, [.hFileName]
        test    eax, eax
        jnz     .finish

        stdcall GetMem, sizeof.TOpenFile
        mov     esi, eax

        stdcall AddArrayItems, [listFiles], 1
        mov     [listFiles], edx
        mov     [eax], esi

        mov     [esi+TOpenFile.ptrType], ebx

        stdcall StrPtr, [.hFileName]
        lea     ecx, [.str]
        push    ecx             ; for future use
        lea     edx, [.ptr]

        invoke  GetFullPathNameA, eax, 512, ecx, edx
        stdcall StrDup  ; .str from the stack

        mov     [esi+TOpenFile.hFileName], eax

        stdcall HashFilename, eax
        mov     [esi+TOpenFile.hashFileName], eax


        stdcall StrPtr, [esi+TOpenFile.hFileName]
        stdcall FileExists, eax
        rcl     [esi+TOpenFile.fNeverSaved], 1

        mov     eax, esi

.finish:
        pop     esi ebx
        return
endp


;--------------------------------------------------
; Frees the TOpenFile descendent structure.
;--------------------------------------------------
proc FreeFStruct, .ptrFile
begin
        push    esi
        mov     esi, [.ptrFile]

        cmp     [esi+TOpenFile.hEditor], 0
        je      .editorclosed
        invoke  DestroyWindow, [esi+TOpenFile.hEditor]
        mov     [esi+TOpenFile.hEditor], 0

.editorclosed:
        cmp     [esi+TOpenFile.projectID], 0
        je      .notinproject

        invoke  SendMessageA, [hProjManager], PMM_REMOVEFILE, esi, 0

.notinproject:
        stdcall ListIndexOf, [listFiles], esi
        jc      .removedfromlist

        stdcall DeleteArrayItems, [listFiles], eax, 1
        mov     [listFiles], edx

.removedfromlist:
        stdcall StrDel, [esi+TOpenFile.hFileName]
        stdcall FreeMem, esi

        pop     esi
        return
endp


;------------------------------------------------------------------------
; Loads the given file in the apropriate editor window.
; If the file is loaded - do nothing.
; Returns NULL if error or eax = [ptrFile] if OK.
;------------------------------------------------------------------------
proc LoadFile, .ptrFile, .hTemplate
begin
        push    esi

        mov     esi, [.ptrFile]
        cmp     [esi+TOpenFile.hEditor], 0
        jne     .fileisloaded

        mov     eax, [esi+TOpenFile.ptrType]

        stdcall [eax+TFileType.CreateProc], esi, [.hTemplate]
        test    eax, eax
        jnz     .error

.fileisloaded:
        stdcall FocusFile, esi
        mov     eax, esi
        pop     esi
        return

.error:
        stdcall ErrorMessage, eax
        xor     eax, eax
        pop     esi
        return
endp


;-------------------------------------------------
; Renames given file and notifies the editor that
; the file was renamed.
;-------------------------------------------------
proc RenameFile, .ptrFile, .hNewName
begin
        push    esi
        mov     esi, [.ptrFile]

        stdcall StrCopy, [esi+TOpenFile.hFileName], [.hNewName]
        stdcall HashFilename, [esi+TOpenFile.hFileName]
        mov     [esi+TOpenFile.hashFileName], eax

        cmp     [esi+TOpenFile.hEditor], 0
        je      .checkproject

        ; notify the editor.
        invoke  SendMessageA, [esi+TOpenFile.hEditor], _CEM_CHANGENOTIFY, 0, 0

.checkproject:
        cmp     [esi+TOpenFile.projectID], 0
        je      .finish

        ; notify project manager.
        invoke  SendMessageA, [hProjManager], PMM_FILECHANGED, esi, 0

.finish:
        pop     esi
        return
endp




;------------------------------------------------
; Saves the file to the disk.
; Also checks if the flag .fNeverSaved is TRUE
; and opens the SaveAs dialog.
; The easy way to make function SaveAs is to
; set .fNeverSaved and to call this function.
; Return: TRUE if the file is saved
;         FALSE if the user canceled operation or error ocures.
;---------------------------------------------------------------
proc SaveFile, .ptrFile
.inmem TInMemoryFile
.res   dd ?
begin
        push    esi

        mov     [.res], TRUE
        mov     [.inmem.ptrBuffer], 0

        mov     esi, [.ptrFile]
        test    esi, esi
        jz      .finish

        cmp     [esi+TOpenFile.hEditor], 0
        je      .finish                         ; the file is not loaded in editor.

; Is the file need SaveAs?
        cmp     [esi+TOpenFile.fNeverSaved], FALSE
        je      .dosave

        mov     eax, [esi+TOpenFile.ptrType]
        stdcall SaveFileDialog, cSaveFileTitle, [eax+TFileType.ptrFilter], [esi+TOpenFile.hFileName]
        test    eax, eax
        jnz     .rename

        mov     [.res], eax
        jmp     .finish

.rename:
        push    eax
        stdcall RenameFile, esi, eax
        stdcall StrDel ; from the stack.

.dosave:
        lea     eax, [.inmem]
        invoke  SendMessageA, [esi+TOpenFile.hEditor], _CEM_GETTEXT, 0, eax
        test    eax, eax
        jnz     .errorsave

        stdcall StrPtr, [esi+TOpenFile.hFileName]
        stdcall SaveBinaryFile, eax, [.inmem.ptrBuffer], [.inmem.fileSize]
        jc      .errorsave

        mov     [esi+TOpenFile.fNeverSaved], 0   ; Mark it as saved at least once.

        xor     eax, eax
        push    eax eax eax eax
        invoke  SendMessageA, [esi+TOpenFile.hEditor], EM_EMPTYUNDOBUFFER  ; remaining arguments are in stack.
        invoke  SendMessageA, [esi+TOpenFile.hEditor], _CEM_SETMODIFIED
        jmp     .free

.errorsave:
        mov     [.res], 0
        stdcall ErrorMessage, eax

.free:
        cmp     [.inmem.ptrBuffer], 0
        je      .finish

        stdcall FreeMem, [.inmem.ptrBuffer]

.finish:
        mov     eax, [.res]
        pop     esi
        return
endp









;--------------------------------------------------
; Close the file and removes it from its editor.
; Returns:
;   0: file is closed successfully
;   1: file is closed and TOpenFile structure was destroyed.
;   2: some error
;   3: CANCEL button was pressed on the save dialog.
;--------------------------------------------------
proc CloseFile, .ptrFile
begin
        push    esi

        mov     esi, [.ptrFile]
        test    esi, esi
        jz      .fault

        cmp     [esi+TOpenFile.hEditor], 0
        je      .checkproj

        stdcall GetModified, esi
        test    eax, eax
        je      .saveok

        stdcall StrDup, cNotSaved1
        push    eax
        stdcall StrCat, eax, [esi+TOpenFile.hFileName]
        stdcall StrCat, eax, cNotSaved2
        stdcall StrPtr, eax

        invoke  MessageBoxA, [hApplication], eax, cTitleWarning, MB_YESNOCANCEL or MB_ICONQUESTION
        stdcall StrDel ; from the stack
        cmp     eax, IDNO
        je      .saveok

        cmp     eax, IDCANCEL
        je      .cancel

        stdcall SaveFile, esi

.saveok:
        invoke  DestroyWindow, [esi+TOpenFile.hEditor]
        mov     [esi+TOpenFile.hEditor], 0

.checkproj:
        cmp     [esi+TOpenFile.projectID], 0
        jne     .finishok

        stdcall FreeFStruct, esi
        mov     eax, cfrDestroyed
        pop     esi
        return

.finishok:
        xor     eax, eax
        mov     al, cfrClosed
        pop     esi
        return

.fault:
        xor     eax, eax
        mov     al, cfrFault
        pop     esi
        return

.cancel:
        xor     eax, eax
        mov     al, cfrCanceled
        pop     esi
        return
endp

iglobal
  cTitleWarning text 'Warning!'
  cNotSaved1  text 'The file "'
  cNotSaved2  text '" is not saved.', 13, 10,         \
                     'Do you want to save it now?'
endg



proc FocusFile, .ptrFile
begin
        push    esi

        mov     esi, [.ptrFile]
        test    esi, esi
        jz      .focusok

        cmp     [esi+TOpenFile.hEditor], 0
        jz      .finish

        invoke  SendMessageA, [esi+TOpenFile.hEditor], _CEM_FOCUSFILE, 0, 0

.focusok:
        stdcall SetCurrentFile, esi
.finish:
        pop     esi
        return
endp


proc SetCurrentFile, .ptrFile
begin
        push    [.ptrFile]
        pop     [ptrCurrentFile]
        return
endp




;----------------------------------------------------------
; Returns TRUE if the file allows some edit action,
; FALSE otherwise.
;----------------------------------------------------------
proc CanAction, .ptrFile, .action
begin
        invoke  GetFocus
        cmp     eax, [hLister]
        je      .check_action

        mov     eax, [.ptrFile]
        test    eax, eax
        jz      .finish
        mov     eax, [eax+TOpenFile.hEditor]
        test    eax, eax
        jz      .finish

.check_action:
        invoke  SendMessageA, eax, _CEM_CANACTION, 0, [.action]

.finish:
        return
endp



proc CommonAction, .ptrFile, .action
begin
        push    esi

        mov     esi, [.ptrFile]
        test    esi, esi
        jz      .finish
        cmp     [esi+TOpenFile.hEditor], 0
        je      .finish

        invoke  SendMessageA, [esi+TOpenFile.hEditor],   \
                             _CEM_EDITACTION, 0, [.action]

.finish:
        pop     esi
        return
endp

;*******************************************************
; Returns TRUE if the file is modified after loading
;*******************************************************
proc GetModified, .ptrFile
begin
        mov     eax, [.ptrFile]
        test    eax, eax
        jz      .exit

        cmp     [eax+TOpenFile.fNeverSaved], 0  ; if the file is never saved.
        jne     .finish

        mov     eax, [eax+TOpenFile.hEditor]
        test    eax, eax
        jz      .exit

        invoke  SendMessageA, eax, _CEM_GETMODIFIED, 0, 0
        return

.finish:
        xor     eax, eax
        inc     eax
.exit:
        return
endp



;*****************************************
; Returns visual properties of the file.
; eax - string handle with screen title
; edx - index of the icon in the files
;       image list.
;*****************************************
proc GetScreenProperties, .ptrFile
begin
        push    edi
        mov     edi, [.ptrFile]
        test    edi,edi
        jz      .error

        stdcall ExtractFileName, [edi+TOpenFile.hFileName]
        stdcall StrExtract, [edi+TOpenFile.hFileName], eax, -1

        mov     edx, [edi+TOpenFile.ptrType]
        mov     edx, [edx+TFileType.iFileIcon]
        cmp     [edi+TOpenFile.projectID], 0
        jne     @f
        add     edx, 8
@@:
        pop     edi
        return

.error:
        mov     eax, edi
        pop     edi
        return
endp



;-------------------------------------
; Returns ptr to TOpenFile of given
; editor. IF there is no such editor
; registered, returns NULL
;-------------------------------------
proc GetEditorFile, .hEditor
begin
        invoke  SendMessageA, [.hEditor], _CEM_GETFILE, 0, 0
        return
endp


;-----------------------------------
; Returns handle of AsmEdit window
; of the some editor. (if any)
; If editor does not contains
; AsmEdit control, returns NULL
;-----------------------------------
proc GetAsmEdit, .hEditor
begin
        invoke  SendMessageA, [.hEditor], _CEM_GETASMEDIT, 0, 0
        return
endp



proc GetFileAsmEdit, .ptrOpenFile
begin
        mov     eax, [.ptrOpenFile]
        test    eax, eax
        jz      .finish
        mov     eax, [eax+TOpenFile.hEditor]
        test    eax, eax
        jz      .finish

        invoke  SendMessageA, eax, _CEM_GETASMEDIT, 0, 0
.finish:
        return
endp




;-------------------------------------------------------
; Notifies editor, that file properties were changed
; ptrFile - TOpenFile structute of the file.
; fWho - fcEditor, fcProject, fcAll
;-------------------------------------------------------
proc FileChanged, .ptrFile, .fWho
begin
        push    ebx
        mov     ebx, [.ptrFile]
        test    ebx, ebx
        jz      .finish

        stdcall CheckFileForFree, ebx
        test    eax, eax
        jnz     .finish

        test    [.fWho], fcEditor
        jz      .notifyproject

        cmp     [ebx+TOpenFile.hEditor], 0
        je      .notifyproject

        invoke  SendMessageA, [ebx+TOpenFile.hEditor], _CEM_CHANGENOTIFY, 0, 0

.notifyproject:
        test    [.fWho], fcProject
        jz      .finish

        cmp     [eax+TOpenFile.projectID], NULL
        je      .finish

        invoke  SendMessageA, [hProjManager], PMM_FILECHANGED, eax, 0

.finish:
        pop     ebx
        return
endp

;--------------------------------------------
; Returns TRUE if the file was destroyed.
;--------------------------------------------
proc CheckFileForFree, .ptrFile
begin
        xor     eax, eax

        mov     ecx, [.ptrFile]
        jecxz   .finish

        mov     edx, [ecx+TOpenFile.hEditor]
        add     edx, [ecx+TOpenFile.projectID]
        jnz     .finish

        stdcall FreeFStruct, ecx
        xor     eax, eax
        inc     eax

.finish:
        return
endp



;---------------------------------------------------
; Enumerates all open files and calls [ptrCallBack]
; Format for callback is:
; proc MyCallBack, ptrFile, lParam
; if callback returns C=1, the enumeration stops
; and the functions returns value in eax.
;---------------------------------------------------
proc EnumOpenFiles, .ptrCallBack, .lParam
begin
        push    esi ecx

        mov     esi, [listFiles]
        mov     ecx, [esi+TArray.count]
        xor     eax, eax
        jecxz   .finish

        lea     esi, [esi+4*ecx-4+TArray.array]

.filesloop:
        push    esi ecx
        stdcall [.ptrCallBack], [esi], [.lParam]
        pop     ecx esi
        jc      .finish

        lea     esi, [esi-4]
        loop    .filesloop

.finish:
        pop     ecx esi
        return
endp

;------------------------------------------
; Returns the number of the files that are
; members of the currently open project.
;------------------------------------------
proc GetProjectFilesCount
begin
        xor     edx, edx
        stdcall EnumOpenFiles, _docountproject, 0
        mov     eax, edx
        return
endp

proc _docountproject, .ptrFile, .lParam
begin
        mov     eax, [.ptrFile]
        cmp     [eax+TOpenFile.projectID], NULL
        je      @f
        inc     edx
@@:
        clc
        return
endp



;------------------------------------------
; Returns the number of the files that are
; currently open for editing.
;------------------------------------------
proc GetEditFilesCount
begin
        xor     edx, edx
        stdcall EnumOpenFiles, _docountedit, 0
        mov     eax, edx
        return
endp


proc _docountedit, .ptrFile, .lParam
begin
        mov     eax, [.ptrFile]
        cmp     [eax+TOpenFile.hEditor], NULL
        je      @f
        inc     edx
@@:
        clc
        return
endp