waNone   = 0
waLeft   = 1
waRight  = 2
waTop    = 3
waBottom = 4
waClient = 5


        ; Global variables used from this module.
uglobal
  hMainForm       dd ?  ; MainWindow handle.
  hMainMenu       dd ?  ; handle of main menu.
  hReopenMenu     dd ?  ; handle of the reopen submenu.
  hMainToolbar    dd ?  ; handle of main toolbar
  hIml            dd ?  ; handle of image list for the toolbar/menu
  hImlGray        dd ?  ; handle of image list for disabled buttons/menu
  hDefImageBitmap dd ?

  hCfgFileName    dd ?  ; handle of the string with INI file name
endg


iglobal
  cMainTitle      text 'Fresh ', FRESH_VERSION, 0
  cMainSeparator  text ' : '
  cHintSelectTool text 'Select tool'

  cLayoutSection     text 'Layout'
  cShowPaletteKey    text 'ShowPalette'
  cShowPropertiesKey text 'ShowProperties'
;  cShowListerKey     text 'ShowScratchpad'

  Window MainForm, wtEnd, waNone, 'TForm', cMainTitle,                                  \
                   WS_CAPTION or WS_VISIBLE or WS_SIZEBOX or                            \
                   WS_SYSMENU or WS_MINIMIZEBOX or WS_MAXIMIZEBOX,                      \
                   WS_EX_CONTROLPARENT, NULL, 1, 1, 739, 600, MainWindowProc


