
.data
szDWORD        db  ':DWORD',0
szBYTE         db  ':BYTE',0
szLOCAL        db  'LOCAL    ',0
szINVOKE       db  'INVOKE',0
szMasmApiCall  db  'Res\MasmApiCall.wrd',0
szMasmApiMsg   db  'Res\MasmApiMsg.wrd',0
szMasmWord01   db  'Res\MasmWord01.wrd',0
szMasmWord02   db  'Res\MasmWord02.wrd',0
szMasmWord03   db  'Res\MasmWord03.wrd',0

szW01          db  '.if',0
szW02          db  '.elseif',0
szW03          db  'add',0
szW04          db  'cmp',0
szW05          db  'db',0
szW06          db  'dd',0
szW07          db  'lea',0
szW08          db  'les',0
szW09          db  'mov',0
szW10          db  'proc',0
szW11          db  'rep',0
szW12          db  'sub',0
WordArray      dd  szW01,szW02,szW03,szW04,szW05,szW06,szW07,szW08,szW09,szW10,szW11,szW12

szWI           db  'WI',0

szError31      db  'Can not find the above file.',0dh,0ah
               db  'The code helper feature will not work.',0
;szError32      db  'The MasmApiCall.wrd file is missing or is',0dh,0ah
;               db  'corrupted.',0

.data?
hParListBox    dd  ?
hWndListBox    dd  ?
hParPopup      dd  ?
hAPIPopup      dd  ?

FontWth        dd  ?
WndHgt         dd  ?
ApiCall        dd  ?
MsgCall        dd  ?
InvokeOn       dd  ?
MsgOn          dd  ?
MessageOn      dd  ?
InstOn         dd  ?
WordOn         dd  ?
LoadSW         dd  ?
MatchNum       dd  ?
LineParse      dd  ?
sLineA         dd  ?
sLineM         dd  ?
sLineW         dd  ?
sPos           dd  ?
ePos           dd  ?
ApiMsg         dd  ?
SavPosX        dd  ?

hApiABC        dd  ?
hApiPointer    dd  ?
hApiCall       dd  ?
hMsgABC        dd  ?
hMsgPointer    dd  ?
hMsgCall       dd  ?

hWord01ABC     dd  ?
hWord01Pointer dd  ?
hWord01Call    dd  ?
hWord02ABC     dd  ?
hWord02Pointer dd  ?
hWord02Call    dd  ?
hWord03ABC     dd  ?
hWord03Pointer dd  ?
hWord03Call    dd  ?

TypePos        dd  ?
TypeChars      db  256  dup(?)
TypeBuff       db  256  dup(?)
szApiBuff      db  256  dup(?)
szMsgBuff      db  256  dup(?)
szOutBuff      db  16   dup(?)
Test22         dd  ?

;---------- [Structures] ----------
LINE struct
  rpLine       dd ?            ; Relative pointer to Line
LINE ends            

.code

;===================================================
; Load root path PROCEDURE
;===================================================
LoadLookUp PROC uses ebx esi edi
LOCAL    pt:POINT
LOCAL    rect:RECT
LOCAL    Code:DWORD, Incr, Cnt, nLine, hDC
LOCAL    szApiPath[256]:BYTE, Clear[20]:BYTE

      INVOKE     HeapAlloc, hDefHeap, HEAP_ZERO_MEMORY, 2048
         mov     hApiABC, eax
      INVOKE     HeapAlloc, hDefHeap, HEAP_ZERO_MEMORY, 10000
         mov     hApiPointer, eax
      INVOKE     HeapAlloc, hDefHeap, HEAP_ZERO_MEMORY, 100000
         mov     hApiCall, eax
      INVOKE     HeapAlloc, hDefHeap, HEAP_ZERO_MEMORY, 2048
         mov     hMsgABC, eax
      INVOKE     HeapAlloc, hDefHeap, HEAP_ZERO_MEMORY, 10000
         mov     hMsgPointer, eax
      INVOKE     HeapAlloc, hDefHeap, HEAP_ZERO_MEMORY, 50000
         mov     hMsgCall, eax

      INVOKE     HeapAlloc, hDefHeap, HEAP_ZERO_MEMORY, 2048
         mov     hWord01ABC, eax
      INVOKE     HeapAlloc, hDefHeap, HEAP_ZERO_MEMORY, 10000
         mov     hWord01Pointer, eax
      INVOKE     HeapAlloc, hDefHeap, HEAP_ZERO_MEMORY, 20000
         mov     hWord01Call, eax
      INVOKE     HeapAlloc, hDefHeap, HEAP_ZERO_MEMORY, 2048
         mov     hWord02ABC, eax
      INVOKE     HeapAlloc, hDefHeap, HEAP_ZERO_MEMORY, 10000
         mov     hWord02Pointer, eax
      INVOKE     HeapAlloc, hDefHeap, HEAP_ZERO_MEMORY, 20000
         mov     hWord02Call, eax
      INVOKE     HeapAlloc, hDefHeap, HEAP_ZERO_MEMORY, 2048
         mov     hWord03ABC, eax
      INVOKE     HeapAlloc, hDefHeap, HEAP_ZERO_MEMORY, 64000
         mov     hWord03Pointer, eax
      INVOKE     HeapAlloc, hDefHeap, HEAP_ZERO_MEMORY, 320000
         mov     hWord03Call, eax


      INVOKE     FillBuffer, addr Clear, sizeof Clear, ' ', 1
         mov     eax, Outdent
         inc     eax
      INVOKE     lstrcpyn, addr szOutBuff, addr Clear, eax
      INVOKE     GetDC, hREdit
         mov     hDC, eax
      INVOKE     SelectObject, hDC, hFont
        push     eax
      INVOKE     GetTextExtentPoint32, hDC, addr szWI, 2, addr pt
         mov     eax, pt.x
         xor     edx, edx
         mov     ecx, 2
         div     ecx
         mov     FontWth, eax
         pop     eax
      INVOKE     SelectObject, hDC, eax
      INVOKE     SelectObject, hDC, hFontTB
        push     eax
      INVOKE     GetTextExtentPoint32, hDC, addr szWI, 2, addr pt
         mov     eax, pt.y
        imul     eax, 10
         mov     WndHgt, eax
         pop     eax
      INVOKE     SelectObject, hDC, eax
      INVOKE     ReleaseDC, hREdit, hDC

