uglobal
  hEditorMenu     dd 0                        ; source popup menu item.
  hBookmarkIcon   dd 0
  CurrentSettings dd  ?
endg

iglobal


defaultAETHEME AETHEME $0, $000000, $ffffff, $ffffff, $800000,  \  ; synproc, text_color,        text_background,  sel_text,     sel_background
                           $c0c0c0, $808080, $000014, $000004,  \  ;          margin_background, margin_border,    margin_width, margin_gap
                           $ffffff, $008000, $c0c0c0, $ffffff,  \  ;          focus_color,       focus_background, rdonly_color, rdonly_background
                           $000000, $a000a0, $0080ff, $808080,  \  ; syntax colors 0..3
                           $808000, $ff0000, $800000, $008000,  \  ; syntax colors 4..7
                           $000000, $000000, $000000, $000000,  \  ; reserved syntax colors 8..11
                           $000000, $000000, $000000, $000000,  \  ; reserved syntax colors 12..15
                           $000000, $000000, $000000, $000000,  \  ; reserved syntax colors 16..19
                           $000000, $000000, $000000, $000000   \  ; reserved syntax colors 20..23


CoolMenu EditorPopup,                   \
    mfNormal, actGotoDefinition,        \
    mfNormal, actGotoInterface,         \
    mfNormal, actCrossReference,        \
    mfNormal, actUnrollMacro,           \
    mfNormal, actOpenFileAtCursor,      \
    mfNormal, actInclude,               \
    mfSeparator, NONE,                  \
    mfNormal, actCut,                   \
    mfNormal, actCopy,                  \
    mfNormal, actPaste,                 \
    mfSeparator, NONE,                  \
    mfNormal,    actIndent,             \
    mfNormal,    actOutdent,            \
    mfSeparator, NONE,                  \
    mfNormal,    actComment,            \
    mfNormal,    actUncomment,          \
    mfSeparator, NONE,                  \
    mfSubmenu, '&Bookmarks',            \
      mfNormal,    actToggleBM,         \
      mfSeparator, NONE,                \
      mfNormal,    actNextBM,           \
      mfNormal,    actPrevBM,           \
      mfSeparator, NONE,                \
      mfNormal,    actClearBM,          \
    mfEnd, END


  property propOwnerAsmEdit, "OwnerAsmEdit"

endg


CCM_UPDATECCPOS = WM_USER+$f000
CCM_UPDATEPAPOS = WM_USER+$f001


;----------------------------------------
; Creates sourceeditor window.
; Call this only once.
;----------------------------------------
proc InitSourceEditor
begin
        stdcall CreateCoolMenu, EditorPopup, TRUE
        mov     [hEditorMenu], eax

        invoke  LoadImageW, [hInstance], resBookmarkIcon, IMAGE_ICON, 0, 0, LR_SHARED
        mov     [hBookmarkIcon], eax

; Load editor color profile...
        stdcall LoadEditorSettings, [hCfgFileName], TRUE
        mov     [CurrentSettings], eax
        return
endp


proc FinalizeSourceEditor
begin
        stdcall SaveEditorSettings, [hCfgFileName], [CurrentSettings], TRUE, TRUE
        stdcall DestroySettings, [CurrentSettings]

        invoke DestroyMenu, [hEditorMenu]
        invoke DestroyIcon, [hBookmarkIcon]
        return
endp





proc CreateAsmEdit, .ptrOpenFile, .hTemplate, .SubclassProc
begin
        pushad

        mov     esi, [.ptrOpenFile]
        mov     edi, [CurrentSettings]

        xor     eax, eax
        mov     ecx, WS_CHILD or WS_HSCROLL or WS_VSCROLL or ES_NOHIDESEL or ES_WANTRETURN or WS_TABSTOP or WS_CLIPSIBLINGS
        or      ecx, [edi+TEditorSettings.AsmEditStyle]

        invoke  CreateWindowExW, WS_EX_ACCEPTFILES or WS_EX_CLIENTEDGE, cAsmEditClassName,    \
                eax, ecx, eax, eax, 640, 480, [hEditorsHost], eax,      \
                [hInstance], eax
        mov     ebx, eax
        test    eax, eax
        jz      .errorcreate

        mov     [esi+TOpenFile.hEditor], ebx

        invoke  SetPropW, ebx, [propOpenFileStructure], esi

