uglobal
  frmMsg        dd 0                        ; Messages window.
  hSplitterMsg  dd 0
  tvMessagesWin dd 0
  fDisableLinks dd 0
endg


iglobal
  cMessagesTitle  du 'Fresh messages.',0

  property propLastMessageSize, "LastMsgWinSize"

  SplitStart MsgLayout
    Cell cellMsgTree
  SplitEnd

endg



proc InitMessageWindow, .hParent
begin
        xor     ebx, ebx
        invoke   CreateWindowExW, WS_EX_CONTROLPARENT, cFormClassName, cMessagesTitle,                  \
                 WS_VISIBLE or WS_CHILD or WS_TABSTOP or WS_CLIPSIBLINGS or WS_CLIPCHILDREN,            \
                 ebx, ebx , 100, 100,                                                                   \
                 [.hParent],                                                                            \
                 ebx, [hInstance], ebx                                                                  \

        mov     [frmMsg], eax
        stdcall SubclassWindow, eax, MsgWindowProc
;        invoke  SendMessageW, [frmMsg], MWM_CLEARMESSAGES, 0, 0

        return
endp





proc MsgWindowProc, .hwnd, .wmsg, .wparam, .lparam
.tvi    TVINSERTSTRUCT
begin

        dispatch [.wmsg]

;        call    JumpTo
;        MessageList                             \
;            AM_INITWINDOW,      .aminitwindow,  \
;            WM_NOTIFY,          .notify,        \
;            MWM_CLEARMESSAGES,  .clearmessages, \
;            MWM_SHOWMESSAGES,   .showmessages,  \
;            MWM_ADDMESSAGE,     .addmessage,    \
;            MWM_FIRSTERROR,     .openfirsterror,\
;            WM_SETFOCUS,        .setfocus,      \
;            WM_COMMAND,         .command

.ondefault:
        stc
        return


oncase WM_COMMAND

;        DebugMsg "WM_COMMAND to the message window!"
;        OutputValue "wparam = ", [.wparam], 16, 8
;        OutputValue "lparam = ", [.lparam], 16, 0

        cmp     word [.wparam], IDOK
        je      .gotolink_fromuser

        jmp     .ondefault


; ---------- WM_SETFOCUS ------------------------------

oncase WM_SETFOCUS

        invoke  SetFocus, [tvMessagesWin]

        xor     eax, eax
        clc
        return


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

oncase AM_INITWINDOW

        xor     ebx,ebx

        stdcall SetSplitGrid, [.hwnd], MsgLayout

        invoke  GetAncestor, [.hwnd], GA_PARENT
        stdcall AttachToCell, [.hwnd], eax, MainLayout.cellMessages

        invoke  CreateWindowExW, WS_EX_CLIENTEDGE, cTreeViewClassName, ebx,                     \
                WS_VISIBLE or WS_CHILD or WS_VSCROLL or WS_TABSTOP or WS_CLIPSIBLINGS or        \
                TVS_DISABLEDRAGDROP or TVS_SHOWSELALWAYS or TVS_HASBUTTONS or                   \
                TVS_LINESATROOT or TVS_HASLINES,                                                \
                ebx, ebx, 100, 100,                                                             \
                [.hwnd], ebx, [hInstance], ebx

        mov     esi, eax
        mov     [tvMessagesWin], eax

        stdcall SubclassWindow, esi, MsgTreeWinProc
        stdcall AttachToCell, esi, [.hwnd], MsgLayout.cellMsgTree

        stdcall ImageList_LoadGif, [hInstance], resBmpMessage, 14, FALSE
        invoke  SendMessageW, esi, TVM_SETIMAGELIST, TVSIL_NORMAL, eax

        clc
        return

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

oncase WM_NOTIFY

        mov     esi, [.lparam]

        cmp     [esi+NMHDR.code], TVN_DELETEITEMW
        je      .delitem

        cmp     [esi+NMHDR.code], TVN_SELCHANGEDW
        je      .selchanged

        cmp     [esi+NMHDR.code], TVN_KEYDOWN
        jne     .qfalse

; TVN_KEYDOWN
        cmp     [esi+TVKEYDOWN.wVKey], VK_SPACE
        jne     .qfalse

        mov     eax, [esi+NMHDR.hwndFrom]
        cmp     eax, [tvMessagesWin]
        jne     .qfalse