;WS_EX_TOPMOST LBS_NOINTEGRALHEIGHT or  or WS_VISIBLE
      INVOKE     CreateWindowEx, NULL, addr KeyWordClass, NULL,\
                 WS_POPUP or WS_BORDER,\
                 400, 300, 150, 169, hWnd, NULL, hInst, NULL
         mov     hParListBox, eax

      INVOKE     CreateWindowEx, NULL, addr ListboxClass, 0,\
                 WS_CHILD or WS_VISIBLE or WS_HSCROLL or WS_VSCROLL or LBS_HASSTRINGS or\
                 LBS_NOTIFY or LBS_SORT or LBS_WANTKEYBOARDINPUT,\
                 0, 0, 0, 0, hParListBox, 43003, hInst, NULL
         mov     hWndListBox, eax
      INVOKE     SendMessage, hWndListBox, LB_SETITEMHEIGHT, 0, 15           ; List items
      INVOKE     SendMessage, hWndListBox, WM_SETFONT, hFontTB, TRUE

      INVOKE     CreateWindowEx, NULL, addr KeyWordClass, NULL,\
                 WS_POPUP or WS_BORDER,\
                 0, 0, 0, 0, hWnd, NULL, hInst, NULL
         mov     hParPopup, eax

      INVOKE     CreateWindowEx, NULL, addr StaticClass, NULL,\
                 WS_CHILD or WS_VISIBLE or SS_OWNERDRAW or SS_NOTIFY,\
                 0, 0, 0, 0, hParPopup, 43004, hInst, NULL
         mov     hAPIPopup, eax
      INVOKE     SendMessage, hAPIPopup, WM_SETFONT, hFont, TRUE

         mov     Incr, 1
      .while (Incr < 6) ;7) ;4)
            and     Code, 0
            and     nLine, 0
         INVOKE     lstrcpy, addr szApiPath, addr AsmRootDir
         .if Incr == 1
            INVOKE     lstrcat, addr szApiPath, addr szMasmApiCall
               mov     ebx, hApiABC
               mov     esi, hApiCall
               mov     edi, hApiPointer
         .elseif Incr == 2
            INVOKE     lstrcat, addr szApiPath, addr szMasmApiMsg
               mov     ebx, hMsgABC
               mov     esi, hMsgCall
               mov     edi, hMsgPointer
         .elseif Incr == 3
            INVOKE     lstrcat, addr szApiPath, addr szMasmWord01
               mov     ebx, hWord01ABC
               mov     esi, hWord01Call
               mov     edi, hWord01Pointer
         .elseif Incr == 4
            INVOKE     lstrcat, addr szApiPath, addr szMasmWord02
               mov     ebx, hWord02ABC
               mov     esi, hWord02Call
               mov     edi, hWord02Pointer
         .elseif Incr == 5
            INVOKE     lstrcat, addr szApiPath, addr szMasmWord03
               mov     ebx, hWord03ABC
               mov     esi, hWord03Call
               mov     edi, hWord03Pointer
         .endif

         INVOKE     GetFileAttributes, addr szApiPath
         .if eax == -1
            INVOKE     MessageBox, NULL, addr szError31, addr szApiPath,\
                       MB_OK or MB_ICONWARNING or MB_SYSTEMMODAL
               ret
         .endif
            mov     ecx, hBuff
         INVOKE     lstrcpy, ecx, addr szApiPath
            mov     ecx, Incr
           call     ReadFApi
         .if eax == -1
               ret
         .endif
            xor     eax, eax
            mov     al, byte ptr[esi]
         .if al >= 'a' && al <= 'z'
               sub     al, 20h
         .endif
            mov     [ebx+eax*8], esi
            mov     dword ptr[ebx+eax*8+4], 0
            mov     [edi].LINE.rpLine, esi
            mov     byte ptr Code, al
            mov     ecx, 1
            mov     eax, BytesR
            mov     Cnt, eax
            xor     eax, eax
         .while (Cnt)
               mov     al, byte ptr[esi]
            .if byte ptr[esi-1] == 0ah
                  inc     nLine
               .if al >= 'a' && al <= 'z'
                     sub     al, 20h
               .endif
               .if byte ptr Code != al
                     mov     byte ptr Code, al
                     mov     [ebx+eax*8], esi           ; Address of line in the file
                     mov     edx, nLine
                     mov     [ebx+eax*8+4], edx         ; Line number
               .endif
                  mov     [edi+ecx*4].LINE.rpLine, esi  ; Address of line in the file
                  inc     ecx
            .endif
               inc     esi
               dec     Cnt
         .endw
            mov     [edi+ecx*4].LINE.rpLine, 0
            inc     Incr
      .endw

;mov     eax, 'D'
;mov     ebx, hWord03ABC
;mov     ecx, [ebx+eax*8]
;mov     edx, [ebx+eax*8+4]
;DSPValue hWnd, ecx, 1, 'm'
;DSPValue hWnd, edx, 1, 'm'
;INVOKE     MessageBox, NULL, ecx, addr AppName, MB_OK
;INVOKE     SendMessage, hREdit, WM_SETTEXT, 0, ecx

         ret

LoadLookUp ENDP