; adjust the look and feel for the editor window.

        mov     eax, [esi+TOpenFile.ptrType]
        stdcall ApplySettingsToAsmEdit, ebx, edi, [eax+TFileType.lParam]

        invoke  SendMessageW, ebx, AEM_SETPOPUPMENU, 0, [hEditorMenu]
        invoke  SendMessageW, ebx, AEM_SETBOOKMARKICON, [hBookmarkIcon], 0

        stdcall SubclassWindow, ebx, [.SubclassProc]

        invoke  SendMessageW, ebx, CEM_LOADFILE, [.hTemplate], 0
        test    eax, eax
        jnz     .errorload

        invoke  SendMessageW, [hEditorsHost], EHM_DOCKWINDOW, ebx, 0

        clc
        mov     [esp+4*regEAX], ebx

.finish:
        popad
        return

.errorload:
        push    eax
        and     [esi+TOpenFile.hEditor], 0
        invoke  DestroyWindow, ebx
        pop     eax

.errorcreate:
        mov     [esp+4*regEAX], eax
        stc
        jmp     .finish

endp




;--------------------------------------------------------
; Creates the editor window and returns handle to it.
;--------------------------------------------------------
proc CreateSourceEditor, .ptrOpenFile, .hTemplate
begin
        push    ebx esi edi

        stdcall CreateAsmEdit, [.ptrOpenFile], [.hTemplate], SourceEditProc
        jc      .error

        xor     eax, eax
        pop     edi esi ebx
        return

.error:
        test    eax, eax
        jnz     .errorload

        invoke  GetLastError
        test    eax, eax
        jnz     .errorload

        or      eax, -1         ; general error

.errorload:
        stc
        pop     edi esi ebx
        return
endp





proc SourceEditProc, .hwnd, .wmsg, .wparam, .lparam
.aepos AEPOS
.str   rw 256
.textlen dd ?
.written dd ?
.memoryfile TInMemoryFile
begin
        invoke  GetPropW, [.hwnd], [propOpenFileStructure]
        mov     edi, eax

        mov     ebx, [.wmsg]
        dispatch ebx

.ondefault:
        stc
        return


;------- Custom message handlers ------------------

oncase WM_DESTROY
        stdcall ClosePopup, [hCCList], 0, 0
        stdcall ClosePopup, [hPAHint], 0, 0
        stc
        return


oncase _CEM_GETTEXT
        mov     ebx, [.lparam]   ; pointer to TInMemoryFile

        stdcall GetControlTextUtf8, [.hwnd]
        push    eax
        stdcall StrPtr, eax
        mov     esi, eax

        mov     ecx, [esi+string.len]
        lea     eax, [ecx + 16]
        stdcall GetMem, eax

        mov     edi, eax
        mov     [ebx+TInMemoryFile.ptrBuffer], eax
        mov     [ebx+TInMemoryFile.fileSize], ecx
        mov     [ebx+TInMemoryFile.fAscii], TRUE

        push    ecx

        shr     ecx, 2
        rep movsd

        pop     ecx
        and     ecx, 3

        rep movsb

        xor     eax, eax
        clc
        return

.errorgettext:
        mov     eax, 1
        clc
        return

;----------------------------------------------------
oncase CEM_LOADFILE
locals
  .forfree dd ?
endl

        mov     [.forfree], 0

        mov     eax, [.wparam]
        test    eax, eax
        jnz     .loadit

        cmp     [edi+TOpenFile.fNeverSaved], 0
        jne     .load_finished

; Load the file in ASMEDIT window.
        mov     eax, [edi+TOpenFile.hFileName]

.loadit:
        stdcall StrPtr, eax
        stdcall LoadBinaryFile, eax
        jc      .endload ; eax contains the error code

        mov     [.forfree], eax

        stdcall InteractivelyConvertAnsiText, eax, -1
        jc      .endload                                ; EAX contains error code.

        mov     esi, edx        ; the code page

        push    eax
        invoke  SendMessageW, [.hwnd], WM_SETTEXT, 0, eax
        stdcall FreeMem ;  address from the stack.

        stdcall AddToMRUList, [ptrMRUFiles], [edi+TOpenFile.hFileName]

        cmp     esi, CP_UTF8
        je      .load_finished