;  macro Split type, width, pos, min, max \{
;   macro Cell name \{

  SplitStart MainLayout
    Split stVert or stJustGap or stAutosize, 2, 100, 0, 1000
      Cell cellMainToolbar                                ; main toolbar
      Split stVert or stJustGap, 2, 64, 0, 64
        Cell cellPalette                                  ; components palette
        Split stHoriz, 4, 200, 32, 600                   ; left/right pane of the window.
          Split stVert or stRelative, 4, 10000, 0, 32768  ; up - properties; down - project manager.
            Cell cellPropEditor
            Cell cellProjectManager
          Split stVert or stOriginBR or stHidden, 4, 100, 0, 600
            Split stVert or stOriginBR or stJustGap, 0, 22, 22, 22
              Split stHoriz or stOriginBR or stRelative or stHidden, 4, 8192, 0, 16384
                Cell cellEditorHost
                Cell cellLister
              Cell cellStatus
            Cell cellMessages
  SplitEnd

endg


;**************************************************
; Creates form for main window.
;**************************************************

proc InitMainWindow
begin
        push    ebx

        xor     ebx,ebx
        stdcall CreateForm, MainForm, 0
        mov     [hMainForm], ebx

; Create the tool palette
        stdcall OnReloadVCL, 0, [hMainForm]

        stdcall CfgGetInt, [hCfgFileName], cLayoutSection, cShowPaletteKey, 1
        test    eax, eax
        setnz   al
        movzx   eax, al

        push    eax eax
        invoke  ShowWindow, [hToolPalette], eax
        stdcall ActionSetCheck, actViewPalette ; from the stack
        stdcall SetCellHidden, [hMainForm], MainLayout.cellPalette ; from the stack

        stdcall CfgGetInt, [hCfgFileName], cLayoutSection, cShowPropertiesKey, 1
        test    eax, eax
        setnz   al
        movzx   eax, al

        push    eax
        invoke  ShowWindow, [hPropEditor], eax
        stdcall ActionSetCheck, actViewPropEditor ; from the stack

        stdcall __RefreshLeftPane

        pop     ebx
        return
endp




;**************************************************************************
; Main window message callback procedure
;**************************************************************************
proc MainWindowProc, .hwnd, .wmsg, .wparam, .lparam

.rect   RECT
.tci    TCITEM
.tce    TEditorTab
.tbb    TToolbarButton
;.ti     TOOLINFO
.mii    MENUITEMINFO
.msg    TFreshMsg
.str    rb 1024

begin
        dispatch [.wmsg]

.default:
        stc
        return

oncase WM_ERASEBKGND

;        DebugMsg "Main window WM_ERASEBKGND!"

        stc
        return



oncase WM_CLOSE

        stdcall OnCloseAll, 0, 0

        mov     eax, [listFiles]
        cmp     [eax+TArray.count], 0
        je      .closeit

; Cancel the close.

        xor     eax, eax
        clc
        return

.closeit:

; Save the visual layout

        invoke  IsWindowVisible, [hToolPalette]
        stdcall CfgSetInt, [hCfgFileName], cLayoutSection, cShowPaletteKey, eax

        invoke  IsWindowVisible, [hPropEditor]
        stdcall CfgSetInt, [hCfgFileName], cLayoutSection, cShowPropertiesKey, eax

; and quit

        invoke  PostQuitMessage
        stc
        return


;----- FM_ONIDLE -------------------------------------

oncase FM_ONIDLE
        stdcall OnIdle
        clc
        return


;-----WM_INITMENUPOPUP--------------------------------

oncase WM_INITMENUPOPUP

        mov     eax, [.wparam]
        cmp     eax, [hReopenMenu]
        jne     .qtrue

        stdcall FillMRUMenu, [.wparam], [ptrMRUProj], FirstMRU, 1
        stdcall FillMRUMenu, [.wparam], [ptrMRUFiles], FirstMRU, 2
        jmp     .qfalse

;---- WM_SETTEXT -------------------------------------

oncase WM_SETTEXT

        stdcall StrDup, cMainTitle
        mov     ebx, eax

        cmp     [.lparam], 0
        je      .setit

        stdcall StrCat, ebx, cMainSeparator

        stdcall WideCharToUtf8, [.lparam]
        stdcall StrCat, ebx, eax
        stdcall StrDel, eax

.setit:
        stdcall utf8ToWideChar, ebx
        push    eax

        invoke  DefWindowProcW, [.hwnd], WM_SETTEXT, 0, eax
        stdcall FreeMem ; from the stack
        clc
        return


;--- WM_NOTIFY ------------------------------------------------

oncase WM_NOTIFY

        mov     edi, [.lparam]
        mov     ebx, [edi+NMHDR.code]
        call    JumpTo
        MessageList                             \
            TTN_NEEDTEXTW,   .tooltipneedtext,  \
            TCN_SELCHANGE,   .tab_selchange,    \
            TCN_SELCHANGING, .tab_selchanging,  \
            TBN_DROPDOWN,    .dropdown
        jmp     .default

; Opens drop-down menu for reopen files.
.dropdown:
        lea     ebx, [.rect]
        invoke  SendMessageW, [edi+NMHDR.hwndFrom], TB_COMMANDTOINDEX, [edi+NMTOOLBAR.iItem], 0
        invoke  SendMessageW, [edi+NMHDR.hwndFrom], TB_GETITEMRECT, eax, ebx
        invoke  ClientToScreen, [edi+NMHDR.hwndFrom], ebx
        add     ebx, 8
        invoke  ClientToScreen, [edi+NMHDR.hwndFrom], ebx
        invoke  TrackPopupMenu, [hReopenMenu], TPM_LEFTALIGN, [.rect.left], [.rect.bottom], 0, [.hwnd], NULL
        jmp     .qfalse


.tooltipneedtext:

; Get hint text for toolbars.

        cmp     [edi+NMHDR.idFrom], FirstID
        jae     .maintoolbar

; it is a toolbar from the component palette.

        invoke  SendMessageW, [hToolPalette], TCM_GETCURSEL, 0, 0
        mov     [.tci.mask], TCIF_PARAM
        lea     ebx, [.tci]
        invoke  SendMessageW, [hToolPalette], TCM_GETITEMW, eax, ebx

        lea     eax, [.tbb]
        mov     ecx, [edi+NMHDR.idFrom]
        inc     ecx                             ; index of the button is ID+1, because of the separator.

        invoke  SendMessageW, [.tci.lParam], TB_GETBUTTON, ecx, eax

        mov     ecx, cHintSelectTool
        mov     eax, [.tbb.dwData]
        and     eax, $7fffffff
        test    eax, eax
        jz      @f

        mov     ecx, [eax+TDesignTimeInfo.ControlHint]
@@:
        lea     eax, [edi+TOOLTIPTEXTW.char]
        mov     [edi+TOOLTIPTEXTW.lpszText], eax

        invoke  MultiByteToWideChar, CP_UTF8, 0, ecx, -1, eax, 78

        mov     [edi+TOOLTIPTEXTW.hinst], 0
        jmp     .qfalse


.maintoolbar:

        mov     ebx, [edi+NMHDR.idFrom]
        sub     ebx, FirstID
        stdcall GetHintText, MainActionList, ebx

        stdcall StrDupMem, eax
        mov     esi, eax

        stdcall StrCharCat, esi, $0a0d
        stdcall StrCharCat, esi, "["

        imul    ebx, sizeof.TAction
        lea     ecx, [.str]
        stdcall AccelToStr, [MainActionList + ebx + TAction.ptrAccel], ecx

        lea     ecx, [.str]
        stdcall StrCat, esi, ecx
        stdcall StrCharCat, esi, "]"

        stdcall StrPtr, esi
        lea     ecx, [edi+TOOLTIPTEXTW.char]
        mov     [edi+TOOLTIPTEXTW.lpszText], ecx
        invoke  MultiByteToWideChar, CP_UTF8, 0, eax, -1, ecx, 78

        stdcall StrDel, esi

        mov     [edi+TOOLTIPTEXTW.hinst], 0
        jmp     .qfalse


; TAB control notifications.

.tab_selchange:

        mov     eax, [edi+NMHDR.hwndFrom]
        cmp     eax, [hToolPalette]
        je      .plt_selchange

        cmp     eax, [hEditorsHost]
        je      .edt_selchange

        jmp     .qfalse

.tab_selchanging:

        mov     eax, [edi+NMHDR.hwndFrom]
        cmp     eax, [hToolPalette]
        je      .plt_selchanging

        cmp     eax, [hEditorsHost]
        je      .edt_selchanging

        jmp     .qfalse


.edt_selchanging:

;        DebugMsg "Editors host, selection changing!"

        invoke  SendMessageW, [hEditorsHost], TCM_GETCURSEL, 0, 0
        cmp     eax, -1
        je      .qfalse

        lea     ebx, [.tce]
        mov     [.tce.mask], TCIF_PARAM
        invoke  SendMessageW, [hEditorsHost], TCM_GETITEMW, eax, ebx

;        stdcall AttachToCell, [.tce.hEditor], [hEditorsHost], 0

uglobal
  hEditorToHide dd ?
endg

; the idea here is to hide the current editor later in order to reduce the flicker.
        push    [.tce.hEditor]
        pop     [hEditorToHide]
        jmp     .qfalse



.edt_selchange:

        invoke  SendMessageW, [hEditorsHost], TCM_GETCURSEL, 0, 0
        cmp     eax, -1
        je      .qfalse

        mov     ebx, eax
        lea     ecx, [.tce]
        mov     [.tce.mask], TCIF_PARAM
        invoke  SendMessageW, [hEditorsHost], TCM_GETITEMW, ebx, ecx

        invoke  SendMessageW, [edi+NMHDR.hwndFrom], SGM_REALIGN, 0, 0
        stdcall AttachToCell, [.tce.hEditor], [hEditorsHost], EditorLayout.cellEditor
        invoke  ShowWindow, [.tce.hEditor], SW_SHOW

        mov     ecx, [hEditorToHide]
        jecxz   .hideok

        cmp     ecx, [.tce.hEditor]
        je      .hideok

        invoke  ShowWindow, [hEditorToHide], SW_HIDE

.hideok:
        mov     [hEditorToHide], 0

;        invoke  SetFocus, 0                             ; work around for ASMEDIT bug (highly obscure)
        invoke  SetFocus, [.tce.hEditor]

        stdcall GetEditorFile, [.tce.hEditor]
        mov     ebx, eax
        stdcall SetCurrentFile, ebx
        jmp     .qfalse



; Tool palette tab control, selection changed.
.plt_selchange:
        invoke  SendMessageW, [edi+NMHDR.hwndFrom], SGM_REALIGN, 0, 0

        invoke  SendMessageW, [edi+NMHDR.hwndFrom], TCM_GETCURSEL, 0, 0
        mov     [.tci.mask], TCIF_PARAM
        lea     ebx, [.tci]
        invoke  SendMessageW, [edi+NMHDR.hwndFrom], TCM_GETITEMW, eax, ebx

        invoke  ShowWindow, [.tci.lParam], SW_SHOWNORMAL
        stdcall AttachToCell, [.tci.lParam], [hToolPalette], PaletteLayout.cellPalette
        invoke  SendMessageW, [.tci.lParam], TB_CHECKBUTTON, 0, TRUE
        jmp     .qfalse

.plt_selchanging:
        invoke  SendMessageW, [edi+NMHDR.hwndFrom], TCM_GETCURSEL, 0, 0
        lea     ebx, [.tci]
        mov     [.tci.mask], TCIF_PARAM
        invoke  SendMessageW, [edi+NMHDR.hwndFrom], TCM_GETITEMW, eax, ebx

        stdcall AttachToCell, [.tci.lParam], [hToolPalette], 0
        invoke  ShowWindow, [.tci.lParam], SW_HIDE
        jmp     .qfalse



;--------- AM_INITWINDOW -------------------------------------------

oncase AM_INITWINDOW

; Create string with the filename of the INI file.

        stdcall GetMem, 4096
        mov     ebx, eax

        invoke  GetModuleFileNameW, NULL, ebx, 2048

        stdcall WideCharToUtf8, ebx
        stdcall FreeMem, ebx
        push    eax

        stdcall StrChangeExt, eax, txt '.cfg'
        stdcall StrDel ; from the stack

        mov     [hCfgFileName], eax

        mov     [procCfgMatchPattern], StrMatchPatternNoCase

; Set the main splitgrid

        stdcall SetSplitGrid, [.hwnd], MainLayout

; Create image lists for toolbar and menus
        stdcall ImageList_LoadGif, [hInstance], resBmpAll, 16, FALSE
        mov     [hIml], eax

        stdcall ImageList_LoadGif, [hInstance], resBmpAll, 16, TRUE
        mov     [hImlGray],eax

; Create main menu
        stdcall CreateCoolMenu, MainMenu, FALSE
        mov     [hMainMenu], eax
        invoke  SetMenu, [.hwnd], [hMainMenu]

        invoke  GetSubMenu, [hMainMenu], 0      ; Get file menu
        invoke  GetSubMenu, eax, 3              ; Get reopen menu
        mov     [hReopenMenu], eax

; Create the main toolbar
        stdcall CreateCoolToolbar, MainActionList, MainToolbar, [.hwnd], $2000, [hIml], [hImlGray]
        mov     [hMainToolbar],eax

        stdcall AttachToCell, [hMainToolbar], [.hwnd], MainLayout.cellMainToolbar
        stdcall AttachToCell, [hMainToolbar], [.hwnd], 0

; Set Main window icon.
        invoke  LoadImageW, [hInstance], resAppIcon, IMAGE_ICON, 0, 0, 0
        invoke  SendMessageW, [.hwnd], WM_SETICON, ICON_SMALL, eax

        invoke  LoadImageW, [hInstance], resAppIcon, IMAGE_ICON, 0, 0, 0
        invoke  SendMessageW, [.hwnd], WM_SETICON, ICON_BIG, eax

; Init of the windows and systems in the application...

        mov     [passes_limit], $80

        stdcall InitEditorHost, [.hwnd]
        stdcall InitMessageWindow, [.hwnd]
        stdcall CheckParams

        stdcall InitSourceEditor  ; Create source editor.
        stdcall InitDumperWindow, [frmMsg]
        stdcall InitListerWindow, [.hwnd]

        stdcall InitPropEditor, [.hwnd]         ; Create property editor
        stdcall InitProjectManager              ; Create project manager

        stdcall InitFileManager

        stdcall InitFindOptions
        stdcall InitHelp


        jmp     .qfalse



;---------- WM_DESTROY ------------------------------------

oncase WM_DESTROY

        cmp     [comp_handle], 0
        je      @f

        invoke  TerminateThread, [comp_handle], 0
        invoke  CloseHandle, [comp_handle]
        mov     [comp_handle], 0
@@:
        invoke  DestroyWindow, [hEditorsHost]
        stdcall FinalizeSourceEditor
        stdcall FinalizeProjectManager
        stdcall CloseFileManager

        stdcall DestroyToolPalette

        stdcall DestroyLabelsTree, [ptrLabels]
        mov     [ptrLabels], 0

        stdcall ClearDebugInfo
        stdcall FreePreprocessed

        invoke  DestroyWindow, [hFindHistory]

        invoke  ImageList_Destroy,[hIml]
        invoke  ImageList_Destroy,[hImlGray]

        invoke  SendMessageW, [.hwnd], WM_GETICON, TRUE, 0
        invoke  DestroyIcon, eax
        invoke  SendMessageW, [.hwnd], WM_GETICON, FALSE, 0
        invoke  DestroyIcon, eax

        invoke  DeleteObject, [hDefImageBitmap]
        invoke  DestroyMenu, [hMainMenu]

        stdcall StrDel, [hCfgFileName]

        jmp     .qfalse

;---------- WM_COMMAND -----------------------

oncase WM_COMMAND

; Return the control to the last window if the command is invoked from
; main window toolbar.

;        DebugMsg "WM_COMMAND message"

        movzx   esi,word [.wparam]
        cmp     esi, FirstID
        jl      .maybeMRU

        sub     esi,FirstID
        cmp     esi,[MainActionList.Number]
        jge     .default

        imul    esi,sizeof.TAction
        add     esi,MainActionList

        xor     eax,eax
        cmp     [esi+TAction.OnExecute],eax
        je      .qfalse

        stdcall [esi+TAction.OnExecute], [.wparam], [.lparam]
        jmp     .qtrue

.maybeMRU:
        sub     esi, FirstMRU
        js      .default

        invoke  GetMenuItemCount, [hReopenMenu]
        cmp     esi, eax
        jge     .default

        mov     [.mii.cbSize], sizeof.MENUITEMINFO
        mov     [.mii.fMask], MIIM_TYPE
        mov     [.mii.fType], MFT_STRING
        lea     ebx, [.str]
        mov     [.mii.dwTypeData], ebx
        mov     [.mii.cch], 512

        lea     eax, [.mii]
        invoke  GetMenuItemInfoW, [hReopenMenu], esi, TRUE, eax
        test    eax, eax
        jz      .default

        stdcall WideCharToUtf8, ebx
        push    eax

        stdcall OpenFileByName, eax, NULL, TRUE       ; inteligent open project/file.
        stdcall StrDel ; from the stack.
        jmp     .qtrue

.qfalse:
        xor     eax,eax
        clc
        return

.qtrue:
        xor     eax,eax
        inc     eax
        clc
        return

;----------------------------------------------------------------------------------------------------
;      DEBUGGER MESSAGES.
;----------------------------------------------------------------------------------------------------

oncase DM_STATUSCHANGED

        mov     ecx, cStatusRunning
        cmp     [dbgStatus], dsRunning
        je      .statusok
        mov     ecx, cStatusPaused
        cmp     [dbgStatus], dsPaused
        je      .statusok
        mov     ecx, cStatusTerminated
        cmp     [dbgStatus], dsFinished
        je      .statusok
        mov     ecx, cStatusUnknown

.statusok:
        invoke  SendMessageW, [hStatus], SB_SETTEXTW, 5, ecx
        clc
        return


iglobal
  cStatusRunning    du  ' Running...', 0
  cStatusPaused     du  ' Paused', 0
  cStatusTerminated du  ' Finished', 0
  cStatusUnknown    du  ' Unknown', 0
endg


oncase DM_EVENTRAISED

        cmp     [.wparam], 0
        jne     .exception

        mov     esi, [dbgEvent.dwDebugEventCode]
        cmp     esi, 9
        jbe     @f
        xor     esi, esi
@@:
        stdcall [TblDebugEvents+4*esi]
        test    eax, eax
        jz      .loggingOK

        lea     edi, [.msg]
        mov     [edi+TFreshMsg.type], mtDebug
        mov     [edi+TFreshMsg.hMessage], eax
        mov     [edi+TFreshMsg.link.hFileName], 0

        invoke  SendMessageW, [frmMsg], MWM_ADDMESSAGE, edi, TVI_ROOT
        stdcall StrDel, [edi+TFreshMsg.hMessage]

.loggingOK:
        cmp     esi, EXCEPTION_DEBUG_EVENT
        je      .exception

        cmp     esi, CREATE_PROCESS_DEBUG_EVENT
        je      .createprocess

        cmp     esi, EXIT_PROCESS_DEBUG_EVENT
        je      .exitprocess

.continue:
        mov     eax, dbgcContinue
        clc
        return


;--------- Exception debug event ------------------------
.exception:
        mov     [dbgContext.ContextFlags], CONTEXT_FULL
        invoke  GetThreadContext, [dbgPInfo.hThread], dbgContext

        invoke  SendMessageW, [hPropEditor], PRM_UPDATEPROP, 0, 0

        stdcall FindAddressPosition, [dbgContext.regEip]
        test    eax,eax
        jz      .unknownposition

        mov     [LastKnownLine], eax
        stdcall PosEditor, [eax+TDebugLine.ptrFile], [eax+TDebugLine.LineNum]
        invoke  SendMessageW, [hLister], LM_SHOWLIST, eax, 0

        invoke  ShowWindow, [hPropEditor], SW_SHOW

        xor      eax, eax
        clc
        return

.unknownposition:
        invoke  ShowWindow, [hPropEditor], SW_HIDE

        mov     eax, dbgcContinue
        cmp     [dbgEvent.Exception.ExceptionRecord.ExceptionCode], EXCEPTION_BREAKPOINT
        je      @f
        mov     eax, dbgcContinueNotHandled   ; Pass these kind of exceptions to the code.
@@:
        clc
        return


.createprocess:
        invoke  SendMessageW, [hPropEditor], PEM_SETCONTROL, dbgContext, DebuggerProperties
        invoke  SendMessageW, [hPropEditor], PEM_SETUPDATEPROC, 0, UpdateThreadContext

        invoke  SendMessageW, [hLister], LM_SHOW, SW_SHOWNORMAL, 0
        invoke  SendMessageW, [Dumper.hwnd], DMM_SHOW, SW_SHOWNORMAL, 0

        mov     eax, [dbgEvent.CreateProcessInfo.hFile]
        mov     [hDebugFileImage], eax
        mov     eax, dbgcContinue
        clc
        return

.exitprocess:
        invoke  CloseHandle, [hDebugThread]
        mov     [hDebugThread], 0

        invoke  CloseHandle, [hDebugFileImage]
        mov     [hDebugFileImage], 0

        invoke  SendMessageW, [hPropEditor], PEM_SETCONTROL, 0, 0

        invoke  ShowWindow, [hPropEditor], SW_SHOW

        invoke  SendMessageW, [hLister], WM_SETTEXT, 0, 0
        invoke  SendMessageW, [hLister], LM_SHOW, SW_HIDE, 0
        invoke  SendMessageW, [Dumper.hwnd], DMM_SHOW, SW_HIDE, 0

        mov     eax, dbgcFinish
        clc
        return


        enddispatch

endp