;===================================================
; KeyWordProc main PROCEDURE
;===================================================
KeyWordProc PROC hwnd:DWORD, wMsg, wParam, lParam
LOCAL    rect:RECT
LOCAL    hBRT:DWORD

      .if wMsg == WM_SIZE
            mov     edx, hwnd
            mov     eax, lParam
            mov     ecx, eax
            shr     ecx, 16
            and     eax, 0ffffh

         .if edx == hParListBox
            INVOKE     MoveWindow, hWndListBox, 0, 0, eax, ecx, TRUE

         .endif

      .elseif wMsg == WM_CTLCOLORLISTBOX
            mov     eax, lParam
         .if eax && eax != hREdit
            INVOKE     SetBkColor, wParam, Color.EditBC
            INVOKE     SetTextColor, wParam, Color.EditTC
               mov     eax, hSavBRM
               ret
         .endif

      .elseif wMsg == WM_DRAWITEM
            mov     esi, lParam
            lea     edi, dis
            mov     ecx, sizeof dis
            rep     movsb
         .if wParam == 43004
               mov     esi, lParam
               lea     edi, dis
               mov     ecx, sizeof dis
               rep     movsb
            .if dis.itemID != -1
               INVOKE     CreateSolidBrush, Color.EditBC                  ; Background color BackGC
                  mov     hBRT, eax
               INVOKE     FillRect, dis.hdc, addr dis.rcItem, eax
               INVOKE     SetBkColor, dis.hdc, Color.EditBC
               INVOKE     SetTextColor, dis.hdc, Color.EditTC
                  inc     dis.rcItem.left
                  dec     dis.rcItem.top
               INVOKE     DrawText, dis.hdc, addr WorkBuff, -1, addr dis.rcItem,\
                          DT_LEFT or DT_TOP or DT_SINGLELINE
                  dec     dis.rcItem.left
                  inc     dis.rcItem.top
               INVOKE     DeleteObject, hBRT
            .endif
               mov     dis.itemState, ODS_DEFAULT
               mov     dis.hdc, 0
        .endif

      .elseif wMsg == WM_VKEYTOITEM ;&& eax == 9999
            mov     eax, wParam
           cwde                          ; Only low word contains command
            mov     ecx, lParam
         .if ecx == hWndListBox
            INVOKE     CodeHelper, WM_KEYDOWN, wParam, lParam
         .endif
            mov     eax, -1
            ret

      .elseif wMsg == WM_COMMAND
            mov     eax, wParam
            mov     ebx, wParam
            mov     ecx, lParam
            shr     ebx, 16
           cwde                          ; Only low word contains command
            mov     wParam, eax

;---------- [Keywords API] ----------
         .if ecx == hWndListBox && ebx == LBN_DBLCLK
            INVOKE     CodeHelper, wMsg, ebx, lParam

;---------- [API popup] ----------
         .elseif ecx == hAPIPopup
            .if ebx == STN_DBLCLK
               INVOKE     ShowWindow, hParPopup, SW_HIDE
               INVOKE     ShowWindow, hAPIPopup, SW_HIDE
            .endif
            INVOKE     SetFocus, hREdit
         .endif

      .else
         INVOKE     DefWindowProc, hwnd, wMsg, wParam, lParam
            ret
      .endif

         mov     eax, FALSE
         ret

KeyWordProc ENDP

;===================================================
; Type ahead PROCEDURE
;===================================================
CodeHelper PROC uses ebx esi edi wMsg:DWORD, wParam, lParam
LOCAL    pt:POINT
LOCAL    ptWH:POINT
LOCAL    rect:RECT
LOCAL    Code:DWORD, CodeM, LineCnt, Cnt, Len, hDC, sPos01, sPos02, cPos01, cPos02, ValOn
LOCAL    szWork[64]:BYTE, szWork2[64]:BYTE, szInst[64]:BYTE

;_____________________________________________________________________________
      .if wMsg == WM_COMMAND
         .if wParam == LBN_DBLCLK
            INVOKE     SendMessage, hWndListBox, LB_GETCURSEL, 0, 0
            .if eax == LB_ERR
               INVOKE     ShowWindow, hParListBox, SW_HIDE
               INVOKE     ShowWindow, hWndListBox, SW_HIDE
                  jmp     Ret0
            .endif
               mov     ebx, eax
            INVOKE     SendMessage, hWndListBox, LB_GETTEXT, ebx, addr szWork2
            INVOKE     SendMessage, hWndListBox, LB_GETITEMDATA, ebx, 0
              push     eax
               shr     eax, 16
            .if al == '^'
               INVOKE     lstrcat, addr szWork2, addr szCRLF
            .elseif al == '`'
               INVOKE     lstrcat, addr szWork2, addr szOutBuff
            .endif
               pop     eax
               and     eax, 0ffffh
            .if !MessageOn && !WordOn || lParam == 1   ; lParam = InvokeOn
                  mov     edi, hApiPointer
                  mov     esi, [edi+eax*4].LINE.rpLine
                  xor     edi, edi
                  xor     ecx, ecx
                  and     MsgOn, 0
               .while (byte ptr[esi] != 0ah)
                  .if dword ptr[esi] == ',gsM'
                        mov     MsgOn, ecx
                  .endif
                     mov     al, byte ptr[esi]
                  .if al == ','
                        inc      ecx
                  .endif 
                  .if al != 0dh
                        mov     byte ptr szApiBuff[edi], al
                        mov     byte ptr szApiBuff[edi+1], 0
                        inc     edi
                  .else
                     .break
                  .endif
                     inc     esi
               .endw
                  mov     ApiMsg, 1
               INVOKE     lstrcpy, addr WorkBuff, addr szApiBuff
            .endif


            .if MessageOn
                  mov     edi, hMsgPointer
                  mov     esi, [edi+eax*4].LINE.rpLine
                  xor     edi, edi
               .while (byte ptr[esi] != 0ah)
                     mov     al, byte ptr[esi]
                  .if al != 0dh
                        mov     byte ptr szMsgBuff[edi], al
                        mov     byte ptr szMsgBuff[edi+1], 0
                        inc     edi
                  .else
                     .break
                  .endif
                     inc     esi
               .endw
                  mov     ApiMsg, 2
               INVOKE     lstrcpy, addr WorkBuff, addr szMsgBuff
                  mov     lParam, 1
            .endif

            INVOKE     SendMessage, hREdit, EM_EXGETSEL, 0, addr cr
               mov     eax, TypePos
               sub     cr.cpMin, eax
            INVOKE     SendMessage, hREdit, EM_EXSETSEL, 0, addr cr
.if !WordOn || lParam == 1   ; lParam = InvokeOn
            INVOKE     lstrcat, addr szWork2, addr szCom
   .if SpaceAfter
            INVOKE     lstrcat, addr szWork2, addr szSpace
   .endif
.endif
            INVOKE     lstrcpy, addr TypeChars, addr szWork2
            INVOKE     SendMessage, hREdit, EM_REPLACESEL, TRUE, addr szWork2
            INVOKE     SendMessage, hREdit, EM_EXGETSEL, 0, addr cr
            INVOKE     ShowWindow, hParListBox, SW_HIDE
            INVOKE     ShowWindow, hWndListBox, SW_HIDE
      INVOKE     lstrlen, addr szWork2
         mov     TypePos, eax

            .if !MessageOn && !WordOn || lParam == 1   ; lParam = InvokeOn
                 call     SetPopup
            .endif