; set the file modified and to be "save as"
        mov     [edi+TOpenFile.fNeverSaved], TRUE
        invoke  SendMessageW, [.hwnd], _CEM_SETMODIFIED, TRUE, 0

.load_finished:
        invoke  GetParent, [.hwnd]
        invoke  SendMessageW, eax, EHM_FILECHANGED, edi, 0   ; Set the parameters of the tab.
        xor     eax, eax

.endload:
        stdcall FreeMem, [.forfree]
        clc
        return


;---------------------------------------------------------------------
oncase _CEM_CHANGENOTIFY

        invoke  GetParent, [.hwnd]
        invoke  SendMessageW, eax, EHM_FILECHANGED, edi, 0
        clc
        return

;---------------------------------------------------------------------
oncase _CEM_FOCUSFILE

        invoke  GetParent, [.hwnd]
        invoke  SendMessageW, eax, EHM_FOCUSWINDOW, [.hwnd], 0
        clc
        return

;---------------------------------------------------------------------
oncase _CEM_CANACTION

        mov     eax, [.lparam]
        cmp     eax, WM_CUT
        je      .checkcopycut
        cmp     eax, WM_COPY
        je      .checkcopycut
        cmp     eax, WM_CLEAR
        je      .checkcopycut
        cmp     eax, WM_UNDO
        je      .checkundo
        cmp     eax, EM_UNDO
        je      .checkundo
        cmp     eax, WM_PASTE
        je      .checkpaste
        xor     eax, eax
        clc
        return

.checkcopycut:
        lea     esi, [.aepos]
        invoke  SendMessageW, [.hwnd], AEM_GETPOS, esi, 0
        mov     eax, [esi+AEPOS.caretPosition]
        mov     ecx, [esi+AEPOS.caretLine]
        cmp     [esi+AEPOS.selectionPosition], eax
        jne     .can_copy
        cmp     [esi+AEPOS.selectionLine], ecx
        jne     .can_copy
        xor     eax, eax
        clc
        return

.can_copy:
        xor     eax, eax
        inc     eax
        clc
        return

.checkundo:
        invoke  SendMessageW, [.hwnd], EM_CANUNDO, 0, 0
        clc
        return

.checkpaste:
        invoke  IsClipboardFormatAvailable, CF_TEXT
        clc
        return

;---------------------------------------------------------------------
oncase _CEM_EDITACTION

        invoke  SendMessageW, [.hwnd], [.lparam], 0, 0
        clc
        return

;---------------------------------------------------------------------
oncase _CEM_GETMODIFIED

        invoke  SendMessageW, [.hwnd], AEM_GETMODIFIED, 0, 0
        clc
        return

;---------------------------------------------------------------------
oncase _CEM_SETMODIFIED

        invoke  SendMessageW, [.hwnd], AEM_SETMODIFIED, [.wparam], [.lparam]
        clc
        return

;---------------------------------------------------------------------
oncase _CEM_GETFILE

        mov     eax, edi
        clc
        return

;---------------------------------------------------------------------
oncase _CEM_GETASMEDIT

        mov     eax, [.hwnd]
        clc
        return

;---------------------------------------------------------------------
oncase WM_KILLFOCUS

        stdcall ClosePopup, [hPAHint], [.hwnd], [.wparam]
        stdcall ClosePopup, [hCCList], [.hwnd], [.wparam]
        stdcall ClosePopup, [hEHelp], [.hwnd], [.wparam]
        jmp     .ondefault


;---------------------------------------------------------------------
oncase CCM_UPDATEPAPOS
        stdcall UpdatePAHint
        clc
        return

oncase CCM_UPDATECCPOS
        stdcall UpdateCCPosition
        clc
        return

;-----------------------------------------------------------------------
oncase WM_LBUTTONDOWN
oncase WM_RBUTTONDOWN

        stdcall ClosePopup, [hCCList], 0, 0
        stdcall ClosePopup, [hPAHint], 0, 0

        jmp     .ondefault

;-----------------------------------------------------------------------
oncase WM_VSCROLL
oncase WM_HSCROLL
        stdcall ClosePopup, [hCCList], 0, 0
        stdcall ClosePopup, [hPAHint], 0, 0
        jmp     .ondefault