locals
  .lastfocus dd ?
endl

.gotolink_fromuser:
        invoke  SendMessageW, [tvMessagesWin], TVM_GETNEXTITEM, TVGN_CARET, NULL
        mov     [.tvi.item.hItem], eax
        mov     [.tvi.item.mask], TVIF_PARAM
        lea     eax, [.tvi.item]
        invoke  SendMessageW, [tvMessagesWin], TVM_GETITEMW, 0, eax
        mov     edi, [.tvi.item.lParam]

        invoke  SetFocus, [hEditorsHost]
        jmp     .gotolink

.selchanged:
        cmp     [fDisableLinks], 0
        jne     .qfalse

        test    [esi+NMTREEVIEW.itemNew.state], TVIS_SELECTED
        jz      .qfalse

        mov     edi, [esi+NMTREEVIEW.itemNew.lParam]

.gotolink:
        test    edi, edi
        jz      .qfalse

        invoke  GetFocus
        mov     [.lastfocus], eax

        stdcall PosEditor, [edi+TFileLine.hFileName], [edi+TFileLine.pos.selectionLine]

; take the focus back
        mov     eax, [.lastfocus]
        cmp     eax, [tvMessagesWin]
        jne     .qfalse

        invoke  SetFocus, [tvMessagesWin]
        jmp     .qfalse

;..............................................................

.delitem:
        mov     edi, [esi+NMTREEVIEW.itemOld.lParam]
        test    edi, edi
        jz      .qfalse

        stdcall StrDel, [edi+TFileLine.hFileName]
        stdcall FreeMem, edi

        jmp     .qfalse

;.checkvisible:
;        invoke  SendMessageW, [tvMessagesWin], TVM_GETCOUNT, 0, 0
;        cmp     eax, 1
;        ja      .qfalse
;        jmp     .hidemsgwnd

;---------- MWM_SHOWMESSAGES --------------------------------

locals
  .rect RECT
endl

oncase MWM_SHOWMESSAGES

        mov     esi, SW_SHOWNORMAL

        cmp     [.wparam], 0
        jne     .doshow

.hidemsgwnd:
        mov     esi, SW_HIDE

.doshow:
        invoke  ShowWindow, [.hwnd], esi
        stdcall SetCellHidden, [hMainForm], MainLayout.cellMessages, esi
        stdcall SetAutoHideTimer
        jmp     .qfalse


;---------- MWM_ADDMESSAGE ----------------------------------

oncase MWM_ADDMESSAGE

        cmp     [flagFakeCompile], 0
        jne     .qfalse

        mov     esi, [.wparam]
        test    esi, esi
        jz      .qfalse

        lea     edi, [.tvi]
        mov     ecx, sizeof.TVINSERTSTRUCT / 4
        xor     eax, eax
        rep stosd

        mov     eax, [.lparam]
        mov     [.tvi.hParent], eax
        mov     [.tvi.hInsertAfter], TVI_LAST
        mov     [.tvi.item.mask], TVIF_IMAGE or TVIF_PARAM or TVIF_SELECTEDIMAGE or TVIF_TEXT

        mov     eax, [esi+TFreshMsg.type]
        mov     [.tvi.item.iImage], eax
        mov     [.tvi.item.iSelectedImage], eax

        stdcall utf8ToWideChar, [esi+TFreshMsg.hMessage]
        mov     [.tvi.item.pszText], eax

        mov     edi, [esi+TFreshMsg.link.hFileName]
        test    edi, edi
        jz      .skiplink

        stdcall GetMem, sizeof.TFileLine
        mov     edi, eax

        stdcall StrDup, [esi+TFreshMsg.link.hFileName]
        mov     [edi+TFileLine.hFileName], eax

        mov     eax, [esi+TFreshMsg.link.pos.caretLine]
        mov     ecx, [esi+TFreshMsg.link.pos.caretPosition]
        mov     [edi+TFileLine.pos.caretLine], eax
        mov     [edi+TFileLine.pos.caretPosition], ecx

        mov     eax, [esi+TFreshMsg.link.pos.selectionLine]
        mov     ecx, [esi+TFreshMsg.link.pos.selectionPosition]
        mov     [edi+TFileLine.pos.selectionLine], eax
        mov     [edi+TFileLine.pos.selectionPosition], ecx