;               and     MessageOn, 0
             MOVmd     cr.cpMin, cr.cpMax
            INVOKE     SendMessage, hREdit, EM_EXSETSEL, 0, addr cr
            INVOKE     SetFocus, hREdit
               and     InvokeOn, 0
               and     WordOn, 0
         .endif
;DSPValue hWnd, TypePos, 1, 't'
;INVOKE     lstrlen, addr TypeChars
;DSPValue hWndStat, eax, 1, 's'

;_____________________________________________________________________________
      .elseif wMsg == WM_KEYDOWN
         INVOKE     IsWindowVisible, hWndListBox
            mov     ebx, wParam
            and     ebx, 0ffffh
         .if eax && ebx == 28h || eax && ebx == 26h || eax && ebx == VK_RETURN
            INVOKE     SetFocus, hWndListBox
            INVOKE     SendMessage, hWndListBox, LB_GETCURSEL, 0, 0
            .if eax == LB_ERR && ebx != VK_RETURN
               INVOKE     SendMessage, hWndListBox, LB_SETCURSEL, 0, 0
            .endif
            .if ebx == VK_RETURN
                  mov     WordOn, 2
;DSPValue hWnd, 1111, 1, 'm'
;DSPValue hWnd, ebx, 1, 't'
;DSPValue hWnd, InvokeOn, 1, 'm'
;DSPValue hWnd, MessageOn, 1, 'm'
               INVOKE     CodeHelper, WM_COMMAND, LBN_DBLCLK, InvokeOn
            .endif
         .elseif eax && ebx == 23h
            INVOKE     ShowWindow, hParListBox, SW_HIDE
            INVOKE     ShowWindow, hWndListBox, SW_HIDE
            INVOKE     SetFocus, hREdit
         .endif

;_____________________________________________________________________________
      .elseif wMsg == WM_CHAR
         .if TypePos > 254 || wParam == 0dh ||\
             WordOn && wParam == 09h || WordOn && wParam == ' ' ||\
             WordOn && wParam == ',' || WordOn && wParam == ':'
               and     TypePos, 0
               and     ApiCall, 0
               and     InvokeOn, 0
               and     MessageOn, 0
               and     WordOn, 0
               and     MsgOn, 0
            INVOKE     FillBuffer, addr TypeBuff, sizeof TypeBuff, ' ', 1
            INVOKE     ShowWindow, hParListBox, SW_HIDE
            INVOKE     ShowWindow, hWndListBox, SW_HIDE
            INVOKE     ShowWindow, hParPopup, SW_HIDE
            INVOKE     ShowWindow, hAPIPopup, SW_HIDE
            INVOKE     SendMessage, hWndListBox, LB_RESETCONTENT, 0, 0
         .endif

            mov     ebx, TypePos
            mov     eax, wParam
         .if al == 08h
            INVOKE     IsWindowVisible, hWndListBox
            .if eax && MsgCall
               INVOKE     lstrcpy, addr WorkBuff, addr szApiBuff
               INVOKE     SendMessage, hAPIPopup, WM_SETTEXT, 0, addr WorkBuff
                  mov     ApiMsg, 1
                 call     SetPopup

            .elseif eax
               INVOKE     ShowWindow, hParPopup, SW_HIDE
               INVOKE     ShowWindow, hAPIPopup, SW_HIDE
            .endif
            INVOKE     lstrlen, addr TypeChars
            INVOKE     lstrcpyn, addr TypeChars, addr TypeChars, eax
            .if TypePos
                  dec     TypePos
            .endif
            .if !TypePos && MessageOn
                  mov     MessageOn, 1
            .endif
               mov     esi, -1

         .elseif al != 0dh
            .if al >= 'A' && al <= 'Z'
                  add     al, 20h
            .endif
            .if al == ',' && ApiCall && MsgOn
                  and     sPos, 0
                  inc     MessageOn
            .endif
               mov     TypeChars[ebx], al
               mov     TypeChars[ebx+1], 0
               inc     TypePos
               mov     esi, 1
         .endif
;INVOKE     SetWindowText, hWnd, addr TypeChars
;DSPValue hWndStat, TypePos, 1, 's'

         INVOKE     lstrlen, addr TypeChars
           push     eax
         INVOKE     IsWindowVisible, hWndListBox
            pop     ecx
;DSPValue hWnd, ecx, 1, 't'
;DSPValue hWnd, TypePos, 1, 't'
;DSPValue hWndStat, ecx, 1, 's'
         .if eax && sdword ptr ecx > 0 || MessageOn && sdword ptr ecx > 0
               mov     ecx, esi
              call     MoveList

         .elseif !ecx
            INVOKE     ShowWindow, hParListBox, SW_HIDE
            INVOKE     ShowWindow, hWndListBox, SW_HIDE
         .endif
         .if ApiCall && byte ptr TypeChars[ebx] != ' ' &&  byte ptr TypeChars[ebx] != 09h ||\
             MsgCall && byte ptr TypeChars[ebx] != ' ' &&  byte ptr TypeChars[ebx] != 09h ||\
             WordOn && byte ptr TypeChars[ebx] != ' ' &&  byte ptr TypeChars[ebx] != 09h
            INVOKE     lstrlen, addr TypeChars
              push     eax
            INVOKE     IsWindowVisible, hWndListBox
               pop     ecx
            .if eax && ecx > 0 ;1
;DSPValue hWnd, InvokeOn, 1, 't'
;DSPValue hWndStat, sLineA, 1, 's'
                 call     GetGroup
               .if !MatchNum
                  INVOKE     ShowWindow, hParListBox, SW_HIDE
                  INVOKE     ShowWindow, hWndListBox, SW_HIDE
            INVOKE     ShowWindow, hParPopup, SW_HIDE
            INVOKE     ShowWindow, hAPIPopup, SW_HIDE
                     jmp     Ret0
               .endif
                  mov     ecx, 44
                 call     Loadbox
                  jmp     Ret0
            .endif
         .endif

;_____________________________________________________________________________
      .elseif wMsg == WM_KEYUP
         .if WordOn == 2
               dec     WordOn
               jmp     Ret0
         .endif
            mov     eax, lParam
            shr     eax, 16
            and     eax, 0fffh
         .if wParam == 0dh || wParam == 26h || wParam == 28h || eax == 3ch ;||\