;-----------------------------------------------------------------------
oncase WM_DROPFILES
locals
  .filename rw 1024
  .drop     POINT
  .incl     dd ?
endl

iglobal
  cIncludeCommand db 'include "', 0
  cIncludeEnd     db '"', 13, 10, 0
;  cIncludeEnd2    db $0d, $0a, 0
endg

        lea     eax, [.drop]
        invoke  DragQueryPoint, [.wparam], eax

        mov     ebx, [.drop.y]
        shl     ebx, 16
        mov     bx, word [.drop.x]
        invoke  SendMessageW, [.hwnd], WM_LBUTTONDOWN, 0, ebx
        invoke  SendMessageW, [.hwnd], WM_LBUTTONUP, 0, ebx

        lea     esi, [.aepos]
        invoke  SendMessageW, [.hwnd], AEM_GETPOS, esi, 0
        mov     [esi+AEPOS.caretPosition], 1
        mov     [esi+AEPOS.selectionPosition], 1
        invoke  SendMessageW, [.hwnd], AEM_SETPOS, esi, 0

        invoke  SendMessageW, [.hwnd], AEM_GETMODE, 0, 0
        push    eax

        invoke  SendMessageW, [.hwnd], AEM_SETMODE, 0, 0

        lea     esi, [.filename]

        invoke  DragQueryFileW, [.wparam], -1, esi, 1024
        mov     ebx, eax
        xor     edi, edi

        stdcall StrNew
        mov     [.incl], eax

.opendroploop:
        invoke  DragQueryFileW, [.wparam], edi, esi, 1024
        stdcall WideCharToUtf8, esi
        push    eax

        stdcall StrCat, [.incl], cIncludeCommand

        stdcall _RelativeToFinc, eax
        stdcall StrDel ; from the stack

        stdcall StrCat, [.incl], eax
        stdcall StrDel, eax

        stdcall StrCat, [.incl], cIncludeEnd

        inc     edi
        dec     ebx
        jnz     .opendroploop

        invoke  DragFinish, [.wparam]

;        stdcall StrCat, [.incl], cIncludeEnd2
        stdcall utf8ToWideChar, [.incl]
        stdcall StrDel, [.incl]
        push    eax

        invoke  SendMessageW, [.hwnd], EM_REPLACESEL, TRUE, eax
        stdcall FreeMem ; from the stack

        pop     eax
        invoke  SendMessageW, [.hwnd], AEM_SETMODE, eax, 0

        lea     esi, [.aepos]
        invoke  SendMessageW, [.hwnd], AEM_GETPOS, esi, 0
        mov     eax, [esi+AEPOS.selectionPosition]
        mov     ecx, [esi+AEPOS.selectionLine]
        mov     [esi+AEPOS.caretPosition], eax
        mov     [esi+AEPOS.caretLine], ecx
        invoke  SendMessageW, [.hwnd], AEM_SETPOS, esi, 0

        xor     eax, eax
        clc
        return


;-----------------------------------------------------------------------
oncase WM_KEYDOWN
;        invoke  PostMessageA, [.hwnd], CCM_UPDATEPAPOS, 0, 0

        cmp     [hCCList], 0
        je      .maybeopen

        mov     ebx, [.wparam]
        call    JumpTo
        MessageList                                      \
          VK_DOWN,   .sendtocc,                          \
          VK_UP,     .sendtocc,                          \
          VK_PRIOR,  .sendtocc,                          \
          VK_NEXT,   .sendtocc,                          \
          VK_HOME,   .sendtocc,                          \
          VK_END,    .sendtocc,                          \
          VK_LEFT,   .closekey,                          \
          VK_RIGHT,  .closekey,                          \
          VK_RETURN, .inserttext

        invoke MapVirtualKeyW, [.wparam], 2
        test   eax, eax
        jz     .ondefault

        cmp     ax, ' '
        je      .closekey

        push    eax

        cmp     ax, '-'
        jne     @f

        invoke  GetKeyState, VK_SHIFT
        test    ax, ax
        jns     @f

        mov     dword [esp], '_'

@@:
        pop     eax

        call    AsmEdit.recognize_character
        jnc     .endchar     ; if nor separator char.