.skiplink:
        mov     [.tvi.item.lParam], edi

        lea     eax, [.tvi]
        invoke  SendMessageW, [tvMessagesWin], TVM_INSERTITEMW, 0, eax
        stdcall FreeMem, [.tvi.item.pszText]

        push    eax

        invoke  SendMessageW, [tvMessagesWin], TVM_ENSUREVISIBLE, 0, eax
        invoke  SendMessageW, [tvMessagesWin], TVM_EXPAND, TVE_EXPAND, [.tvi.hParent]

        invoke  GetWindowLongW, [.hwnd], GWL_STYLE
        test    eax, WS_VISIBLE
        jnz     .endadd

        invoke  PostMessageW, [.hwnd], MWM_SHOWMESSAGES, 1, 0

.endadd:
        call SetAutoHideTimer

        pop     eax
        clc
        return


;----------- MWM_FIRSTERROR --------------------------

oncase MWM_FIRSTERROR

        mov     ebx, TVI_ROOT

.loopchild:
        invoke  SendMessageW, [tvMessagesWin], TVM_GETNEXTITEM, TVGN_CHILD, ebx
        test    eax, eax
        jz      .notfound

        lea     esi, [.tvi.item]
        mov     [.tvi.item.mask], TVIF_IMAGE or TVIF_PARAM

.itemsloop:
        mov     ebx, eax
        mov     [.tvi.item.hItem], ebx

        invoke  SendMessageW, [tvMessagesWin], TVM_GETITEMW, 0, esi
        cmp     [.tvi.item.iImage], mtError
        je      .found

.next:
        invoke  SendMessageW, [tvMessagesWin], TVM_GETNEXTITEM, TVGN_NEXT, ebx
        test    eax, eax
        jnz     .itemsloop

.notfound:
        mov     eax, TRUE
        clc
        return

.found:
        mov     edi, [.tvi.item.lParam]
        test    edi, edi
        jz      .next

        invoke  SendMessageW, [tvMessagesWin], TVM_SELECTITEM, TVGN_CARET, ebx
        jmp     .qfalse


;----------- MWM_CLEARMESSAGES ----------------------

oncase MWM_CLEARMESSAGES

        mov     [blockAutoHide], 0

        invoke  SendMessageW, [tvMessagesWin], TVM_GETCOUNT, 0, 0
        test    eax, eax
        jz      .hidemsgwnd

        mov     [fDisableLinks], TRUE
        invoke  SendMessageW, [tvMessagesWin], TVM_DELETEITEM, 0, TVI_ROOT
        mov     [fDisableLinks], FALSE

.qfalse:
        xor     eax, eax
        clc
        return


        enddispatch

endp



iglobal
  idCloseTimer dd 0
endg


proc MsgTreeWinProc, .hwnd, .wmsg, .wparam, .lparam
begin

        mov     ebx, [.wmsg]
        dispatch ebx

.ondefault:
        stc
        return

oncase WM_SETFOCUS
        call    KillAutoHideTimer
        stc
        return

oncase WM_KILLFOCUS
        call    SetAutoHideTimer
        stc
        return

oncase WM_TIMER
        mov     eax, [.wparam]
        cmp     eax, 101
        jne     .ondefault

        call    KillAutoHideTimer
        invoke  PostMessageW, [frmMsg], MWM_SHOWMESSAGES, 0, 0
        clc
        return

        enddispatch
endp


proc KillAutoHideTimer
begin
        cmp     [idCloseTimer],0
        je      .exit
        invoke  KillTimer, [tvMessagesWin], 101
        mov     [idCloseTimer], 0
.exit:
        return
endp

proc SetAutoHideTimer
begin
        call    KillAutoHideTimer
        cmp     [flagAutoHide], 0
        je      .exit
        cmp     [blockAutoHide], 0
        jne     .exit

        invoke  IsWindowVisible, [frmMsg]
        test    eax, eax
        jz      .exit

        invoke  SetTimer, [tvMessagesWin], 101, [timeAutoHide], 0
        mov     [idCloseTimer], eax

.exit:
        return
endp