;             wParam == 2eh || wParam == 20h || wParam == 09h
         .else
              call     ParseLine
         .endif
      .endif

Ret0:
         xor     eax, eax
         ret

;---------- [Parse line] ----------
ParseLine:
;DSPValue hWndStat, TypePos, 1, 's'
      INVOKE     SendMessage, hREdit, EM_EXGETSEL, 0, addr cr
      INVOKE     SendMessage, hREdit, EM_EXLINEFROMCHAR, 0, cr.cpMin
         mov     LineParse, eax
         mov     TypeBuff, 0ffh
      INVOKE     SendMessage, hREdit, EM_GETLINE, LineParse, addr TypeBuff
         mov     TypeBuff[eax], 0
         mov     Len, eax
      .if byte ptr TypeBuff == ';'
            mov     eax, 0
      .endif
         mov     Cnt, eax
      .if eax
            mov     ecx, eax
            lea     esi, TypeBuff
           call     LowerCase                     ; Convert to lowercase
;INVOKE     SetWindowText, hWnd, addr TypeBuff
         INVOKE     GetCaretPos, addr pt
            mov     eax, pt.x
            sub     eax, 11                      ; Selection bar width
         .if LineOn
               sub     eax, LineWth
         .endif
            xor     edx, edx
            mov     ecx, FontWth
            div     ecx
            mov     pt.x, eax
            and     sPos01, 0
            and     sPos02, 0
            and     cPos01, 0
            and     cPos02, 0
            and     Code, 0
            and     CodeM, 0
            and     InvokeOn, 0
            and     ApiCall, 0
            and     MessageOn, 0
            and     InstOn, 0
            and     LoadSW, 0
            and     ValOn, 0
;            and     WordOn, 0
            xor     ebx, ebx
            xor     ecx, ecx
            xor     edx, edx
            xor     esi, esi
         .while (Cnt)
               mov     al, byte ptr TypeBuff[ecx]
            .if byte ptr TypeBuff[ecx-1] == 09h
                  mov     byte ptr TypeBuff[ecx-1], ' '
            .endif
            .if byte ptr TypeBuff[ecx+4] == 09h
                  mov     byte ptr TypeBuff[ecx+4], ' '
            .endif
            .if byte ptr TypeBuff[ecx] == 'i' &&\
                byte ptr TypeBuff[ecx+1] == 'n' &&\
                byte ptr TypeBuff[ecx+2] == 'v'
                  mov     InvokeOn, 1
                  mov     ApiCall, ecx
                  add     ApiCall, 6
               .if byte ptr TypeBuff[ecx+3] == 0 && !ebx && !esi && wParam != 08h
                  INVOKE     lstrcpy, addr szWork, addr szINVOKE
                  INVOKE     lstrcat, addr szWork, addr szOutBuff
                     mov     esi, 3
                    call     DoUpdate
                    retn
               .elseif byte ptr TypeBuff[ecx+3] == 'o' &&\
                       byte ptr TypeBuff[ecx+4] == 'k' &&\
                       byte ptr TypeBuff[ecx+5] == 'e' &&\
                       byte ptr TypeBuff[ecx+6] >= 'a' && byte ptr TypeBuff[ecx+6] <= 'z'
                     and     InvokeOn, 0
                     and     ApiCall, 0
               .endif

            .elseif byte ptr TypeBuff[ecx-1] == ' ' && word ptr TypeBuff[ecx] == 'bd' &&\
                    byte ptr TypeBuff[ecx+2] == ' ' ||\
                    byte ptr TypeBuff[ecx-1] == ' ' && word ptr TypeBuff[ecx] == 'dd' &&\
                    byte ptr TypeBuff[ecx+2] == ' '
                  mov     ValOn, 1

            .elseif byte ptr TypeBuff[ecx-1] == ' ' && dword ptr TypeBuff[ecx] == 'corp' &&\
                    byte ptr TypeBuff[ecx+4] == ' '
                  mov     ValOn, 1

            .elseif al == ','
                  inc     ebx
                  mov     edx, ecx
                  mov     cPos02, ecx
            .elseif al == 20h || al == 09h
                  mov     edx, ecx
               .if !cPos01
                     mov     sPos01, ecx
               .else
                     mov     sPos02, ecx
               .endif
            .elseif al != 20h && al != 09h && al != 0
                  inc     esi
               .if !sPos02
                     mov     cPos01, ecx
               .else
                     mov     cPos02, ecx
               .endif
               .if ApiCall && ecx > ApiCall && !ebx && !Code
                  .if byte ptr TypeBuff[ecx-1] == 20h || byte ptr TypeBuff[ecx-1] == 09h
                     .if al != 0
                           mov     ApiCall, ecx
                        .if byte ptr TypeBuff[ecx+1] == 0
                              mov     byte ptr Code, al
                        .endif
                     .endif
                  .endif

               .elseif ApiCall && ecx > ApiCall && ebx == MsgOn && !CodeM  ;2
                  .if byte ptr TypeBuff[ecx-1] == 20h || byte ptr TypeBuff[ecx-1] == 09h ||\
                      byte ptr TypeBuff[ecx-1] == ','
                     .if al != 0
                           mov     MsgCall, ecx
                        .if byte ptr TypeBuff[ecx+1] == 0
                              mov     byte ptr CodeM, al
                        .endif
                     .endif
                  .endif
               .endif
            .endif
               inc     ecx
               dec     Cnt
         .endw

            mov     ecx, edx
         .if InvokeOn && MsgOn && ebx == MsgOn ;2
               mov     MessageOn, 1
         .else
               and     MessageOn, 0
               and     MsgCall, 0
         .endif
         .if ebx && InvokeOn
               and     InvokeOn, 0
               and     ApiCall, 0
            .if ebx >= 2 && !MessageOn
            .else
               and     WordOn, 0
               jmp     Pass
            .endif
         .elseif InvokeOn
               and     WordOn, 0
               jmp     Pass
         .endif