; if separator character.

        call    .insert_text_proc      ; this approach makes problem when one wants to type sequence of dot characters.

        cmp     [.wparam], $bc
        jne     .maybedot

        invoke  GetKeyState, VK_SHIFT
        test    eax, $8000
        jnz     .closekey

        stdcall CreatePAHint, [.hwnd]
        jmp     .closekey

.maybedot:
        cmp     [.wparam], $ba  ; ;: key
        jne     .maybedot2

        invoke  GetKeyState, VK_SHIFT
        test    eax, $8000
        jnz     .endchar

.maybedot2:
        cmp     [.wparam], $be  ; .> key
        jne     .closekey

.itsdot:
        invoke  GetKeyState, VK_SHIFT
        test    eax, $8000
        jnz     .closekey

.endchar:
        invoke  PostMessageW, [.hwnd], CCM_UPDATECCPOS, 0, 0
        stc
        return

.closekey:
        invoke  PostMessageW, [hCCList], WM_CLOSE, 0, 0
        stc
        return

.sendtocc:
        invoke  SendMessageW, [hCCList], [.wmsg], [.wparam], [.lparam]
        clc
        return

.inserttext:
        call    .insert_text_proc
        invoke  ShowWindow, [hCCList], SW_HIDE
        invoke  PostMessageW, [hCCList], WM_CLOSE, 0, 0
        invoke  SetFocus, [.hwnd]
        clc
        return

;----------------------------------------------------------------------
.insert_text_proc:

        stdcall GetCCListSelected
        jc      .finishinsert

        stdcall utf8ToWideChar, ebx
        mov     ebx, eax

        lea     eax, [.str]
        invoke  SendMessageW, [.hwnd], AEM_GETWORDATCARET, $ffff0100, eax

        mov     [.aepos.selectionLine], 0
        mov     [.aepos.caretLine], 0
        movzx   ecx, ax
        shr     eax, 16

        inc     ecx
        inc     eax

        mov     [.aepos.selectionPosition], eax
        mov     [.aepos.caretPosition], ecx
        lea     eax, [.aepos]
        invoke  SendMessageW, [.hwnd], AEM_SETPOS, eax, 0
        invoke  SendMessageW, [.hwnd], EM_REPLACESEL, TRUE, ebx

        stdcall FreeMem, ebx

        lea     ebx, [.aepos]
        invoke  SendMessageW, [.hwnd], AEM_GETPOS, ebx, 0
        push    [.aepos.selectionPosition] [.aepos.selectionLine]
        pop     [.aepos.caretLine] [.aepos.caretPosition]
        invoke  SendMessageW, [.hwnd], AEM_SETPOS, ebx, 0

.finishinsert:
        retn


;-------------------------------------------------------------------

.maybeopen:
        mov     eax, [.wparam]
        cmp     eax, $be  ; point
        je      .point

        cmp     eax, VK_SPACE
        je      .space

        cmp     eax, 'Q'
        je      .ctrlQ                  ; procedure arguments hint.

        cmp     eax, 'W'
        je      .ctrlW                  ; procedure embeded help

        cmp     eax, $bc
        jne     .ondefault

        invoke  GetKeyState, VK_SHIFT
        test    eax, $8000
        jnz     .ondefault

; open procedure arguments hint (hPAHint) window
.openPA:
        stdcall CreatePAHint, [.hwnd]
        stc
        return

; open embeded help window
.openEH:
        stdcall CreateEHWindow, [.hwnd]
        stc
        return


.ctrlQ:
        invoke  GetKeyState, VK_CONTROL
        test    eax, $8000
        jnz     .openPA
        stc
        return

.ctrlW:
        invoke  GetKeyState, VK_CONTROL
        test    eax, $8000
        jnz     .openEH
        stc
        return

.space:
        invoke  GetKeyState, VK_CONTROL
        test    eax, $8000
        jz      .ondefault
        jmp     .doit

.point:
        invoke  GetKeyState, VK_SHIFT
        test    eax, $8000
        jnz     .ondefault

;        lea     esi, [.str]
;        invoke  SendMessageA, [.hwnd], AEM_GETWORDATCARET, $ffff0100, esi

;        cmp     byte [esi], 0
;        je      .ondefault

.doit:
        stdcall CreateCCList, [.hwnd]
        invoke  PostMessageW, [.hwnd], CCM_UPDATECCPOS, 0, 0

        cmp     [.wparam], $be
        je      .ondefault

        clc
        return

        enddispatch