;---------- [Get instruction word
         .if cPos02
              push     ebx
              push     ecx
               lea     esi, szInst
               mov     edx, sPos01
            .if edx
                  inc     edx
            .endif
            .while (edx <= cPos01)
                  mov     al, byte ptr TypeBuff[edx]
               .if al != 20h && al != 09h
                     mov     byte ptr[esi], al
                     mov     byte ptr[esi+1], 0
                     inc     esi
               .endif
                  inc     edx
            .endw
               xor     ebx, ebx
               mov     ecx, sizeof WordArray
               shr     ecx, 2
            .while (ecx)
                  lea     esi, szInst
                  mov     edi, WordArray[ebx*4]
                  xor     edx, edx
                  mov     al, byte ptr[esi]
               .while (al != 0)
                     mov     al, byte ptr[esi]
                  .if al == byte ptr[edi+edx]
                        inc     esi
                        inc     edx
                  .else
                     .break
                  .endif
               .endw
               .if al == 0
                  .break
               .endif
                  inc     ebx
                  dec     ecx
            .endw
            .if al == 0
                  mov     InstOn, 1
            .endif
               pop     ecx
               pop     ebx
         .endif
;DSPValue hWnd, InstOn, 1, 't'

         .if wParam == 25h || wParam == 27h || wParam == 2eh || wParam == 20h || wParam == 09h
              retn
         .endif

            xor     edx, edx
            xor     esi, esi
            mov     al, byte ptr TypeBuff[ecx]
         .while (al != 0)
               xor     eax, eax
               mov     al, byte ptr TypeBuff[ecx]
;DSPValue hWnd, eax, 1, 'm'
            .if al == 20h || al == 09h || al == 0
            .else
                   mov     edx, ecx
;                   dec     edx
               .if byte ptr TypeBuff[ecx] == '.' && byte ptr TypeBuff[ecx-1] == 20h ||\
                   byte ptr TypeBuff[ecx] == '.' && byte ptr TypeBuff[ecx-1] == 09h ||\
                   byte ptr TypeBuff[ecx] == '.' && edx == 0 ||\
                   byte ptr TypeBuff[ecx] == ':'
                  .if byte ptr TypeBuff[ecx+1] == 0
                        jmp     Ret0
                  .endif
                     mov     ebx, Len
                     inc     ebx
                     sub     ebx, ecx
                  .if ebx > 3 && byte ptr TypeBuff[ecx] == '.'
                     mov     edx, Len
                        mov     dl, byte ptr TypeBuff[edx-1]
                     .if dl == '6' || dl == '?' ||\
                         dl == 'a' && byte ptr TypeBuff[ecx+1] != 'b' && ebx > 5 ||\
                         dl == 'e' && byte ptr TypeBuff[ecx+1] != 'b' && ebx > 5 ||\
                         dl == 'f' || dl == 'k' || dl == 't' && ebx > 5 || dl == 'w'
                        INVOKE     ShowWindow, hParListBox, SW_HIDE
                        INVOKE     ShowWindow, hWndListBox, SW_HIDE
                           jmp     Ret0
                     .endif
                  .endif
                     mov     LoadSW, 1
                     mov     ebx, hWord01ABC
                     mov     al, byte ptr TypeBuff[ecx]
                     mov     esi, [ebx+eax*8]       ; Start address of group
                     mov     eax, [ebx+eax*8+4]     ; Start line number of group
                     mov     sLineW, eax
                  .if !esi
                        jmp     Ret0
                  .endif
                     mov     WordOn, 1
                  INVOKE     lstrcpy, addr TypeChars, addr TypeBuff[ecx]
                  INVOKE     lstrlen, addr TypeChars
                     mov     TypePos, eax
                  .break

               .elseif byte ptr TypeBuff[ecx-1] == 20h || byte ptr TypeBuff[ecx-1] == 09h ||\
                       byte ptr TypeBuff[ecx-1] == ',' || !ecx
                     lea     esi, TypeBuff
                     mov     edx, ecx
                     mov     edi, MinMatch
                  .while (edi || edx <= Len)
                     .if edi
                           dec     edi
                     .endif
                        mov     al, byte ptr[esi+edx]
                     .if al == 'j' && byte ptr[esi+edx+1] == 0
                        .break
                     .elseif al == '.' || al == ':'
                        .if edx > pt.x
                              and     LoadSW, 0
                              jmp     Pass
                        .endif
                           mov     eax, pt.x
                        .if byte ptr[esi+eax] >= 'a' && byte ptr[esi+eax] <= 'z'
                              and     LoadSW, 0
                              jmp     Pass
                        .endif
                           jmp     NoLoad
                     .elseif al >= 'a' && al <= 'z' && byte ptr[esi+edx+1] == 0
                        .break
                     .endif
                        inc     edx
                  .endw
                     mov     al, byte ptr TypeBuff[ecx]
;                  .if edi && al != 'j'
;                        jmp     NoLoad
;                  .endif
;DSPValue hWnd, sPos02, 1, 't'
;DSPValue hWndStat, cPos02, 1, 's'
                  .if !InstOn && !sPos01 && !sPos02 || !InstOn && sPos01 && !sPos02 || ValOn
                        mov     LoadSW, 1
                        mov     ebx, hWord01ABC
                  .elseif !InstOn && !sPos01 && sPos02 && !ebx
                        mov     LoadSW, 2
                        mov     ebx, hWord02ABC
                  .else
                        mov     LoadSW, 3
                        mov     ebx, hWord03ABC
                  .endif
;DSPValue hWnd, ecx, 1, 't'
;DSPValue hWndStat, pt.x, 1, 's'
                     mov     edx, pt.x
                  .if edi && al != 'j' && !ValOn || ecx > pt.x ||\
                      byte ptr TypeBuff[edx+1] >= 'a' && byte ptr TypeBuff[edx+1] <= 'z'
                        and     LoadSW, 0   ; !!!!!!!!! NOTE
                        jmp     NoLoad
                  .endif
                     mov     al, byte ptr TypeBuff[ecx]
                     sub     al, 20h
                     mov     esi, [ebx+eax*8]       ; Start address of group
                     mov     eax, [ebx+eax*8+4]     ; Start line number of group
                     mov     sLineW, eax
                  .if !esi
                        jmp     Ret0
                  .endif
                     mov     WordOn, 1
                  INVOKE     lstrcpy, addr TypeChars, addr TypeBuff[ecx]
                  INVOKE     lstrlen, addr TypeChars
                     mov     TypePos, eax
                  .break
NoLoad:
               .endif
            .endif
               inc     ecx
         .endw

Pass:
;---------- [Copy field to TypeBuff
         .if ApiCall || MsgCall
               mov     ecx, ApiCall
            .if MsgCall
                  mov     ecx, MsgCall
            .endif
            .if byte ptr TypeBuff[ecx] >= 'a' && byte ptr TypeBuff[ecx] <= 'z'
               INVOKE     lstrcpy, addr TypeChars, addr TypeBuff[ecx]
            .endif
         .endif
         INVOKE     lstrlen, addr TypeChars
            mov     TypePos, eax
;INVOKE     SetWindowText, hWnd, addr TypeChars
;DSPValue hWndStat, TypePos, 1, 's'

         .if ApiCall && Code || MsgCall && CodeM
               mov     eax, Code
               mov     ebx, hApiABC
            .if MsgCall
                  mov     eax, CodeM
                  mov     ebx, hMsgABC
            .endif
               sub     eax, 20h
               mov     esi, [ebx+eax*8]       ; Start address of group
               mov     eax, [ebx+eax*8+4]     ; Start line number of group

            .if ApiCall
                  mov     sLineA, eax
            .else
                  mov     sLineM, eax
            .endif
            .if !esi
                  jmp     Ret0
            .endif
         .endif
         INVOKE     IsWindowVisible, hWndListBox

;DSPValue hWnd, ApiCall, 1, 't'
;DSPValue hWndStat, TypePos, 1, 's'
;DSPValue hWnd, Code, 1, 't'

;-------- [Load the listbox
         .if ApiCall && Code && !eax || MsgCall && CodeM && !eax || WordOn
               and     sPos, 0
            .if WordOn && !LoadSW
                 retn
            .endif
              call     GetGroup
            .if !MatchNum
               INVOKE     ShowWindow, hParListBox, SW_HIDE
               INVOKE     ShowWindow, hWndListBox, SW_HIDE
            INVOKE     ShowWindow, hParPopup, SW_HIDE
            INVOKE     ShowWindow, hAPIPopup, SW_HIDE
                 retn
            .endif
               mov     eax, sPos
            .if WordOn && sLineW && !sPos ;|| WordOn && eax == ePos
                 retn
            .endif
               xor     ecx, ecx
              call     Loadbox

;-------- [Reload the listbox from backspace
         .elseif ApiCall && TypePos && !eax || MsgCall && TypePos && !eax ;|| WordOn
            INVOKE     SetFocus, hREdit
               and     sPos, 0
              call     GetGroup
            .if MatchNum
               INVOKE     ShowWindow, hParListBox, SW_SHOWDEFAULT
               INVOKE     ShowWindow, hWndListBox, SW_SHOWDEFAULT
            .else
                 retn
            .endif
               xor     ecx, ecx
              call     Loadbox

         .elseif ApiCall && !TypePos
            INVOKE     ShowWindow, hParPopup, SW_HIDE
            INVOKE     ShowWindow, hAPIPopup, SW_HIDE
         .endif
      .endif
        retn

;---------- [Update keyword] ----------
DoUpdate:
      INVOKE     SendMessage, hREdit, EM_EXGETSEL, 0, addr cr
         sub     cr.cpMin, esi
      INVOKE     SendMessage, hREdit, EM_EXSETSEL, 0, addr cr
      INVOKE     SendMessage, hREdit, EM_REPLACESEL, TRUE, addr szWork
      INVOKE     lstrlen, addr szWork
         mov     ecx, cr.cpMax
         sub     ecx, cr.cpMin
         sub     eax, ecx
         add     cr.cpMax, eax
       MOVmd     cr.cpMin, cr.cpMax
      INVOKE     SendMessage, hREdit, EM_EXSETSEL, 0, addr cr
         and     TypePos, 0
        retn

;---------- [Get group range] ----------
GetGroup:
        push     sPos
         and     sPos, 0
         and     ePos, 0
         and     MatchNum, 0
      INVOKE     lstrlen, addr TypeChars
         mov     Len, eax
         mov     dl, TypeChars[eax-1]
      .if ApiCall
            mov     edi, hApiPointer
            mov     ebx, sLineA
      .elseif MessageOn
            mov     edi, hMsgPointer
            mov     ebx, sLineM
;      .elseif WordOn
;            mov     edi, hWordPointer
;            mov     ebx, sLineW
      .elseif WordOn && LoadSW == 1
            mov     edi, hWord01Pointer
            mov     ebx, sLineW
      .elseif WordOn && LoadSW == 2
            mov     edi, hWord02Pointer
            mov     ebx, sLineW
      .elseif WordOn && LoadSW == 3
            mov     edi, hWord03Pointer
            mov     ebx, sLineW
      .else
            pop     sPos
           retn
      .endif
         mov     esi, [edi+ebx*4].LINE.rpLine
         mov     al, byte ptr[esi]
      .if al >= 'a' && al <= 'z'
            sub     al, 20h
      .endif
         mov     byte ptr Code, al

      .while (TRUE)
            mov     esi, [edi+ebx*4].LINE.rpLine
         .if !esi
            .break
         .endif
;            xor     eax, eax
            mov     al, byte ptr[esi]
         .if al >= 'a' && al <= 'z'
               sub     al, 20h
         .endif
         .if al != byte ptr Code
;DSPValue hWnd, eax, 1, 'm'
;DSPValue hWnd, Code, 1, 'm'
            .break
         .endif
            xor     edx, edx
            mov     ecx, Len
         .while (ecx)
;xor     eax, eax
               mov     al, byte ptr TypeChars[edx]
            .if byte ptr[esi+edx] >= 'A' && byte ptr[esi+edx] <= 'Z' && al >= 'a' && al <= 'z'
                  sub     al, 20h
            .elseif byte ptr[esi+edx] >= 'a' && byte ptr[esi+edx] <= 'z' && al >= 'A' && al <= 'Z'
                  add     al, 20h
            .endif
            .if byte ptr[esi+edx] < al
               .break
            .endif
            .if byte ptr[esi+edx] == al
                  mov     eax, Len
                  dec     eax
               .if edx == eax
                     inc     MatchNum
               .endif
               .if !sPos && edx == eax
                     mov     sPos, ebx
               .endif
                  inc     edx
                  dec     ecx
            .else
                  jmp     GetOut
            .endif
         .endw
            inc     ebx
      .endw

GetOut:
         pop     eax
      .if !sPos
            mov     sPos, eax
      .endif
         dec     ebx
         mov     ePos, ebx
;DSPValue hWnd, sPos, 1, 'm'
;DSPValue hWnd, ePos, 1, 'm'
        retn

;---------- [Load the listbox] ----------
Loadbox:
      .if ecx != 44
           call     MoveList
      .endif
      INVOKE     SendMessage, hWndListBox, WM_SETREDRAW, 0, 0
      .if BeepOn
         INVOKE     MessageBeep, MB_ICONEXCLAMATION ;0ffffffffh
      .endif
      INVOKE     ShowWindow, hParListBox, SW_SHOWDEFAULT
      INVOKE     ShowWindow, hWndListBox, SW_SHOWDEFAULT
      INVOKE     SetFocus, hREdit
      INVOKE     SendMessage, hWndListBox, LB_RESETCONTENT, 0, 0
         mov     ebx, sPos
      .if ApiCall
            mov     edi, hApiPointer
      .elseif MessageOn
            mov     edi, hMsgPointer
;      .elseif WordOn
;            mov     edi, hWordPointer
      .elseif WordOn && LoadSW == 1
            mov     edi, hWord01Pointer
      .elseif WordOn && LoadSW == 2
            mov     edi, hWord02Pointer
      .elseif WordOn && LoadSW == 3
            mov     edi, hWord03Pointer
      .else
           retn
      .endif
         mov     esi, [edi+ebx*4].LINE.rpLine
      .while (ebx <= ePos)
            xor     ecx, ecx
            xor     edx, edx
         .while (TRUE)
               mov     al, byte ptr[esi]
            .if al != ',' && al != 0dh
               .if al == '^' || al == '`'
                     mov     dl, al
                     mov     al, 0
               .endif
                  mov     byte ptr szWork[ecx], al
                  mov     byte ptr szWork[ecx+1], 0
                  inc     ecx
            .else
               .break
            .endif
               inc     esi
         .endw
           push     edx
         INVOKE     SendMessage, hWndListBox, LB_ADDSTRING, 0, addr szWork
            pop     edx
            mov     ecx, ebx
         .if dl == '^' || dl == '`'
               xor     ecx, ecx
               mov     cl, dl
               shl     ecx, 16
               mov     cx, bx
         .endif
         INVOKE     SendMessage, hWndListBox, LB_SETITEMDATA, eax, ecx
            inc     ebx
            mov     esi, [edi+ebx*4].LINE.rpLine
         .if !esi
            .break
         .endif
      .endw
      INVOKE     SendMessage, hWndListBox, WM_SETREDRAW, 1, 0
      INVOKE     InvalidateRect, hWndListBox, NULL, TRUE
        retn

;---------- [Move the listbox] ----------
MoveList:
        push     ecx
      INVOKE     GetCaretPos, addr pt
      INVOKE     GetWindowRect, hREdit, addr rect
         mov     eax, rect.left
         add     eax, 4
         pop     ecx
      .if ecx
         .if ecx == -1
               sub     eax, FontWth
         .else
               add     eax, FontWth
         .endif
      .endif
         add     pt.x, eax
         mov     eax, rect.top
         add     eax, 20
         add     pt.y, eax
         mov     ecx, WndHgt
         add     ecx, 2
      INVOKE     MoveWindow, hParListBox, pt.x, pt.y, 150, ecx, TRUE
        retn

;---------- [Set the popup window] ----------
SetPopup:
      INVOKE     GetCaretPos, addr pt
      INVOKE     GetWindowRect, hREdit, addr rect
         mov     eax, rect.left
         add     pt.x, eax
      INVOKE     lstrlen, addr szWork2
        imul     eax, FontWth
         sub     pt.x, eax
         mov     eax, rect.top
         add     eax, 20
         add     pt.y, eax
      .if ApiCall
            mov     eax, pt.x
            mov     SavPosX, eax
      .endif
      .if ApiMsg == 1
            mov     eax, SavPosX
            mov     pt.x, eax
      .endif
      INVOKE     GetDC, hAPIPopup
         mov     hDC, eax
      INVOKE     SelectObject, hDC, hFont
      INVOKE     lstrlen, addr WorkBuff
         mov     ecx, eax
      INVOKE     GetTextExtentPoint32, hDC, addr WorkBuff, ecx, addr ptWH
      INVOKE     ReleaseDC, hAPIPopup, hDC
         add     ptWH.x, 5
         add     ptWH.y, 1
      INVOKE     MoveWindow, hParPopup, pt.x, pt.y, ptWH.x, ptWH.y, TRUE
      INVOKE     MoveWindow, hAPIPopup, 0, 0, ptWH.x, ptWH.y, TRUE
      INVOKE     ShowWindow, hParPopup, SW_SHOWDEFAULT
      INVOKE     ShowWindow, hAPIPopup, SW_SHOWDEFAULT
      INVOKE     SendMessage, hAPIPopup, WM_SETTEXT, 0, addr WorkBuff
        retn

CodeHelper ENDP

;===================================
; Read file Procedure
;===================================
ReadFApi PROC uses edi
LOCAL    hFile:DWORD

      .if ecx == 1
            mov     edi, hApiCall
      .elseif ecx == 2
            mov     edi, hMsgCall
      .elseif ecx == 3
            mov     edi, hWord01Call
      .elseif ecx == 4
            mov     edi, hWord02Call
      .elseif ecx == 5
            mov     edi, hWord03Call
      .else
            mov     eax, -1
            ret
      .endif
         mov     ecx, hBuff
      INVOKE     CreateFile, ecx,\
                 GENERIC_READ or GENERIC_WRITE ,\
                 FILE_SHARE_READ or FILE_SHARE_WRITE,\
                 0, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, 0
      .if eax == -1
         INVOKE     MessageBox, NULL, addr szError31, hBuff,\
                    MB_OK or MB_ICONWARNING or MB_SYSTEMMODAL
            mov     eax, -1
      .else
            mov     hFile, eax
         INVOKE     GetFileSize, hFile, addr BytesR
            mov     ecx, eax
         INVOKE     ReadFile, hFile, edi, ecx, addr BytesR, NULL
            mov     eax, edi
            mov     ecx, BytesR
            mov     byte ptr [eax+ecx], 0
         INVOKE     CloseHandle, hFile
      .endif

         ret

ReadFApi ENDP