endp




;-----------------------------------------------------------------------

proc OnGotoDefinition, .wparam, .lparam
begin
        stdcall GetDefinition
        jnc     .def_found

        test    eax, eax
        jz      .missing_info

        cmp     eax, 2
        je      .not_defined

        return

.missing_info:
        stdcall ErrorMessage, errNotCompiled
        return

.not_defined:
        stdcall ErrorMessage, errNotDefined
        return

.def_found:
        stdcall PosEditor, eax, edx
        stdcall StrDel, eax
        return
endp



proc OnGotoInterface, .wparam, .lparam
begin
        stdcall GetInterface
        jnc     .def_found

        test    eax, eax
        jz      .missing_info

        cmp     eax, 2
        je      .not_defined

        return

.missing_info:
        stdcall ErrorMessage, errNotCompiled
        return

.not_defined:
        stdcall ErrorMessage, errNotDefined
        return

.def_found:
        stdcall PosEditor, eax, edx
        stdcall StrDel, eax
        return
endp




; returns:
; CF=0
; eax - handle of the string with filename of the source file where the label is defined.
; if eax = 0 the cursor is not on the word.
; edx - line number of the definition.
;
; CF=1 - the label definition can not be determined.
; eax = 0 - the source is not compiled and there is no debug info loaded
; eax = 1 - the symbol name can not be extracted from the editor.
; eax = 2 - the symbol is not defined for some reason.

proc GetDefinition
.aepos  AEPOS
.str    rb 1024
begin
        push    ebx ecx esi edi

        stdcall GetCurrentAsmEdit
        jc      .unknown_symbol

        mov     ebx, eax

.edit_ok:
        lea     esi, [.str]
        invoke  SendMessageW, ebx, AEM_GETWORDATCARET, 512, esi

        cmp     word [esi], 0
        je      .unknown_symbol

        stdcall WideCharToUtf8, esi
        mov     esi, eax

        lea     eax, [.aepos]
        invoke  SendMessageW, ebx, AEM_GETPOS, eax, 0

        stdcall GetEditorFile, ebx

        xor     ecx, ecx
        test    eax, eax
        jz      @f
        mov     eax, [eax+TOpenFile.hFileName]
        mov     ecx, [.aepos.caretLine]
@@:
        stdcall SearchDefinition, esi, eax, ecx
        stdcall StrDel, esi

.finish:
        pop     edi esi ecx ebx
        return

.unknown_symbol:
        mov     eax, 1
        stc
        jmp     .finish
endp



; returns:
; CF=0
; eax - handle of the string with filename of the source file where the label is defined.
; if eax = 0 the cursor is not on the word.
; edx - line number of the definition.
;
; CF=1 - the label definition can not be determined.
; eax = 0 - the source is not compiled and there is no debug info loaded
; eax = 1 - the symbol name can not be extracted from the editor.
; eax = 2 - the symbol is not defined for some reason.

proc GetInterface
.aepos  AEPOS
.str    rw 512
begin
        push    ebx ecx esi edi

        stdcall GetCurrentAsmEdit
        jc      .unknown_symbol

        mov     ebx, eax

        lea     esi, [.str]
        invoke  SendMessageW, ebx, AEM_GETWORDATCARET, 512, esi

        cmp     word [esi], 0
        je      .unknown_symbol

        stdcall WideCharToUtf8, esi
        mov     esi, eax

        stdcall StrDupMem, "interfaces."
        mov     edi, eax

        stdcall StrCat, edi, esi

        lea     eax, [.aepos]
        invoke  SendMessageW, ebx, AEM_GETPOS, eax, 0

        stdcall GetEditorFile, ebx
        mov     ecx, eax
        jecxz   .editor_ok

        mov     ecx, [eax+TOpenFile.hFileName]

.editor_ok:
        lea     edi, [.str]
        stdcall SearchDefinition, edi, ecx, [.aepos.caretLine]
        jnc     .finish_free

        stdcall SearchDefinition, esi, ecx, [.aepos.caretLine]

.finish_free:
        stdcall StrDel, esi
        stdcall StrDel, edi

.finish:
        pop     edi esi ecx ebx
        return

.unknown_symbol:
        mov     eax, 1
        stc
        jmp     .finish
endp


; Searches in the debug info, where some symbol is defined in the source file.
; arguments:
;    .hSymbol  - the name of the symbol.
;    .filename - origin filename.
;    .line     - origin line.
;
; The .filename and .line are needed only if the searched symbol is a local symbol (starts with ".")
; In this case, the procedure will try to find the previous global label in order to
; properly search the symbol definition.
; If the symbol is a global symbol, .filename and .line can have random values.
;
; returns:
; CF=0
; eax - handle of the string with filename of the source file where the label is defined.
; edx - line number of the definition.
;
; CF=1 - the label definition can not be determined.
; eax = 0 - the source is not compiled and there is no debug info loaded
; eax = 1 - the symbol name can not be extracted from the editor.
; eax = 2 - the symbol is not defined for some reason.

proc SearchDefinition, .hSymbol, .filename, .line
.full_name   dd ?
.with_suffix dd ?
begin
        push    ebx ecx esi edi

        stdcall StrDup, [.hSymbol]
        mov     [.full_name], eax

        stdcall StrDup, eax
        stdcall StrCat, eax, '.@here'
        mov     [.with_suffix], eax

        stdcall WaitForCompiler
        jc      .missing_info

        mov     edi, [ptrPreprocessed]
        test    edi, edi
        jz      .missing_info

        stdcall StrPtr, [.full_name]
        cmp     byte [eax], '.'
        jne     .localok

        cmp     [.filename], 0
        je      .localok

        stdcall SearchForLabelPrefix, [.filename], [.line]
        test    eax, eax
        jz      .localok        ; the prefix was not found or there is no prefix.

        stdcall StrInsert, [.full_name], eax, 0
        stdcall StrInsert, [.with_suffix], eax, 0

; here esi contains a pointer to the whole name including the parent label.
.localok:
        stdcall StrPtr, [.with_suffix]  ; search with suffix first, in order to find the proper definition.
        stdcall SearchTreeExact, eax, ptrLabels
        test    eax, eax
        jnz     .found

        stdcall StrPtr, [.full_name]
        stdcall SearchTreeExact, eax, ptrLabels
        test    eax, eax
        jz      .unknown_symbol

.found:
        test    [eax+TLabel.flags], lfDefined
        jz      .not_defined

        mov     eax, [eax+TLabel.pXRefArray]
        add     edi, [eax+TArray.array+TXRefInfo.ofsSource]         ; address of the preprocessed line where defined

.trytogo:
        mov     eax, [edi+TIntLine.LineNumber]
        test    eax, eax
        jns     .not_from_macro

; the name of the macro
        mov   ecx, [edi+TIntLine.ofsGenerator]
        add   ecx, [ptrPreprocessed]
        cmp   word [ecx+1], '__'          ; internal macro definition... for example __UGlobalBlock or __IGlobalBlock
        je    .searchdown

;.searchup:
        mov   edi, [edi+TIntLine.ofsSourceLine]
        add   edi, [ptrPreprocessed]
        jmp   .trytogo

.searchdown:
        mov     edi, [edi+TIntLine.ofsMacroLine]
        add     edi, [ptrPreprocessed]
        jmp     .trytogo



.not_from_macro:
        mov     ecx, [edi+TIntLine.ofsGenerator]
        add     ecx, [ptrPreprocessed]
        cmp     ecx, [ptrPreprocessed]
        jne     @f
        mov     ecx, [hStrFileName]
@@:

        mov     edx, eax        ; the line number
        stdcall StrDup, ecx     ; the name
        clc

.finish:
        stdcall StrDel, [.full_name]
        stdcall StrDel, [.with_suffix]
        pop     edi esi ecx ebx
        return

.missing_info:
        xor     eax, eax
        stc
        jmp     .finish

.not_defined:
        mov     eax, 2
        stc
        jmp     .finish

.unknown_symbol:
        mov     eax, 1
        stc
        jmp     .finish

endp



proc ClosePopup, .hpopup, .host, .wparam
begin
        mov     eax, [.wparam]
        cmp     [.hpopup], 0
        je      .exit

        cmp     eax, [.hpopup]
        je      .exit

        cmp     eax, [.host]
        je      .exit

        invoke  PostMessageW, [.hpopup], WM_CLOSE, 0, 0

.exit:
        return
endp