      .586
      .model flat, stdcall     ; 32 bit memory model
      option casemap :none     ; Case sensitive

     include     HexEdit.inc

.data

.code

start:
      INVOKE     GetModuleHandle, NULL
         mov     hInst, eax
      INVOKE     GetCommandLine
         mov     CommandLine, eax
      INVOKE     InitCommonControls

      INVOKE     WinMain, hInst, NULL, CommandLine, SW_SHOWDEFAULT
      INVOKE     ExitProcess, eax

;===================================
;* WinMain procedure
;===================================
WinMain proc hinst:DWORD, hPrevInst, CmdLine, CmdShow

LOCAL     wc:WNDCLASSEX
LOCAL     msg:MSG

;---------- [Fill WNDCLASSEX structure with required variables] ----------
      INVOKE     LoadIcon, hInst, 500    ; icon ID
         mov     hIcon, eax

         mov     wc.cbSize, sizeof WNDCLASSEX
         mov     wc.style, CS_HREDRAW or CS_VREDRAW or CS_BYTEALIGNWINDOW
         mov     wc.lpfnWndProc, offset WndProc
         mov     wc.cbClsExtra, NULL
         mov     wc.cbWndExtra, NULL
       MOVmd     wc.hInstance, hInst
      INVOKE     GetStockObject, HOLLOW_BRUSH
         mov     wc.hbrBackground, COLOR_BTNFACE+1
         mov     wc.lpszMenuName, NULL
         mov     wc.lpszClassName, offset szClassName
       MOVmd     wc.hIcon, hIcon
      INVOKE     LoadCursor, NULL, IDC_ARROW
         mov     wc.hCursor, eax
       MOVmd     wc.hIconSm, 0
      INVOKE     RegisterClassEx, addr wc

;---------- [Register the MDI frame window class] ----------
         mov     wc.lpfnWndProc, offset FrameProc
         mov     wc.hbrBackground, COLOR_WINDOW+1
         mov     wc.lpszMenuName, NULL
         mov     wc.lpszClassName, offset MDIFrameClass
      INVOKE     RegisterClassEx, addr wc

;---------- [Register the MDI child window class] ----------
         mov     wc.lpfnWndProc, offset ChildProc
         mov     wc.hbrBackground, COLOR_WINDOW+1
         mov     wc.lpszClassName, offset MDIChildClass
      INVOKE     RegisterClassEx, addr wc
      INVOKE     LoadMenu, hInst, 603
         mov     hChildMenu, eax

;---------- [Center window at the following size] ----------
         mov     Wwd, 572 ;570
         mov     Wht, 435
        call     CenterWin
      INVOKE     CreateWindowEx, WS_EX_CLIENTEDGE, addr szClassName, addr szUntitled,
                 WS_OVERLAPPEDWINDOW, WxPos, WyPos, Wwd, Wht, 0, 0, hInst, 0
         mov     hWnd, eax

      INVOKE     LoadMenu, hInst, 600  ; Menu ID
         mov     hMenu, eax
      INVOKE     SetMenu, hWnd, eax

      INVOKE     LoadMenu, hInst, 601
      INVOKE     GetSubMenu, eax, 0
         mov     hSubMenu, eax

      INVOKE     ShowWindow, hWnd, SW_SHOWNORMAL
      INVOKE     UpdateWindow, hWnd
      INVOKE     LoadAccelerators, hInst, 4114
         mov     hAccel, eax

;---------- [Loop until PostQuitMessage is sent] ----------
      .while TRUE
         INVOKE     GetMessage, addr msg, 0, 0, 0
         .break .if (!eax)
         INVOKE     TranslateAccelerator, hWnd, hAccel, addr msg
         INVOKE     TranslateMessage, addr msg
         INVOKE     DispatchMessage, addr msg
      .endw
   INVOKE     DestroyMenu, hChildMenu
         mov     eax, msg.wParam
         ret
WinMain endp

;===================================
; WndProc procedure
;===================================
WndProc proc  uses ebx edx esi edi  hwnd:DWORD, uMsg, wParam, lParam

LOCAL     tbh:DWORD, sbh, Cnt, Chg
LOCAL     tm:TEXTMETRIC
LOCAL     rect:RECT
LOCAL     rTest:RECT

;_______________________________________________________________________________________
      .if uMsg == WM_COMMAND
            mov     eax, wParam
            and     eax, 0000ffffh
            mov     wParam, eax

;---------- [Menu and Toolbar commands] ----------
;----- [New
         .if wParam == 1000
            INVOKE     SendMessage, hREdit, EM_GETMODIFY, 0, 0
            .if eax != FALSE
               INVOKE     Confirmation, hwnd
                  .if eax == IDYES
                       call     SaveFile
                  .elseif eax == IDCANCEL
                        mov     eax, 0
                        ret
                  .endif
            .endif
            INVOKE     SetWindowText, hSplit1, NULL
            INVOKE     SetWindowText, hREdit, NULL
            INVOKE     SetWindowText, hSplit3, NULL
            INVOKE     SetWindowText, hWorkC, NULL
            INVOKE     SetWindowText, hWorkN, NULL
            INVOKE     SetWindowText, hwnd, addr szUntitled
            INVOKE     SendMessage, hwndStat, SB_SETTEXT, 0, NULL

;----- [Open
         .elseif wParam == 1001
            INVOKE     ReadEM, addr szFileName, hREdit

;----- [Save
         .elseif wParam == 1002
              call     SaveFile

;----- [Save as
         .elseif wParam == 1003
              call     SaveFileAs

;----- [Cut
         .elseif wParam == 1100
Cut:
            INVOKE     SendMessage, hREdit, EM_EXGETSEL, 0, addr cr
            INVOKE     SendMessage, hREdit, WM_CUT, 0, 0
            INVOKE     SendMessage, hWorkC, WM_CUT, 0, 0
            INVOKE     SendMessage, hWorkN, WM_CUT, 0, 0
              call     EnableDisableMenuTool
             MOVmd     TextLen, BytesOut
            INVOKE     REditProc, hREdit, 4455, wParam, lParam

;----- [Copy
         .elseif wParam == 1101
            INVOKE     SendMessage, hREdit, WM_COPY, 0, 0
              call     EnableDisableMenuTool

;----- [Paste
         .elseif wParam == 1102
              call     Validate  ; Validate the Clipboard contents
            .if eax == 1
               INVOKE     MessageBox, hWnd, addr szError1, addr szDisplayName, MB_OK
                  jmp     Ret0
            .elseif eax == 2
               INVOKE     MessageBox, hWnd, addr szError2, addr szDisplayName, MB_OK
                  jmp     Ret0
            .endif
            INVOKE     SendMessage, hREdit, EM_EXGETSEL, 0, addr cr
            INVOKE     SendMessage, hREdit, WM_PASTE, 0, 0
            INVOKE     SendMessage, hWorkC, WM_PASTE, 0, 0
            INVOKE     SendMessage, hWorkN, WM_PASTE, 0, 0
              call     EnableDisableMenuTool
             MOVmd     TextLen, BytesOut
            INVOKE     REditProc, hREdit, 4455, wParam, lParam

;----- [Delete
         .elseif wParam == 1103
               jmp     Cut

;----- [Undo
         .elseif wParam == 1104
UndoAgain:
            INVOKE     SendMessage, hREdit, EM_CANUNDO, 0, 0
               cmp     eax, TRUE
               jne     NoUndo
            INVOKE     SendMessage, hREdit, WM_UNDO, 0, 0
            INVOKE     SendMessage, hWorkC, WM_UNDO, 0, 0
            INVOKE     SendMessage, hWorkN, WM_UNDO, 0, 0
              call     CopyLine
            INVOKE     SendMessage, hREdit, EM_EXGETSEL, 0, addr cr
            INVOKE     SendMessage, hREdit, WM_GETTEXTLENGTH, 0, 0
            .if cr.cpMax == eax && cr.cpMin == 0
                  jmp     UndoAgain
            .endif
NoUndo:
              call     EnableDisableMenuTool

;----- [Redo
         .elseif wParam == 1105
               and     Hold, 0
RedoAgain:
            INVOKE     SendMessage, hREdit, EM_REDO, 0, 0
            INVOKE     SendMessage, hWorkC, EM_REDO, 0, 0
            INVOKE     SendMessage, hWorkN, EM_REDO, 0, 0
              call     CopyLine
            INVOKE     SendMessage, hREdit, EM_EXGETSEL, 0, addr cr
            INVOKE     SendMessage, hREdit, WM_GETTEXTLENGTH, 0, 0
               dec     eax

               mov     ebx, cr.cpMax
               sub     ebx, cr.cpMin
            .if ebx > 40 && cr.cpMin == 0 && cr.cpMax < eax
                  jmp     RedoAgain
            .endif

            .if cr.cpMax == eax && cr.cpMin == eax && Hold < 2
                  add     Hold, 1
                  jmp     RedoAgain
            .endif
              call     EnableDisableMenuTool

;----- [Find
         .elseif wParam == 1106
            INVOKE     SendMessage, hREdit, EM_GETSELTEXT, 0, addr szBuff
            .if !Hex
               INVOKE     WriteEM, 0, 1
            .else
               INVOKE     lstrcpy, addr szFind, addr szBuff
            .endif

            INVOKE     CreateDialogParam, hInst, 4200, hwnd, offset FindReplace, 4200
               cmp     eax, -1       ; Canceled?
                je     Ret0          ; yes, then return
            INVOKE     SetDlgItemText, hFRDlg, 1206, addr szFind
              call     EnableDisableMenuTool
               mov     w4, WM_CHAR
            INVOKE     FindReplace, hFRDlg, WM_COMMAND, 1206, 4200

;----- [Find next
         .elseif wParam == 1107 || wParam == VK_F3
               and     UD, 0
               mov     Flag, 1
               mov     ft.chrg.cpMax, -1
FindPrev:
            .if MatchCase
               INVOKE     SendMessage, hWorkC, EM_EXGETSEL, 0, addr cr
            .else
               INVOKE     SendMessage, hWorkN, EM_EXGETSEL, 0, addr cr
            .endif
            INVOKE     SendMessage, hREdit, EM_GETSELTEXT, 0, addr szWork

               xor     esi, esi
               xor     edi, edi
            .while (eax)
                  mov     bl, byte ptr szWork[esi]
               .if bl != 20h
                     mov     byte ptr szFind[edi], bl
                     inc     edi
               .endif
                  inc     esi
                  dec     eax
            .endw
               mov     byte ptr szFind[edi], 0

            INVOKE     lstrlen, addr szFind
               mov     Len, eax
            .if !UD 
                  add     cr.cpMin, 1
            .endif
             MOVmd     ft.chrg.cpMin, cr.cpMin
               lea     eax, offset szFind
               mov     ft.lpstrText, eax
            .if MatchCase
               INVOKE     Find, hWorkC, Flag, addr szFind, UD
            .else
                  mov     ecx, Len
                  lea     esi, szFind
               .if ecx
                    call     UpperCase
               .endif
               INVOKE     Find, hWorkN, Flag, addr szFind, UD
            .endif
              call     EnableDisableMenuTool
               jmp     Ret0

;----- [Find previous
         .elseif wParam == 1108
               mov     UD, 1
               and     Flag, 0
               mov     ft.chrg.cpMax, 0
               jmp     FindPrev

;----- [Replace
         .elseif wParam == 1109
            INVOKE     SendMessage, hREdit, EM_GETSELTEXT, 0, addr szBuff
            .if !Hex
               INVOKE     WriteEM, 0, 1
            .else
               INVOKE     lstrcpy, addr szFind, addr szBuff
            .endif
            INVOKE     CreateDialogParam, hInst, 4201, hwnd, offset FindReplace, 4201
               cmp     eax, -1       ; Canceled?
                je     Ret0          ; yes, then return
            INVOKE     SetDlgItemText, hFRDlg, 1206, addr szFind
              call     EnableDisableMenuTool
               mov     w4, WM_CHAR
            INVOKE     FindReplace, hFRDlg, WM_COMMAND, 1206, 4201

;----- [Hex Renumber
         .elseif wParam == 1110
            INVOKE     SendMessage, hwndTool, TB_CHECKBUTTON, 1110, MF_CHECKED or MF_BYCOMMAND
            INVOKE     SendMessage, hwndTool, TB_CHECKBUTTON, 1111, MF_UNCHECKED or MF_BYCOMMAND
            INVOKE     CheckDlgButton, hVDlg, 21, BST_CHECKED      ; Resets the appropiate radio button
            INVOKE     CheckDlgButton, hVDlg, 22, BST_UNCHECKED    ; Resets the appropiate radio button
               mov     HexDec, 16
              call     Renumber

;----- [Dec Renumber
         .elseif wParam == 1111
            INVOKE     SendMessage, hwndTool, TB_CHECKBUTTON, 1111, MF_CHECKED or MF_BYCOMMAND
            INVOKE     SendMessage, hwndTool, TB_CHECKBUTTON, 1110, MF_UNCHECKED or MF_BYCOMMAND
            INVOKE     CheckDlgButton, hVDlg, 22, BST_CHECKED      ; Resets the appropiate radio button
            INVOKE     CheckDlgButton, hVDlg, 21, BST_UNCHECKED    ; Resets the appropiate radio button
               mov     HexDec, 10
              call     Renumber

;----- [Tab Control
         .elseif wParam == 1120
            INVOKE     CreateDialogParam, hInst, 4000, hwnd, offset TabCtlDlg, 0

;----- [HexEdit
         .elseif wParam == 1200
            INVOKE     WinExec, addr szHexEdit, SW_SHOWNORMAL      ; Exec a program

;----- [Exit
         .elseif wParam == 1300
            INVOKE     SendMessage, hWnd, WM_SYSCOMMAND, SC_CLOSE, NULL

;----- [Notify
         .elseif wParam == 1801
            INVOKE     CheckMenuItem, hMenu, 1801, MF_BYCOMMAND
               and     InsNotify, 0
            .if eax == MF_CHECKED
               INVOKE     CheckMenuItem, hMenu, 1801, MF_UNCHECKED
            .else
                   or     InsNotify, 1
               INVOKE     CheckMenuItem, hMenu, 1801, MF_CHECKED
            .endif
         .elseif wParam == 1802
            INVOKE     CheckMenuItem, hMenu, 1802, MF_BYCOMMAND
               and     DelNotify, 0
            .if eax == MF_CHECKED
               INVOKE     CheckMenuItem, hMenu, 1802, MF_UNCHECKED
            .else
                   or     DelNotify, 1
               INVOKE     CheckMenuItem, hMenu, 1802, MF_CHECKED
            .endif

;----- [Converter
         .elseif wParam == 1803
            INVOKE     CreateDialogParam, hInst, 4808, hwnd, offset ConvertDlg, 0

;----- [Calculator
         .elseif wParam == 1804
            INVOKE     WinExec, addr szCalc, SW_SHOWNORMAL         ; Exec a program

;----- [Help
         .elseif wParam == 1900
            INVOKE     WinHelp, hWnd, addr szHelp, HELP_CONTENTS, 0

;----- [About
         .elseif wParam == 1901
            INVOKE     ShellAbout, hWnd, addr szDisplayName, addr AboutMsg, hIcon


;----- [Goto offset
         .elseif wParam == 2000
            INVOKE     DialogBoxParam, hInst, 4100, hwnd, offset GoToOff, 0

         .endif
;---------- [End of Commands] ----------

;_______________________________________________________________________________________
      .elseif uMsg == WM_SETFOCUS
         INVOKE     SetFocus, hREdit

;_______________________________________________________________________________________
      .elseif uMsg == WM_SYSCOLORCHANGE
         INVOKE     DestroyWindow, hwndTool
            jmp     CreateTool

;_______________________________________________________________________________________
      .elseif uMsg == WM_CREATE
         INVOKE     LoadLibrary, addr RichEdDLL ;Version 2\3

;         INVOKE     GetStockObject, OEM_FIXED_FONT     ;OEM_FIXED_FONT  ;SYSTEM_FIXED_FONT  ;ANSI_FIXED_FONT
;            mov     hSFont, eax
         INVOKE     lstrcpy, addr lf.lfFaceName, addr FontMS
            mov     lf.lfHeight, -7 ;-13
            mov     lf.lfWeight, 500
         INVOKE     CreateFontIndirect, addr lf
            mov     hSFont, eax

           call     FontSize

;---------- [Create the status bar window] ----------
         INVOKE     CreateStatusWindow, WS_CHILD or WS_VISIBLE or\
                    SBS_SIZEGRIP, 0, hwnd, 200
            mov     hwndStat, eax
            mov     [sbParts+0], 165    ; pixels from left
            mov     [sbParts+4], 265    ; pixels from left
            mov     [sbParts+8], 340    ; pixels from left
            mov     [sbParts+12], -1    ; last part
         INVOKE     SendMessage, hwndStat, SB_SETPARTS, 4, addr sbParts

;---------- [Create the main tool bar] ----------
CreateTool:
         INVOKE     CreateWindowEx, 0, addr ToolClass, 0,
                    WS_CHILD or WS_VISIBLE or TBSTYLE_TOOLTIPS or CCS_NOPARENTALIGN or CCS_NORESIZE or\
                    CCS_ADJUSTABLE or TBSTYLE_FLAT, 0, 0, 1000, 28, hwnd, 0, hInst, 0
            mov     hwndTool, eax

         INVOKE     LoadBitmap, hInst, 750
            mov     hTbBmp, eax

         INVOKE     SendMessage, hwndTool, TB_BUTTONSTRUCTSIZE, sizeof TBBUTTON, 0
            mov     ecx, 16  ; loword = bitmap Width
            mov     eax, 16  ; hiword = bitmap Height
            shl     eax, 16
            mov     ax, cx
            mov     bSize, eax
         INVOKE     SendMessage, hwndTool, TB_SETBITMAPSIZE, 0, bSize

            mov     tbab.hInst, 0
          MOVmd     tbab.nID, hTbBmp
         INVOKE     SendMessage, hwndTool, TB_ADDBITMAP, 17, addr tbab  ;15
         INVOKE     SendMessage, hwndTool, TB_SETBUTTONSIZE, 0, bSize

         TBButt     hwndTool, 0,  1000, 0
         TBButt     hwndTool, 1,  1001, 0
         TBButt     hwndTool, 2,  1002, 0
          TBSep     hwndTool
         TBButt     hwndTool, 3,  1100, 0
         TBButt     hwndTool, 4,  1101, 0
         TBButt     hwndTool, 5,  1102, 0
         TBButt     hwndTool, 6,  1103, 0
         TBButt     hwndTool, 7,  1104, 0
         TBButt     hwndTool, 8,  1105, 0
          TBSep     hwndTool
         TBButt     hwndTool, 9,  1106, 0
         TBButt     hwndTool, 10, 1107, 0
         TBButt     hwndTool, 11, 1108, 0
         TBButt     hwndTool, 12, 1109, 0
          TBSep     hwndTool
         TBButt     hwndTool, 13, 1110, 0
         TBButt     hwndTool, 14, 1111, 0
          TBSep     hwndTool
         TBButt     hwndTool, 15, 1200, 0
         TBButt     hwndTool, 16, 1300, 0

;---------- [Create the GoTo tool bar] ----------
         INVOKE     CreateWindowEx, 0, addr ToolClass, 0,
                    WS_CHILD or WS_VISIBLE or TBSTYLE_TOOLTIPS or CCS_NOPARENTALIGN or\
                    CCS_NORESIZE or CCS_ADJUSTABLE or TBSTYLE_FLAT or TBSTYLE_LIST or CCS_NODIVIDER,\
                    430, 0, 1200, 24, hwndTool, 72, hInst, NULL
            mov     w4, eax
   
         INVOKE     lstrcpy, addr lf.lfFaceName, addr FontMS
            mov     lf.lfHeight, -12
            mov     lf.lfWeight, 600
         INVOKE     CreateFontIndirect, addr lf
         INVOKE     SendMessage, w4, WM_SETFONT, eax, 1
         INVOKE     SendMessage, w4, TB_BUTTONSTRUCTSIZE, sizeof TBBUTTON, 0
            mov     eax, 00100000h
         INVOKE     SendMessage, w4, TB_SETBITMAPSIZE, 0, eax
         INVOKE     SendMessage, w4, TB_ADDSTRING, 0, addr buttxt1
         TBButt     w4, 0, 2000, eax

;---------- [Create the Static window] ----------
         INVOKE     CreateWindowEx, WS_EX_WINDOWEDGE, addr StatClass, 0,
                    WS_CHILD or WS_VISIBLE or SS_BLACKRECT or SS_SUNKEN,
                    0, 30, 100, 200, hwnd, 40, hInst, NULL
            mov     hStatM, eax

;---------- [Create a test window to get pixels per char] ----------
MOVmd     Hold, hwnd
           call     WinSize

;---------- [Create the Offset window] ----------
           push     w1W
         INVOKE     CreateWindowEx, 0, addr richedit, 0,
                    WS_CHILD or WS_VISIBLE or ES_MULTILINE or ES_READONLY,
                    0, 30, w1W, 200, hwnd, 41, hInst, NULL
            mov     hSplit1, eax
         INVOKE     SetWindowLong, hSplit1, GWL_WNDPROC, REditProc
            mov     hREditSub, eax
         INVOKE     SendMessage, hSplit1, WM_SETFONT, hFont, TRUE

;---------- [Create the REdit window] ----------   or ES_AUTOVSCROLL
            pop     ebx
            inc     ebx
           push     w2W
         INVOKE     CreateWindowEx, 0, addr richedit, 0,
                    WS_CHILD or WS_VISIBLE or ES_MULTILINE or ES_NOHIDESEL or ES_SAVESEL,
                    ebx, 30, w2W, 200, hwnd, 42, hInst, NULL
            mov     hREdit, eax
         INVOKE     SetWindowLong, hREdit, GWL_WNDPROC, REditProc
            mov     hREditSub, eax
         INVOKE     SendMessage, hREdit, WM_SETFONT, hFont, TRUE
         INVOKE     SendMessage, hREdit, EM_LIMITTEXT, 2000000, 0

;---------- [Create the Splitter3 window] ----------
            pop     ebx
            inc     ebx
            mov     ecx, w3W
            add     ecx, 17 ;20
         INVOKE     CreateWindowEx, WS_EX_TOPMOST, addr richedit, 0,
                    WS_CHILD or WS_VISIBLE or ES_MULTILINE or ES_NOHIDESEL or ES_READONLY or WS_VSCROLL,
                    ebx, 30, ecx, 200, hwnd, 43, hInst, NULL ;ebx, 30, w3W, 200
            mov     hSplit3, eax
         INVOKE     SetWindowLong, hSplit3, GWL_WNDPROC, SplitProc
            mov     hSplitSub, eax
         INVOKE     SendMessage, hSplit3, WM_SETFONT, hFont, TRUE ;hSFont
         INVOKE     SendMessage, hSplit3, EM_LIMITTEXT, 1000000, 0

            mov     sci.cbSize, sizeof sci
            mov     sci.fMask, SIF_ALL            ; Initilize scroll info

           call     EnableDisableMenuTool

;---------- [Create the Work windows] ----------
            mov     ebx, w4W
            add     ebx, 19
           push     ebx
;----- [Case sensitive or WS_VISIBLE
         INVOKE     CreateWindowEx, 0, addr richedit, 0,
                    WS_POPUP or WS_VSCROLL or ES_MULTILINE or ES_NOHIDESEL or\
                    ES_SAVESEL,
                    WxPos, WyPos, ebx, 300, 0, 0, hInst, 0   ;!!!!!!!!!!!!!!!!!!!!!!!!!! hwnd
            mov     hWorkC, eax
            pop     ebx
           push     ebx
         INVOKE     SetWindowPos, hWorkC, HWND_BOTTOM, WxPos, WyPos, ebx, 300, SWP_SHOWWINDOW
         INVOKE     SendMessage, hWorkC, EM_LIMITTEXT, 2000000, 0
         INVOKE     SendMessage, hWorkC, WM_SETFONT, hFont, TRUE
         INVOKE     ShowWindow, hWorkC, SW_HIDE

            pop     ebx
           push     ebx
;----- [Non-case sensitive or WS_VISIBLE
         INVOKE     CreateWindowEx, 0, addr richedit, 0,
                    WS_POPUP or WS_VSCROLL or ES_MULTILINE or ES_NOHIDESEL or\
                    ES_SAVESEL,
                    WxPos, WyPos, ebx, 300, 0, 0, hInst, 0
            mov     hWorkN, eax
            pop     ebx
         INVOKE     SetWindowPos, hWorkN, HWND_BOTTOM, WxPos, WyPos, ebx, 300, SWP_SHOWWINDOW
         INVOKE     SendMessage, hWorkN, EM_LIMITTEXT, 2000000, 0
         INVOKE     SendMessage, hWorkN, WM_SETFONT, hFont, TRUE
         INVOKE     ShowWindow, hWorkN, SW_HIDE

;_______________________________________________________________________________________
      .elseif uMsg == WM_WINDOWPOSCHANGED
            mov     ebx, lParam    ; Get pointer to WINDOWPOS
          MOVmd     WxPos, (WINDOWPOS ptr [ebx]).x
          MOVmd     WyPos, (WINDOWPOS ptr [ebx]).y
            mov     NoSize, 1

;_______________________________________________________________________________________
      .elseif uMsg == WM_SIZE
            and     wHth, 0
         INVOKE     SendMessage, hREdit, EM_GETMODIFY, 0, 0
            mov     Chg, eax
         .if !NoSize
               jmp     WorkWindows
         .endif
         INVOKE     SendMessage, hwndTool, TB_AUTOSIZE, 0, 0
         INVOKE     MoveWindow, hwndStat, 0, 0, 0, 0, TRUE

            mov     eax, lParam
            and     eax, 0000ffffh
            add     eax, 12
            mov     Wwd, eax
            mov     eax, lParam
            shr     eax, 16
            add     eax, 50 
            and     eax, 0000ffffh
            mov     Wht, eax

          finit
            fld     PixPC
           fild     LineCnt
           fmul     ST(0), ST(1)
          fistp     w4
          MOVmd     w2W, w4
            mov     eax, w1W
            add     w4, eax
            mov     eax, w3W
            add     w4, eax
            add     w4, 28     ; w4 = the total width of the main window

         INVOKE     GetClientRect, hwnd, addr rect
            mov     ebx, rect.right
            add     ebx, 12
           push     Wwd
         .if ebx > Wwd
               mov     Wwd, ebx
         .endif
            mov     eax, Wwd
            pop     ebx
         .if eax > w4 && ebx > 12 && bytesread
               sub     eax, w4
               add     w4, eax
         .endif

         INVOKE     MoveWindow, hwnd, WxPos, WyPos, w4, Wht, TRUE

         INVOKE     GetClientRect, hwndTool, addr rect
          MOVmd     tbh, rect.bottom
         INVOKE     GetClientRect, hwndStat, addr rect
          MOVmd     sbh, rect.bottom
         INVOKE     GetClientRect, hwnd, addr rect
            mov     ebx, rect.right
            mov     ecx, rect.bottom
            mov     eax, tbh
            sub     ecx, eax
            mov     eax, sbh
            sub     ecx, eax
            add     tbh, 2
            mov     wHth, ecx
            sub     wHth, 2
            mov     edx, tbh
            sub     edx, 3
            add     ecx, 2
            add     ebx, 1
         INVOKE     MoveWindow, hStatM, 0, edx, ebx, 4, TRUE

;---------- [Size the Offset window] ----------
         INVOKE     GetClientRect, hSplit1, addr rect
         INVOKE     MoveWindow, hSplit1, 0, tbh, rect.right, wHth, TRUE
            and     xPos, 0
         .if bytesread
               mov     Split1, 1
             MOVmd     Hold, rect.right
            INVOKE     SizeEM, hSplit1, 9, xPos, tbh, Hold, wHth, 0
               and     Split1, 0
         .else
               mov     eax, rect.right
               add     xPos, eax
         .endif
            inc     xPos
         INVOKE     SendMessage, hSplit1, EM_SETBKGNDCOLOR, 0, c1B
          MOVmd     charF.crTextColor, c1T
          MOVmd     charF.crBackColor, 0
            mov     charF.dwMask, CFM_FACE or CFM_SIZE or CFM_COLOR
         INVOKE     SendMessage,  hSplit1, EM_SETCHARFORMAT, SCF_ALL, offset charF

;---------- [Size the Edit window] ----------
            mov     ebx, w2W
            sub     ebx, PPC
         INVOKE     MoveWindow, hREdit, xPos, tbh, ebx, wHth, TRUE
         INVOKE     GetClientRect, hREdit, addr rect
         .if bytesread
             MOVmd     Hold, rect.right
            INVOKE     SizeEM, hREdit, LineCnt, xPos, tbh, Hold, wHth, 0
         .else
               mov     eax, rect.right
               add     xPos, eax
         .endif
         INVOKE     SendMessage, hREdit, EM_SETBKGNDCOLOR, 0, c2B
          MOVmd     charF.crTextColor, c2T
          MOVmd     charF.crBackColor, 0
            mov     charF.dwMask, CFM_FACE or CFM_SIZE or CFM_COLOR
         INVOKE     SendMessage,  hREdit, EM_SETCHARFORMAT, SCF_ALL, offset charF
         .if NoSize
            INVOKE     SendMessage, hREdit, EM_EMPTYUNDOBUFFER, 0, 0
            INVOKE     SendMessage, hWorkC, EM_EMPTYUNDOBUFFER, 0, 0
            INVOKE     SendMessage, hWorkN, EM_EMPTYUNDOBUFFER, 0, 0
            INVOKE     SendMessage, hREdit, EM_SETMODIFY, 0, 0
         .endif

;---------- [Size the Ascii window] ----------
            inc     xPos
         INVOKE     GetClientRect, hSplit3, addr rect
          MOVmd     Hold, rect.right
         INVOKE     MoveWindow, hSplit3, xPos, tbh, Hold, wHth, TRUE
         INVOKE     GetClientRect, hSplit3, addr rect
           push     xPos
         .if bytesread
             MOVmd     Hold, rect.right
            INVOKE     SizeEM, hSplit3, 17, xPos, tbh, Hold, wHth, 0
         .endif

            pop     xPos
         INVOKE     GetClientRect, hwnd, addr rect
            mov     ebx, rect.right
            sub     ebx, xPos
         INVOKE     MoveWindow, hSplit3, xPos, tbh, ebx, wHth, TRUE

         .if bytesread
            INVOKE     GetClientRect, hwnd, addr rect
             MOVmd     Hold, rect.right

LoopSplit3:
               mov     word ptr szWork, 60
            INVOKE     SendMessage, hSplit3, EM_GETLINE, 0, addr szWork
            .if eax < 17 || eax > 17
               .if eax < 17
                     inc     Hold
               .else
                     dec     Hold
               .endif
                  add     Hold, 12
               INVOKE     MoveWindow, hwnd, WxPos, WyPos, Hold, Wht, TRUE
                  jmp     LoopSplit3
            .endif
         .endif

         INVOKE     SendMessage, hSplit3, EM_SETBKGNDCOLOR, 0, c3B
          MOVmd     charF.crTextColor, c3T
          MOVmd     charF.crBackColor, 0
         INVOKE     SendMessage,  hSplit3, EM_SETCHARFORMAT, SCF_ALL, offset charF

;---------- [Size the Work windows] ----------
WorkWindows:
         .if bytesread && SizeWork
               and     SizeWork, 0

            INVOKE     SendMessage, hWorkC, EM_LINELENGTH, 0, 0
               cmp     eax, 32
                je     ChkN

            INVOKE     ShowWindow, hWorkC, SW_SHOWNORMAL
            INVOKE     GetClientRect, hWorkC, addr rect
             MOVmd     Hold, rect.right
            .if !wHth
                MOVmd     wHth, rect.bottom
            .endif
            INVOKE     GetWindowRect, hwnd, addr rect
            INVOKE     SizeEM, hWorkC, 32, rect.left, rect.top, Hold, wHth, 1
            INVOKE     ShowWindow, hWorkC, SW_HIDE

ChkN:
            INVOKE     GetClientRect, hWorkN, addr rect
            INVOKE     SendMessage, hWorkN, EM_LINELENGTH, 0, 0
               cmp     eax, 32
                je     NoNSize

            INVOKE     ShowWindow, hWorkN, SW_SHOWNORMAL
            INVOKE     GetClientRect, hWorkN, addr rect
             MOVmd     Hold, rect.right
            .if !wHth
                MOVmd     wHth, rect.bottom
            .endif
            INVOKE     GetWindowRect, hwnd, addr rect
            INVOKE     SizeEM, hWorkN, 32, rect.left, rect.top, Hold, wHth, 1
            INVOKE     ShowWindow, hWorkN, SW_HIDE
               and     NoSize, 0
         .endif

NoNSize:
         .if HexDec == 16
            INVOKE     SendMessage, hwndTool, TB_CHECKBUTTON, 1110, MF_CHECKED or MF_BYCOMMAND
            INVOKE     SendMessage, hwndTool, TB_CHECKBUTTON, 1111, MF_UNCHECKED or MF_BYCOMMAND
         .else
            INVOKE     SendMessage, hwndTool, TB_CHECKBUTTON, 1111, MF_CHECKED or MF_BYCOMMAND
            INVOKE     SendMessage, hwndTool, TB_CHECKBUTTON, 1110, MF_UNCHECKED or MF_BYCOMMAND
         .endif
           call     ScreenLines

         .if InsNotify
            INVOKE     CheckMenuItem, hMenu, 1801, MF_CHECKED
         .endif
         .if DelNotify
            INVOKE     CheckMenuItem, hMenu, 1802, MF_CHECKED
         .endif
         INVOKE     SendMessage, hREdit, EM_SETMODIFY, Chg, 0
           call     EnableDisableMenuTool

;_______________________________________________________________________________________
      .elseif uMsg == WM_PAINT
            jmp     DefWinProc

;_______________________________________________________________________________________
      .elseif uMsg == WM_NOTIFY
            mov     ebx, lParam                      ; Get pointer to NMHDR
            mov     eax, (NMHDR ptr [ebx]).code
         .if eax == TTN_NEEDTEXT
               mov     eax, (NMHDR ptr [ebx]).idFrom ; Resource id
            INVOKE     LoadString, hInst, eax, addr szBuff, lengthof szBuff
               mov     ebx, lParam                   ; Buffer addr
               mov     (TOOLTIPTEXT ptr [ebx]).lpszText, offset szBuff
               jmp     Ret0
         .endif


;_______________________________________________________________________________________
      .elseif uMsg == WM_CLOSE
         INVOKE     SendMessage, hREdit, EM_GETMODIFY ,0, 0
         .if eax != FALSE
            INVOKE     Confirmation, hWnd
            .if eax == IDYES
                 call     SaveFile
            .elseif eax == IDCANCEL
                  mov     eax, 0
                  ret
            .endif
         .endif

;_______________________________________________________________________________________
      .elseif uMsg == WM_DESTROY
         INVOKE     PostQuitMessage, NULL
            xor     eax, eax
            ret
      .endif

DefWinProc:
      INVOKE     DefWindowProc, hwnd, uMsg, wParam, lParam
         jmp     Finish

Ret0:
         xor     eax, eax
Finish:
         ret

WndProc endp

;===================================
; FrameProc procedure
;===================================
FrameProc proc hFrame:DWORD, uMsg, wParam, lParam
LOCAL     rect:RECT

      .if uMsg == WM_PAINT || uMsg == WM_SIZE
            jmp     AlignSize

      .elseif uMsg == WM_CLOSE
         INVOKE     SendMessage, hwndClient, WM_MDIDESTROY, hwndChild1, 0
         INVOKE     SendMessage, hwndClient, WM_MDIDESTROY, hwndChild2, 0
         INVOKE     DestroyWindow, hwndFrame
         INVOKE     LoadMenu, hInst, 602
            mov     hFrameMenu, eax
            jmp     Ret0

;      .elseif uMsg == WM_DESTROY || WM_NCDESTROY
;            jmp     Ret0

      .elseif uMsg == WM_COMMAND
         .if wParam == 406
AlignSize:
            INVOKE     SetFocus, hwndChild1
            INVOKE     SendMessage, hwndClient, WM_MDITILE, MDITILE_HORIZONTAL, 0
            INVOKE     GetClientRect, hwndChild1, addr rect
            INVOKE     MoveWindow, hEdit1, rect.left, rect.top, rect.right, rect.bottom, TRUE
            INVOKE     MoveWindow, hEdit2, rect.left, rect.top, rect.right, rect.bottom, TRUE
         .endif
      .endif

      INVOKE     DefFrameProc, hFrame, hwndClient, uMsg, wParam, lParam       
         ret

Ret0:
         xor     eax, eax
         ret
FrameProc endp

;===================================
; ChildProc procedure
;===================================
ChildProc proc hChild:DWORD, uMsg, wParam, lParam
LOCAL     rect:RECT

      .if uMsg == WM_MDIACTIVATE
            mov     eax, lParam
         .if eax == hChild
            INVOKE     GetSubMenu, hChildMenu, 1
               mov     edx,eax
            INVOKE     SendMessage, hwndClient, WM_MDISETMENU, hChildMenu, edx
         .else
            INVOKE     GetSubMenu, hFrameMenu, 1
               mov     edx, eax
            INVOKE     SendMessage, hwndClient, WM_MDISETMENU, hFrameMenu, edx
         .endif
            INVOKE     DrawMenuBar, hwndFrame

      .elseif uMsg == WM_SIZE
         INVOKE     GetClientRect, hChild, addr rect
            mov     eax, hChild
         .if eax == hwndChild1
            INVOKE     MoveWindow, hEdit1, rect.left, rect.top, rect.right, rect.bottom, TRUE
         .else
            INVOKE     MoveWindow, hEdit2, rect.left, rect.top, rect.right, rect.bottom, TRUE
         .endif

      .elseif uMsg == WM_CLOSE

      .else
         INVOKE     DefMDIChildProc, hChild, uMsg, wParam, lParam
            ret
      .endif

Ret0:
         xor     eax, eax
         ret
ChildProc endp

;======================================
;* CenterWin procedure
;======================================
CenterWin proc
      INVOKE     GetSystemMetrics, SM_CXSCREEN
         sub     eax, Wwd
         shr     eax, 1
         mov     WxPos, eax
      INVOKE     GetSystemMetrics, SM_CYSCREEN
         sub     eax, Wht
         shr     eax,1
         mov     WyPos, eax
         ret
CenterWin endp

;=============================================================
; Size windows to line length
;=============================================================
SizeEM   proc  hwnd:DWORD, Cnt, xP, yP, wW, wH, WorkWnd
LOCAL     rect:RECT
LOCAL     hPos:DWORD, IncS, DecS

         and     IncS, 0
         and     DecS, 0
       MOVmd     hPos, xPos

LoopSize:
         mov     word ptr szWork, 60
      INVOKE     SendMessage, hwnd, EM_GETLINE, 0, addr szWork
      .if eax < Cnt || eax > Cnt
         .if eax < Cnt
               inc     wW
               mov     IncS, 1
         .else
               dec     wW
               mov     DecS, 1
         .endif

         .if IncS && DecS && !WorkWnd
               add     wW, 10
            INVOKE     MoveWindow, hwnd, xP, yP, wW, wH, TRUE
               jmp     GetOut
         .endif

         INVOKE     MoveWindow, hwnd, xP, yP, wW, wH, TRUE
            jmp     LoopSize
      .endif

GetOut:
      .if WorkWnd
            ret
      .endif
      INVOKE     GetClientRect, hwnd, addr rect
         mov     eax, rect.right
         add     xPos, eax
         add     rect.left, 5
         sub     rect.right, 5
      INVOKE     SendMessage, hwnd, EM_SETRECT, 0, addr rect
      .if IncS && DecS
            ret
      .endif
         mov     word ptr szWork, 60
      INVOKE     SendMessage, hwnd, EM_GETLINE, 0, addr szWork
      .if eax < Cnt || eax > Cnt
          MOVmd     xPos, hPos
            jmp     LoopSize
      .endif
         ret
SizeEM   endp

;=============================================================
; Enable or disable the items in the edit menu and toolbar
;=============================================================
EnableDisableMenuTool PROC
LOCAL     tempword:DWORD

      INVOKE     SendMessage, hREdit, EM_CANUNDO, 0, 0
         cmp     eax, TRUE
         jne     EdMu1
         mov     tempword, MF_ENABLED
         jmp     EdMu2
EdMu1:   mov     tempword, MF_GRAYED
EdMu2:
      INVOKE     EnableMenuItem, hMenu, 1104, tempword     ; Undo
         xor     tempword, 1
      INVOKE     SendMessage, hwndTool, TB_ENABLEBUTTON, 1104, tempword
      INVOKE     SendMessage, hREdit, EM_CANREDO, 0, 0
         cmp     eax, TRUE
         jne     EdMu3
         mov     tempword, MF_ENABLED
         jmp     EdMu4
EdMu3:   mov     tempword, MF_GRAYED
EdMu4:
      INVOKE     EnableMenuItem, hMenu, 1105, tempword     ; Redo
         xor     tempword, 1
      INVOKE     SendMessage, hwndTool, TB_ENABLEBUTTON, 1105, tempword
      INVOKE     IsClipboardFormatAvailable, CF_TEXT
         cmp     eax, TRUE
         jne     EdMu5
         mov     tempword, MF_ENABLED
         jmp     EdMu6
EdMu5:   mov     tempword, MF_GRAYED
EdMu6:
      INVOKE     EnableMenuItem, hMenu, 1102, tempword     ; Paste
         xor     tempword, 1
      INVOKE     SendMessage, hwndTool, TB_ENABLEBUTTON, 1102, tempword
         mov     eax, cr.cpMin
         cmp     eax, cr.cpMax                             ; If no selection then gray otherwise enable
         je      EdMu7
         mov     tempword, MF_ENABLED
         jmp     EdMu8
EdMu7:   mov     tempword, MF_GRAYED
EdMu8:
      INVOKE     EnableMenuItem, hMenu, 1100, tempword     ; Cut
      INVOKE     EnableMenuItem, hMenu, 1101, tempword     ; Copy
      INVOKE     EnableMenuItem, hMenu, 1103, tempword     ; Delete
      INVOKE     EnableMenuItem, hMenu, 1107, tempword     ; Find next
      INVOKE     EnableMenuItem, hMenu, 1108, tempword     ; Find prev
         xor     tempword, 1
      INVOKE     SendMessage, hwndTool, TB_ENABLEBUTTON, 1100, tempword
      INVOKE     SendMessage, hwndTool, TB_ENABLEBUTTON, 1101, tempword
      INVOKE     SendMessage, hwndTool, TB_ENABLEBUTTON, 1103, tempword
      INVOKE     SendMessage, hwndTool, TB_ENABLEBUTTON, 1107, tempword
      INVOKE     SendMessage, hwndTool, TB_ENABLEBUTTON, 1108, tempword
      .if OnlyRead
            mov     tempword, MF_GRAYED
         INVOKE     EnableMenuItem, hMenu, 1100, tempword  ; Cut
         INVOKE     EnableMenuItem, hMenu, 1102, tempword  ; Paste
         INVOKE     EnableMenuItem, hMenu, 1103, tempword  ; Delete
            xor     tempword, 1
         INVOKE     SendMessage, hwndTool, TB_ENABLEBUTTON, 1100, tempword
         INVOKE     SendMessage, hwndTool, TB_ENABLEBUTTON, 1102, tempword
         INVOKE     SendMessage, hwndTool, TB_ENABLEBUTTON, 1103, tempword
      .endif
         RET
EnableDisableMenuTool ENDP

;======================================
; Validate Paste procedure
;======================================
Validate proc
LOCAL    Err:DWORD

         mov     Err, 0
      INVOKE     CreateWindowEx, 0, addr richedit, 0,
                 WS_CHILD or ES_MULTILINE,
                 0, 30, 300, 200, hWnd, 41, hInst, NULL
         mov     Test4, eax
      INVOKE     SendMessage, Test4, WM_PASTE, 0, 0
      INVOKE     SendMessage, Test4, WM_GETTEXTLENGTH, 0, 0
         inc     eax
      INVOKE     SendMessage, Test4, WM_GETTEXT, eax, addr szWork
         xor     esi, esi
         xor     edi, edi
      .while (eax)
            mov     bl, byte ptr szWork[esi]
         .if bl != 20h
            .if bl > 2fh && bl < 3ah || bl > 40h && bl < 47h ||\
                bl > 60h && bl < 67h || bl == 0Ah || bl == 0Dh
               .if bl > 60h && bl < 67h
                     sub     bl, 20h
               .endif
                  mov     byte ptr szBuff[edi], bl
                  inc     edi
            .else
                  mov     Err, 1
                  jmp     EndIt
            .endif
         .endif
            inc     esi
            dec     eax
      .endw
         mov     byte ptr szBuff[edi], 0
         mov     eax, edi
         xor     edx, edx
         mov     ebx, 2
         div     ebx
      .if edx
            mov     Err, 2
            jmp     EndIt
      .endif

EndIt:
      .if Err
         INVOKE     OpenClipboard, NULL
         INVOKE     EmptyClipboard
         INVOKE     CloseClipboard
           call     EnableDisableMenuTool
      .endif
      INVOKE     DestroyWindow, Test4
         mov     eax, Err
         ret
Validate endp

;=======================================
; GoTo Offset Dialog
;=======================================
GoToOff PROC  uses ebx edx  hdlg:DWORD, wmsg:DWORD, wparam:DWORD, lparam:DWORD
LOCAL     Base:DWORD, Val, SavVal, Cnt, FOffset

      .if wmsg == 1234
          MOVmd     SavVal, lparam
          MOVmd     Val, lparam      ; See if Val should be offset
            jmp     FromFind
      .endif
      .if wmsg == WM_INITDIALOG
         INVOKE     GetDlgItem, hdlg, 1202
         INVOKE     SendMessage, eax, BM_SETCHECK, BST_CHECKED, 0 ; Sets Hex to checked
         INVOKE     GetDlgItem, hdlg, 1201
         INVOKE     SetFocus, eax

      .elseif wmsg != WM_COMMAND
         jmp     GoToDone
      .endif
         mov     eax, wparam
        cwde
         cmp     eax, IDCANCEL
          je     CancelOut
      .if eax == 1202 || eax == 1203
            INVOKE     GetDlgItem, hdlg, 1201
            INVOKE     SetFocus, eax
               jmp     GoToDone
      .endif
         cmp     eax, IDOK
         jne     GoToDone
      INVOKE     GetDlgItemText, hdlg, 1201, addr szBuff, 10
         mov     Base, 16
      .if HexDec == 16
            mov     Base, 10
      .endif
      INVOKE     IsDlgButtonChecked, hdlg, 1202 ; Hex
      .if eax
            mov     Base, 16
      .else
            mov     Base, 10
      .endif
      INVOKE     AsciiBase, addr szBuff, addr Val, Base
      .if Base == 10 && HexDec == 16
            mov     Base, 16
      .elseif HexDec == 10
            mov     Base, 10
      .endif
      INVOKE     BaseAscii, Val, addr szWork, 8, Base, 0, 1, 1
       MOVmd     SavVal, Val

FromFind:
        call     ScreenLines
          or     Split1, 1
         mov     ft.chrg.cpMin, 0
         mov     ft.chrg.cpMax, -1
         mov     Cnt, 15
      .if wmsg == 1234
            jmp     DoAgain
      .endif
      INVOKE     AsciiBase, addr szWork, addr Val, Base
         mov     eax, Val
         xor     edx, edx
         div     Base
        imul     eax, Base
         mov     Val, eax
      INVOKE     BaseAscii, eax, addr szWork, 8, Base, 0, 1, 1

DoAgain:
         lea     eax, offset szWork
         mov     ft.lpstrText, eax
      INVOKE     SendMessage, hSplit1, EM_FINDTEXT, FR_DOWN, offset ft
         cmp     eax, -1                 ; Nothing found?
         jne     FoundIt
      .while (Cnt)
            and     Val, 0
         INVOKE     AsciiBase, addr szWork, addr Val, HexDec
            dec     Val
         INVOKE     BaseAscii, Val, addr szWork, 8, HexDec, 0, 1, 1
            dec     Cnt
            jmp     DoAgain
      .endw
         jmp     Pass2

FoundIt:
        push     eax
      INVOKE     BaseAscii, SavVal, addr szWork, 1, HexDec, 0, 1, 1
      INVOKE     lstrcpy, addr szStat, addr szFileOff
      INVOKE     lstrcat, addr szStat, addr szWork
      INVOKE     SendMessage, hwndStat, SB_SETTEXT, 1, addr szStat
         mov     ebx, SavVal
         sub     ebx, Val
      INVOKE     BaseAscii, ebx, addr szWork, 1, HexDec, 0, 1, 1
      INVOKE     lstrcpy, addr szStat, addr szLineOff
      INVOKE     lstrcat, addr szStat, addr szWork
      INVOKE     SendMessage, hwndStat, SB_SETTEXT, 2, addr szStat
         pop     eax

         mov     ecx, NScrL
         shr     ecx, 1
         xor     edx, edx
         mov     ebx, 9
         div     ebx
         mov     FOffset, eax

      .if eax > ecx
            sub     eax, ecx
      .else
            mov     eax, 0
      .endif
         mov     yPos, eax
      INVOKE     GetScrollInfo, hSplit3, SB_VERT, addr sci
       finit
        fild     sci.nMax
        fild     Ltot
        fdiv     ST(0), ST(1)
        fild     yPos
        fdiv     ST(0), ST(1)
       fistp     yPos
       MOVmd     sci.nPos, yPos
      INVOKE     SetScrollInfo, hSplit3, SB_VERT, addr sci, 1
         mov     eax, Val
         sub     SavVal, eax
      INVOKE     SendMessage, hSplit3, EM_LINEINDEX, FOffset, 0
         add     eax, SavVal
         mov     cr.cpMin, eax
         inc     eax
         mov     cr.cpMax, eax
      INVOKE     SendMessage, hSplit3, EM_EXSETSEL, 0, offset cr

      INVOKE     SendMessage, hREdit, EM_LINEINDEX, FOffset, 0
         mov     ecx, SavVal
         shl     ecx, 1
         add     eax, ecx
        push     eax
         xor     edx, edx
         mov     eax, ecx
         mov     ebx, 4
         div     ebx
         mov     ecx, eax
         pop     eax
         add     eax, ecx
         mov     cr.cpMin, eax
         mov     cr.cpMax, eax
      INVOKE     SendMessage, hREdit, EM_EXSETSEL, 0, offset cr
      INVOKE     SetFocus, hREdit

         and     sw2, 0
         mov     ecx, yPos
         shl     ecx, 16
         mov     eax, SB_THUMBTRACK
         mov     cx, ax
      INVOKE     SendMessage, hSplit3, WM_VSCROLL, ecx, 0

      INVOKE     GetScrollInfo, hSplit3, SB_VERT, addr sci
       MOVmd     syPos, sci.nPos

      .if wmsg != 1234
            xor     ecx, ecx
            mov     eax, SB_LINEDOWN
            mov     cx, ax
         INVOKE     SendMessage, hSplit3, WM_VSCROLL, ecx, 0
      .endif

Pass2:
         and     Split1, 0
      .if wmsg == 1234
            ret
      .endif

CancelOut:
        call     EnableDisableMenuTool
      INVOKE     EndDialog, hdlg, wparam
         mov     eax, TRUE
         jmp     GoToRet

GoToDone:
         mov     eax, FALSE           ;return with FALSE

GoToRet:
         RET
GoToOff ENDP

;========================================================================
; Subclass procedure for the Edit field
;========================================================================
ControlEdit  PROC uses ebx edx esi edi  hwnd:DWORD, wMsg, wparam, lparam

      .if wMsg == WM_CHAR || wMsg == WM_KEYUP
          MOVmd     w4, wMsg
            mov     eax, hwnd
          MOVmd     Hold, wparam
         .if eax == hConvert && wMsg == WM_CHAR
             MOVmd     Hold, wparam
            .if Hold == 09h || Hold == 0dh || Hold == 20h
               .if Hold == 09h
                     mov     word ptr szWork, 'TH'
                     mov     szWork+2, 0
               .elseif Hold == 0dh
                     mov     word ptr szWork, 'RC'
                     mov     szWork+2, 0
               .else
                     mov     word ptr szWork, 'PS'
                     mov     szWork+2, 0
               .endif
               INVOKE     SetDlgItemText, Test4, 1216, offset szWork
                  mov     w4, 0
                  jmp     EndIt
            .endif
            INVOKE     SendMessage, hConvert, EM_SETSEL, 0, -1
         .endif
      .endif
EndIt:
      INVOKE     CallWindowProc, hEditSub, hwnd, wMsg, wparam, lparam
         ret
ControlEdit  ENDP

;========================================================================
; Key Translator DIALOG PROCEDURE
;========================================================================
ConvertDlg PROC  uses ebx edx esi edi  hdlg:DWORD, wmsg, wparam, lparam
LOCAL    Num:DWORD
LOCAL    szWorkS[10]:BYTE

      .if wmsg == WM_INITDIALOG      ; If message is INITDIALOG then
;MOVmd     Test4, hdlg
         INVOKE     CheckDlgButton, hdlg, 31, BST_CHECKED   ; Sets Hex type
            mov     Hex, 1
         INVOKE     GetDlgItem, hdlg, 1216
            mov     hConvert, eax
         INVOKE     SetWindowLong, eax, GWL_WNDPROC, ControlEdit
            mov     hEditSub, eax
         INVOKE     GetDlgItem, hdlg, 1217
            mov     hInput, eax
         INVOKE     SetWindowLong, eax, GWL_WNDPROC, ControlEdit
            mov     hEditSub, eax
         INVOKE     SendMessage, hInput, EM_LIMITTEXT, 2, 0 ; Limit text size

;         INVOKE     lstrcpy, addr lf.lfFaceName, addr FontMS
;            mov     lf.lfHeight, -13
;            mov     lf.lfWeight, 500
;         INVOKE     CreateFontIndirect, addr lf
         INVOKE     GetStockObject, OEM_FIXED_FONT
         INVOKE     SendMessage, hConvert, WM_SETFONT, eax, 1
         INVOKE     SetFocus, hConvert
            and     sw1, 0
            jmp     ConvertDone
      .endif

         cmp     wmsg, WM_COMMAND
         jne     ConvertDone
         mov     eax, wparam
        cwde

      .if eax == 31
            mov     Hex, 1
         INVOKE     SetWindowLong, hInput, GWL_STYLE, WS_CHILD or WS_VISIBLE or\
                    WS_BORDER or ES_UPPERCASE or ES_CENTER or ES_AUTOHSCROLL
         INVOKE     SendMessage, hInput, EM_LIMITTEXT, 2, 0 ; Limit text size
         INVOKE     GetDlgItemText, hdlg, 42, addr szWork, sizeof szWork
         INVOKE     SetDlgItemText, hdlg, 1217, offset szWork
         INVOKE     SetFocus, hInput

      .elseif eax == 32
            and     Hex, 0
         INVOKE     SetWindowLong, hInput, GWL_STYLE, WS_CHILD or WS_VISIBLE or\
                    WS_BORDER or ES_UPPERCASE or ES_CENTER or ES_AUTOHSCROLL or ES_NUMBER
         INVOKE     SendMessage, hInput, EM_LIMITTEXT, 3, 0 ; Limit text size
         INVOKE     GetDlgItemText, hdlg, 41, addr szWork, sizeof szWork
         INVOKE     SetDlgItemText, hdlg, 1217, offset szWork
         INVOKE     SetFocus, hInput

      .elseif eax == 1216 && w4 == WM_CHAR
         INVOKE     BaseAscii, Hold, offset szBuff, 2, 10, 0, 1, 1
         INVOKE     BaseAscii, Hold, offset szWork, 2, 16, 0, 1, 1
         INVOKE     SetDlgItemText, hdlg, 41, offset szBuff
         INVOKE     SetDlgItemText, hdlg, 42, offset szWork

            mov     szWork, 0
         INVOKE     SetDlgItemText, hdlg, 1217, offset szWork
            jmp     ConvertDone

      .elseif eax == 1217 && w4 == WM_CHAR ;|| eax == 1217 && w4 == WM_KEYUP
         INVOKE     GetDlgItemText, hdlg, 1217, addr szWork, sizeof szWork

;----- [Validate the user input characters
            mov     Num, eax
            cmp     Hex, 0
             je     NotHex
            xor     esi, esi
         .while (eax)
               mov     bl, byte ptr szWork[esi]
            .if bl > 2fh && bl < 3ah || bl > 40h && bl < 47h || bl > 60h && bl < 67h
                  jmp     HexOK
            .else
ReSet:
                  mov     eax, Num
                  mov     ebx, eax
                  dec     eax
                  mov     szWorkS, 0
               INVOKE     SendMessage, hInput, EM_SETSEL, eax, ebx
               INVOKE     SendMessage, hInput, EM_REPLACESEL, FALSE, addr szWorkS
                  jmp     ConvertErr
            .endif

HexOK:
               inc     esi
               dec     eax
         .endw

NotHex:
         INVOKE     GetDlgItemText, hdlg, 1217, addr szWork, sizeof szWork
         INVOKE     GetDlgItemText, hdlg, 1217, addr szBuff, sizeof szBuff
            mov     Num, eax
            and     Hold, 0
         .if Hex
            .if eax == 1
                  mov     ax, word ptr szBuff
                  mov     szBuff+1, al
                  mov     szBuff+2, ah
                  mov     byte ptr szBuff, '0'
            .endif
            INVOKE     AsciiBase, addr szWork, addr Hold, 16
         .else
            INVOKE     AsciiBase, addr szWork, addr Hold, 10
         .endif
         .if Hold > 255
               jmp     ReSet
         .endif
         .if Hex
            INVOKE     SetDlgItemText, hdlg, 42, addr szBuff
            INVOKE     WriteEM, 0, 17
            INVOKE     SendMessage, hConvert, WM_SETTEXT, NULL, addr szFind
            INVOKE     BaseAscii, Hold, addr szBuff, 0, 10, 0, 0, 1
            INVOKE     SetDlgItemText, hdlg, 41, addr szBuff
         .else
            INVOKE     SetDlgItemText, hdlg, 41, addr szBuff
            .if Num
               INVOKE     BaseAscii, Hold, addr szBuff, 2, 16, 0, 1, 1
            .else
               INVOKE     BaseAscii, Hold, addr szBuff, 0, 16, 0, 0, 1
            .endif
            INVOKE     SetDlgItemText, hdlg, 42, addr szBuff
            INVOKE     WriteEM, 0, 17
            INVOKE     SendMessage, hConvert, WM_SETTEXT, NULL, addr szFind
        .endif
            jmp     ConvertDone
      .endif

         cmp     eax, IDCANCEL
         jne     ConvertDone
      INVOKE     EndDialog, hdlg, wparam
         mov     eax, TRUE
         jmp     ConvertRet

ConvertErr:
      INVOKE     MessageBeep, MB_OK

ConvertDone:
         and     w4, 0
         mov     eax, FALSE

ConvertRet:
         RET
ConvertDlg ENDP

;=======================================
;* FindReplace Dialog
;=======================================
FindReplace PROC  uses ebx edx esi edi  hdlg:DWORD, wmsg:DWORD, wparam:DWORD, lparam:DWORD
LOCAL     rect:RECT
LOCAL     Num:DWORD, Cnt, FRField
LOCAL     szWorkS[10]:BYTE, szRep[260]

      .if wmsg == WM_INITDIALOG      ; If message is INITDIALOG then
          MOVmd     hFRDlg, hdlg
          MOVmd     FR, lparam
            and     Match, 0
            and     Match0, 0
         .if Hex
            INVOKE     CheckDlgButton, hdlg, 31, BST_CHECKED        ; Sets Hex type
         .else
            INVOKE     CheckDlgButton, hdlg, 32, BST_CHECKED        ; Sets Text type
         .endif
         .if MatchCase
            INVOKE     CheckDlgButton, hdlg, 33, BST_CHECKED        ; Sets Match case
         .endif
         INVOKE     CheckDlgButton, hdlg, 36, BST_CHECKED           ; Sets Down
         INVOKE     GetDlgItem, hdlg, 1206
            mov     hFind, eax
         INVOKE     SetWindowLong, eax, GWL_WNDPROC, ControlEdit
            mov     hEditSub, eax
         .if FR == 4201
            INVOKE     GetDlgItem, hdlg, 1209
               mov     hReplace, eax
            INVOKE     SetWindowLong, eax, GWL_WNDPROC, ControlEdit
               mov     hEditSub, eax
         .endif
         INVOKE     GetDC, hdlg
            mov     hDC, eax
         INVOKE     lstrcpy, addr lf.lfFaceName, addr FontMS
            mov     lf.lfHeight, -12
            mov     lf.lfWeight, 500
         INVOKE     CreateFontIndirect, addr lf
         INVOKE     SelectObject, hDC, eax
         INVOKE     SetFocus, hFind
            and     sw1, 0
            jmp     FRDone
      .endif

      .if wmsg == WM_PAINT
         INVOKE     IsDlgButtonChecked, hdlg, 31
         .if eax
               mov     eax, 31
         .else
               mov     eax, 32
         .endif
            jmp     PaintEM
      .endif
      
         cmp     wmsg, WM_COMMAND
         jne     FRDone
         mov     eax, wparam
        cwde
      .if eax == 33
         INVOKE     SetFocus, hFind
      .endif
         mov     eax, wparam
        cwde

PaintEM:
      .if eax == 31 || eax == 32
         .if eax == 31
            INVOKE     lstrcpy, addr szWorkS, addr szText
               mov     Hex, 1
         .else
            INVOKE     lstrcpy, addr szWorkS, addr szHex
               and     Hex, 0
         .endif
         INVOKE     SetFocus, hFind
         .if wmsg == WM_PAINT
               jmp     NoSwap
         .endif
         INVOKE     GetDlgItemText, hdlg, 1206, addr szBuff, sizeof szBuff
         INVOKE     GetDlgItemText, hdlg, 1207, addr szWork, sizeof szWork
         INVOKE     SetDlgItemText, hdlg, 1206, addr szWork
         INVOKE     SetDlgItemText, hdlg, 1207, addr szBuff

         INVOKE     GetDlgItemText, hdlg, 1209, addr szBuff, sizeof szBuff
         INVOKE     GetDlgItemText, hdlg, 1210, addr szWork, sizeof szWork
         INVOKE     SetDlgItemText, hdlg, 1209, addr szWork
         INVOKE     SetDlgItemText, hdlg, 1210, addr szBuff

NoSwap:
         INVOKE     GetClientRect, hdlg, addr rect
            and     rect.right, 0
            and     rect.bottom, 0
         .if FR == 4200
            add     rect.left, 21
            add     rect.right, 50
         .else
            add     rect.left, 30
            add     rect.right, 59
         .endif
            add     rect.top, 72
            add     rect.bottom, 85
         INVOKE     SetTextColor, hDC, 00ff0000h
         INVOKE     SetBkMode, hDC, TRANSPARENT
         INVOKE     FillRect, hDC, addr rect, COLOR_BTNFACE+1
         INVOKE     DrawText, hDC, addr szWorkS, -1, addr rect, DT_LEFT or DT_SINGLELINE

            cmp     FR, 4200
             je     FRDone
            add     rect.top, 58
            add     rect.bottom, 58
         INVOKE     FillRect, hDC, addr rect, COLOR_BTNFACE+1
         INVOKE     DrawText, hDC, addr szWorkS, -1, addr rect, DT_LEFT or DT_SINGLELINE

      .elseif eax == 1206 && w4 == WM_CHAR || eax == 1206 && w4 == WM_KEYUP ||\
              eax == 1209 && w4 == WM_CHAR || eax == 1209 && w4 == WM_KEYUP
            mov     FRField, eax
         .if sw1 == 4
               and     sw1, 0
               jmp     DoneIt
         .endif
         .if FRField == 1206
            INVOKE     GetDlgItemText, hdlg, 1206, addr szWork, sizeof szWork
         .else
            INVOKE     GetDlgItemText, hdlg, 1209, addr szWork, sizeof szWork
         .endif

;----- [Validate the user input characters
            cmp     eax, 0
             je     FRDone
            mov     Num, eax
            xor     esi, esi
            xor     edi, edi
         .while (eax)
               mov     bl, byte ptr szWork[esi]
            .if !Hex
                  jmp     InputOK
            .elseif bl > 2fh && bl < 3ah || bl == 20h
                  jmp     InputOK
            .elseif bl > 40h && bl < 47h
                  jmp     InputOK
            .elseif bl > 60h && bl < 67h
                  sub     bl, 20h
                  jmp     InputOK
            .else
                  mov     eax, Num
                  mov     ebx, eax
                  dec     eax
                  mov     szWorkS, 0
               .if FRField == 1206
                  INVOKE     SendMessage, hFind, EM_SETSEL, eax, ebx
                  INVOKE     SendMessage, hFind, EM_REPLACESEL, TRUE, addr szWorkS
               .else
                  INVOKE     SendMessage, hReplace, EM_SETSEL, eax, ebx
                  INVOKE     SendMessage, hReplace, EM_REPLACESEL, TRUE, addr szWorkS
               .endif
               INVOKE     MessageBeep, MB_OK
                  jmp     FRDone
            .endif

InputOK:
            .if bl != 20h
                  mov     byte ptr szBuff[edi], bl
                  inc     edi
            .endif
               inc     esi
               dec     eax
         .endw
            mov     byte ptr szBuff[edi], 0
           push     edi
            mov     sw1, 4
         .if FRField == 1206
            INVOKE     SetDlgItemText, hdlg, 1206, addr szBuff
               pop     edi
            INVOKE     SendMessage, hFind, EM_SETSEL, edi, edi
         .else
            INVOKE     SetDlgItemText, hdlg, 1209, addr szBuff
               pop     edi
            INVOKE     SendMessage, hReplace, EM_SETSEL, edi, edi
         .endif

DoneIt:
         .if FRField == 1206
            INVOKE     GetDlgItemText, hdlg, 1206, addr szBuff, sizeof szBuff
         .else
            INVOKE     GetDlgItemText, hdlg, 1209, addr szBuff, sizeof szBuff
         .endif
         INVOKE     IsDlgButtonChecked, hdlg, 31
         .if eax
            INVOKE     WriteEM, 0, 1

;---------- [Convert ascii to formated hex] ----------
         .else
               mov     szFind, 0
               xor     esi, esi
               xor     edi, edi
            INVOKE     lstrlen, addr szBuff
               mov     ecx, eax

            .while (ecx)
                  mov     Cnt, 2

               .while (Cnt)
                     mov     al, byte ptr [szBuff+esi]
                  .if Cnt == 2
                        shr     eax, 4
                  .endif
                     and     eax, 0fh
                  .if eax > 9
                     add     eax, 37h
                  .else
                     add     eax, 30h
                  .endif
                     mov     byte ptr[szFind+edi], al
                     inc     edi
                     dec     Cnt
               .endw

                  inc     esi
                  dec     ecx
            .endw
                  mov     byte ptr[szFind+edi], 0
            .if byte ptr[szFind+edi-1] == 20h
                  mov     byte ptr[szFind+edi-1], 0
            .endif
         .endif
         .if FRField == 1206
            INVOKE     SetDlgItemText, hdlg, 1207, addr szFind
         .else
            INVOKE     SetDlgItemText, hdlg, 1210, addr szFind
         .endif
            jmp     FRDone
      .endif  

      .if eax == 1205                  ; Find next button
         INVOKE     SetFocus, hFind
            jmp     FRText
      .elseif eax == 1208              ; Replace button
         INVOKE     SetFocus, hReplace
         INVOKE     IsDlgButtonChecked, hdlg, 31
         .if eax
            INVOKE     GetDlgItemText, hdlg, 1209, addr szRep, 256
         .else
            INVOKE     GetDlgItemText, hdlg, 1210, addr szRep, 256
         .endif
            mov     Len, eax
            xor     edx, edx
            mov     ebx, 2
            div     ebx
         .if edx
            INVOKE     MessageBox, hWnd, addr szError3, addr szDisplayName, MB_OK
               jmp     FRDone
         .endif
         INVOKE     SendMessage, hWorkC, EM_REPLACESEL, TRUE, addr szRep
         INVOKE     lstrcpy, addr szWork, addr szRep
            mov     ecx, Len
            lea     esi, szWork
         .if ecx
              call     UpperCase
         .endif
         INVOKE     SendMessage, hWorkN, EM_REPLACESEL, TRUE, addr szWork

;---------- [Format to hex view] ----------
         INVOKE     SendMessage, hREdit, EM_EXGETSEL, 0, offset cr
            mov     eax, cr.cpMax
            sub     eax, cr.cpMin
         .if Len == eax
               jmp     SameSize
         .else
            INVOKE     SendMessage, hREdit, EM_REPLACESEL, TRUE, addr szRep
               mov     Refresh, 1
            INVOKE     SendMessage, hWorkC, EM_EXGETSEL, 0, offset cr
            INVOKE     WriteEM, addr szFileName, 0
            INVOKE     SendMessage, hWorkC, EM_EXSETSEL, 0, offset cr
            INVOKE     SendMessage, hWorkN, EM_EXSETSEL, 0, offset cr
              call     EnableDisableMenuTool
               jmp     FRText
         .endif

SameSize:
         INVOKE     SendMessage, hREdit, EM_GETSELTEXT, 0, addr szWork
            xor     esi, esi
            xor     edi, edi
         .while (eax)
               mov     bl, byte ptr szRep[esi]
               mov     cl, byte ptr szWork[edi]
            .if cl != 20h
                  mov     byte ptr szWork[edi], bl
                  inc     esi
                  inc     edi
            .else
                  inc     edi
            .endif
               dec     eax
         .endw
            mov     byte ptr szWork[edi], 0
         INVOKE     SendMessage, hREdit, EM_REPLACESEL, TRUE, addr szWork

;---------- [Format to ascii view] ----------
         INVOKE     lstrcpy, addr szBuff, addr szRep
         INVOKE     WriteEM, 0, 1
         INVOKE     SendMessage, hSplit3, EM_GETSELTEXT, 0, addr szWork
            xor     esi, esi
            xor     edi, edi
         .while (eax)
               mov     bl, byte ptr szFind[esi]
               mov     cl, byte ptr szWork[edi]
            .if cl != 0Dh && cl != 0Ah
                  mov     byte ptr szWork[edi], bl
            .else
                  inc     edi
            .endif
               inc     esi
               inc     edi
               dec     eax
         .endw
            mov     byte ptr szWork[edi], 0
         INVOKE     SendMessage, hSplit3, EM_REPLACESEL, TRUE, addr szWork

           call     EnableDisableMenuTool
            jmp     FRText
      .endif
         cmp     eax, IDCANCEL
         je      CloseIt
         jmp     FRDone

FRText:
      .if MatchCase
         INVOKE     SendMessage, hWorkC, EM_EXGETSEL, 0, offset cr
      .else
         INVOKE     SendMessage, hWorkN, EM_EXGETSEL, 0, offset cr
      .endif
      INVOKE     IsDlgButtonChecked, hdlg, 31   ; Hex Ascii
      .if eax
         INVOKE     GetDlgItemText, hdlg, 1206, addr szBuff, 256
      .else
         INVOKE     GetDlgItemText, hdlg, 1207, addr szBuff, 256
      .endif
         xor     edx, edx
         mov     ebx, 2
         div     ebx
      .if edx
         INVOKE     MessageBox, hWnd, addr szError3, addr szDisplayName, MB_OK
            jmp     FRDone
      .endif

;---------- [Prepare the find] ----------
      .if Match0    ; Matched on the first byte
            and     Match0, 0
            inc     cr.cpMin
      .endif
         lea     eax, offset szBuff
         mov     ft.lpstrText, eax
      INVOKE     lstrlen, addr szBuff
         mov     Len, eax
       MOVmd     ft.chrg.cpMin, cr.cpMin
         mov     ft.chrg.cpMax, -1
      .if FR == 4201 && ft.chrg.cpMin > 1 && wparam == 1208  ; N O T E  !!!!!!!!!!!!!!!!!!!!!!!!!
;            dec     ft.chrg.cpMin
      .endif 
         and     MatchCase, 0
         and     Flag, 0
         mov     UD, 1
      INVOKE     IsDlgButtonChecked, hdlg, 36
      .if eax
            mov     Flag, FR_DOWN
            and     UD, 0
         .if Match && wparam != 1208
               mov     eax, Len
               add     ft.chrg.cpMin, eax
         .endif
      .endif
      INVOKE     IsDlgButtonChecked, hdlg, 33
      .if eax
             or     Flag, FR_MATCHCASE
            mov     MatchCase, 1
         INVOKE     Find, hWorkC, Flag, addr szBuff, UD
      .else
            mov     ecx, Len
            lea     esi, szBuff
         .if ecx
              call     UpperCase
         .endif
         INVOKE     Find, hWorkN, Flag, addr szBuff, UD
      .endif
         jmp     FRDone

CloseIt:
         and     hFRDlg, 0
      INVOKE     ReleaseDC, hdlg, hDC
      INVOKE     EndDialog, hdlg, wparam
         mov     eax, TRUE
         jmp     FRRet

FRDone:
         mov     eax, FALSE           ;return with FALSE
         and     w4, 0
FRRet:
         RET
FindReplace ENDP

;=========================================================================
;* FindProc returns TRUE or FALSE based on finding FText 
;=========================================================================
Find    PROC  uses ebx esi hWork:DWORD, Flags, FText, Up
LOCAL     Val:DWORD

Loop1:
         and     Match, 0
      INVOKE     SendMessage, hWork, EM_FINDTEXT, Flags, offset ft
         cmp     eax, -1                 ; Nothing found?
         jne     FoundIt

      .if Up == 0
         INVOKE     lstrcpyn, offset TopBot, offset Top, 6
      .else
         INVOKE     lstrcpyn, offset TopBot, offset Bot, 6
      .endif
      INVOKE     MessageBox, NULL, offset FindEnd, offset szFR, MB_YESNO or MB_ICONQUESTION or MB_TASKMODAL
         cmp     eax, IDNO
          je     Find0

DoIt:
      .if Up == 0
         INVOKE     SendMessage, hWork, EM_SETSEL, 0, 0
            mov     ft.chrg.cpMin, 0
            mov     ft.chrg.cpMax, -1
      .else
            mov     eax, BytesOut
            mov     ft.chrg.cpMin, eax
            mov     ft.chrg.cpMax, 0
      .endif
         jmp     Loop1

FoundIt:
         mov     ebx, cr.cpMax
         sub     ebx, cr.cpMin
      .if eax == cr.cpMin && Up == 0 && eax != 0 && ebx
            mov     eax, Len
            add     ft.chrg.cpMin, eax
            jmp     Loop1
      .endif
         mov     ft.chrg.cpMin, eax
         mov     cr.cpMin, eax
         add     eax, Len
         mov     cr.cpMax, eax
      INVOKE     SendMessage, hWork, EM_EXSETSEL, 0, offset cr
      INVOKE     SendMessage, hWork, EM_EXLINEFROMCHAR, 0, cr.cpMin
         mov     Lnum, eax
      INVOKE     SendMessage, hWork, EM_EXLINEFROMCHAR, 0, cr.cpMax
         mov     LastLine, eax
      INVOKE     SendMessage, hWork, EM_LINEINDEX, Lnum, 0
         mov     FileOff, eax
         mov     ebx, cr.cpMin
         sub     ebx, eax
         mov     LineOff, ebx
         mov     word ptr szWork, 60
      INVOKE     SendMessage, hREdit, EM_GETLINE, Lnum, addr szWork
         mov     byte ptr szWork[eax], 0
         and     Space, 0
         mov     ebx, LineOff
         xor     esi, esi
      .while (ebx)
            add     esi, 1 ;2
         .if byte ptr szWork[esi] == 20h
               inc     esi
               inc     Space
         .endif
            dec     ebx
      .endw
         mov     LineOff, esi  ; esi = hex line offset

;---------- [Check to see if byte aligned] ----------
         mov     eax, esi
         sub     eax, Space
         xor     edx, edx
         mov     ebx, 2
         div     ebx
      .if edx
         .if Up
               sub     ft.chrg.cpMin, 1
         .else
               add     ft.chrg.cpMin, 1
         .endif
            jmp     Loop1
      .endif

         mov     esi, LineOff
      INVOKE     lstrcpy, addr szBuff, addr szWork[esi]
      INVOKE     SplitProc, hREdit, 777, 0, 0

      INVOKE     SendMessage, hREdit, EM_HIDESELECTION, 1, 0
      INVOKE     SendMessage, hREdit, EM_EXSETSEL, 0, offset cr
        call     EnableDisableMenuTool

;---------- [Scroll the selection into view] ----------
      INVOKE     SendMessage, hREdit, EM_HIDESELECTION, 0, 0
        push     cr.cpMin
        push     cr.cpMax
          or     Split1, 1
         mov     word ptr szWork, 10
      INVOKE     SendMessage, hSplit1, EM_GETLINE, Lnum, addr szWork
         mov     byte ptr szWork[eax], 0
      INVOKE     lstrcpy, addr szBuff, addr szWork
         and     Split1, 0
         mov     Val, 0
      INVOKE     AsciiBase, addr szWork, addr Val, HexDec ;16
      INVOKE     lstrcpy, addr szWork, addr szBuff
      INVOKE     GoToOff, hREdit, 1234, 0, Val
         mov     word ptr szWork, 60
      INVOKE     SendMessage, hREdit, EM_GETLINE, Lnum, addr szWork
         mov     byte ptr szWork[eax], 0

         pop     cr.cpMax
         pop     cr.cpMin
      INVOKE     SendMessage, hREdit, EM_EXSETSEL, 0, offset cr

         add     Match, 1
      .if cr.cpMin == 0
            mov     Match0, 1
      .endif

;---------- [Echo the selection to the ascii window] ----------
      INVOKE     REditProc, hREdit, WM_MOUSEMOVE, MK_LBUTTON, 0
         mov     eax, TRUE
         jmp     Find1
Find0:   mov     eax, FALSE
Find1:   RET
Find    ENDP

;=======================================================
; esi = Input string pointer ecx = len get before call
; Returns string converted to upper case
;=======================================================
UpperCase PROC
         push    esi                ; Save pointer
         mov     edi, esi           ; Dest = source
struplp:
       lodsw                        ; Get word in ax
         .if al > 35h && al < 38h && ah > 2fh && ah < 3ah ||\
             al > 35h && al < 38h && ah > 40h && ah < 4ah
               sub     al, 2        ; Sub 2h to lower case bit
         .endif
        stosw                       ; store ax
         loop    struplp            ; for length of string
         pop     esi                ; Restore string ptr
         RET                        ; Return to caller
UpperCase ENDP


;=======================================================
; Renumber the offset view
;=======================================================
Renumber PROC  uses edx edi
LOCAL     rect:RECT
LOCAL     szWorkS[12]:BYTE
LOCAL     hMemS1:DWORD, pMemS1, BytesO, SavS1, Cnt, Val, SavMin, SavMax

      .if !Ltot
            ret
      .endif

      INVOKE     BaseAscii, FileOffS, addr szWorkS, 1, HexDec, 0, 1, 1
      INVOKE     lstrcpy, addr szStat, addr szFileOff
      INVOKE     lstrcat, addr szStat, addr szWorkS
      INVOKE     SendMessage, hwndStat, SB_SETTEXT, 1, addr szStat

      INVOKE     BaseAscii, LineOffS, addr szWorkS, 1, HexDec, 0, 1, 1
      INVOKE     lstrcpy, addr szStat, addr szLineOff
      INVOKE     lstrcat, addr szStat, addr szWorkS
      INVOKE     SendMessage, hwndStat, SB_SETTEXT, 2, addr szStat

        call     ScreenLines
         mov     eax, Ltot
         inc     eax
        imul     eax, 10
         mov     BytesO, eax
      INVOKE     HeapCreate, HEAP_GENERATE_EXCEPTIONS, BytesO, 0
         mov     hMemS1, eax
      INVOKE     HeapAlloc, hMemS1, HEAP_GENERATE_EXCEPTIONS, BytesO
         mov     pMemS1, eax
         mov     SavS1, 0
         mov     Cnt, 0
       MOVmd     Len, Ltot

      .while (Len)
            mov     edi, SavS1
            mov     eax, pMemS1
            add     eax, edi
         INVOKE     BaseAscii, Cnt, eax, 8, HexDec, 0, 1, 1
            mov     edx, pMemS1
            mov     edi, SavS1
            mov     word ptr[edx+edi+8], 0A0Dh
            add     SavS1, 10
            add     Cnt, 16
            dec     Len
      .endw
         mov     edx, pMemS1
         mov     edi, SavS1
         mov     byte ptr[edx+edi], 0

         mov     Split1, 1
         mov     cr.cpMin, 0
         mov     cr.cpMax, -1
      INVOKE     SendMessage, hSplit1, EM_EXSETSEL, 0, addr cr
      INVOKE     SendMessage, hSplit1, EM_REPLACESEL, TRUE, pMemS1
      INVOKE     SendMessage, hSplit1, WM_SETREDRAW, 1, 0
      INVOKE     RedrawWindow, hSplit1, 0, 0, RDW_INVALIDATE
      INVOKE     UpdateWindow, hSplit1

      INVOKE     GetScrollInfo, hSplit3, SB_VERT, addr sci
         mov     ecx, sci.nPos
         shl     ecx, 16
         mov     eax, SB_THUMBPOSITION
         mov     cx, ax

      .if sw3
         INVOKE     SendMessage, hSplit1, WM_VSCROLL, ecx, 0
      .else
         INVOKE     SendMessage, hSplit3, WM_VSCROLL, ecx, 0
      .endif
         and     Split1, 0
         and     sw2, 0
      INVOKE     HeapDestroy, hMemS1
xor     eax, eax
         RET
Renumber ENDP

;======================================
;* Read file procedure
;======================================
ReadEM proc uses ebx edx esi edi lpFileName:DWORD, hwnd:DWORD

LOCAL     BytesO:DWORD, Cnt, Num, SavIn, hMemO, pMemO, hMemWC, pMemWC, hMemWN, pMemWN, WorkOut
LOCAL     hMemS1:DWORD, pMemS1, hMemS3, pMemS3, SavS1, SavS3, tbh, sbh
LOCAL     txtBuffer[260]:BYTE, szWorkS[12]
LOCAL     rect   :RECT

         cmp     Refresh, 0
         jne     GotFile
      INVOKE     SendMessage, hREdit, EM_GETMODIFY ,0, 0
      .if eax != FALSE
         INVOKE     Confirmation, hWnd
         .if eax == IDYES
              call     SaveFile
         .elseif eax == IDCANCEL
               mov     eax, 0
               ret
         .endif
      .endif

         mov     szFileName, 0
         mov     ofn.lStructSize, sizeof OPENFILENAME
       MOVmd     ofn.hwndOwner, hREdit
       MOVmd     ofn.hInstance, hInst
         mov     ofn.lpstrFilter, offset szFilter
         mov     ofn.lpstrFile, offset szFileName
         mov     ofn.nMaxFile, sizeof szFileName
         mov     ofn.lpstrTitle, offset szTitleO
         mov     ofn.Flags, OFN_EXPLORER or OFN_PATHMUSTEXIST or OFN_FILEMUSTEXIST or OFN_HIDEREADONLY
      INVOKE     GetOpenFileName, addr ofn
         cmp     eax, FALSE       ; Cancel'ed or error occurred
          je     NoFile

         and     OnlyRead, 0
      INVOKE     SendMessage, hREdit, EM_SETREADONLY, FALSE, 0
      INVOKE     CreateFile, offset szFileName,\
                 GENERIC_READ or GENERIC_WRITE,\
                 FILE_SHARE_READ or FILE_SHARE_WRITE,\
                 0, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, 0
         jmp     Past

ReadOnlyR:
         mov     OnlyRead, 1
      INVOKE     SendMessage, hREdit, EM_SETREADONLY, TRUE, 0
      INVOKE     CreateFile, addr szFileName,\
                 GENERIC_READ, FILE_SHARE_READ,\
                 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0

Past:
      .if eax == -1
           call     GetLastError
         .if eax == 32
            INVOKE     MessageBox, hWnd, addr szAccess, addr szDisplayName, MB_YESNO
            .if IDYES
                  jmp     ReadOnlyR
            .endif
               jmp     NoFile
         .else
            INVOKE     MessageBox, hWnd, addr szError7, addr szDisplayName, MB_OK
               jmp     NoFile
         .endif
      .endif
         mov     hFile, eax

         and     PE, 0
      INVOKE     GlobalAlloc, GMEM_MOVEABLE or GMEM_ZEROINIT, MemSize
         mov     hMem, eax
      INVOKE     GlobalLock, hMem
         mov     pMem, eax
      INVOKE     ReadFile, hFile, pMem, MemSize-1, addr bytesread, NULL

;---------- [Check for PE type file] ----------
         mov     ebx, pMem
         mov     ax, word ptr [ebx]
      .if ax == 'ZM'                        ; IMAGE_DOS_SIGNATURE  -DOS MZ header-
            mov     edx, 3Ch
            xor     eax, eax
            mov     al, byte ptr [ebx+edx]
            add     ebx, eax
            mov     eax, dword ptr [ebx]
         .if eax == 00004550h               ; IMAGE_NT_SIGNATURE   -PE header-
               mov     PE, 1
         .endif
      .endif

GotFile:
         mov     eax, bytesread
        imul     eax, 2
         mov     BytesO, eax
      INVOKE     HeapCreate, HEAP_GENERATE_EXCEPTIONS, BytesO, 0
         mov     hMemS1, eax
      INVOKE     HeapAlloc, hMemS1, HEAP_GENERATE_EXCEPTIONS, BytesO
         mov     pMemS1, eax

         mov     eax, bytesread
        imul     eax, 2
         mov     BytesO, eax
      INVOKE     HeapCreate, HEAP_GENERATE_EXCEPTIONS, BytesO, 0
         mov     hMemS3, eax
      INVOKE     HeapAlloc, hMemS1, HEAP_GENERATE_EXCEPTIONS, BytesO
         mov     pMemS3, eax

         mov     eax, bytesread
        imul     eax, 5
         mov     BytesO, eax
      INVOKE     HeapCreate, HEAP_GENERATE_EXCEPTIONS, BytesO, 0
         mov     hMemO, eax
      INVOKE     HeapAlloc, hMemO, HEAP_GENERATE_EXCEPTIONS, BytesO
         mov     pMemO, eax

         mov     eax, bytesread
        imul     eax, 4
         mov     BytesO, eax
      INVOKE     HeapCreate, HEAP_GENERATE_EXCEPTIONS, BytesO, 0
         mov     hMemWC, eax
      INVOKE     HeapAlloc, hMemWC, HEAP_GENERATE_EXCEPTIONS, BytesO
         mov     pMemWC, eax

         mov     eax, bytesread
        imul     eax, 4
         mov     BytesO, eax
      INVOKE     HeapCreate, HEAP_GENERATE_EXCEPTIONS, BytesO, 0
         mov     hMemWN, eax
      INVOKE     HeapAlloc, hMemWC, HEAP_GENERATE_EXCEPTIONS, BytesO
         mov     pMemWN, eax

         mov     SavIn, 0
         mov     BytesOut, 0
         mov     WorkOut, 0
         mov     SavS1, 0
         mov     SavS3, 0
         mov     Cnt, 0
         mov     Len, 17
.if bytesread < 17   ; N O T E  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    MOVmd     Len, bytesread
      inc     Len
.endif

LoopIt:
;---------- [Offset file] ----------
         mov     Num, 0
         mov     edi, SavS1
         mov     eax, pMemS1
         add     eax, edi
      INVOKE     BaseAscii, Cnt, eax, 8, HexDec, 0, 1, 1
         mov     edx, pMemS1
         mov     edi, SavS1
         mov     word ptr[edx+edi+8], 0A0Dh
         add     SavS1, 10
         mov     ecx, Len
         dec     ecx

      .while (ecx)
;---------- [Ascii file] ----------
            mov     esi, SavIn
            mov     ebx, pMem
            mov     edi, SavS3
            mov     edx, pMemS3
            mov     al, byte ptr [ebx+esi]
         .if  al < 20h || al > 7fh
               mov     byte ptr [edx+edi], 2eh
         .else
               mov     byte ptr [edx+edi], al
         .endif
            inc     SavS3

;---------- [Hex file] ----------
            mov     edi, BytesOut
            mov     edx, pMemO
            shr     eax, 4
            and     al, 0fh
         .if al > 9
            add     al, 37h
         .else
            add     al, 30h
         .endif
            mov     byte ptr[edx+edi], al

            mov     BytesOut, edi
            mov     edi, WorkOut
            mov     edx, pMemWC
            mov     byte ptr[edx+edi], al
            mov     edx, pMemWN
         .if al == 36h || al == 37h
               sub     al, 2h
         .endif
            mov     byte ptr[edx+edi], al
            inc     WorkOut
            mov     edi, BytesOut
            mov     edx, pMemO

            mov     al, byte ptr [ebx+esi]
            and     al, 0fh
         .if al > 9
               add     al, 37h
         .else
               add     al, 30h
         .endif
            inc     edi
            mov     byte ptr[edx+edi], al

            mov     BytesOut, edi
            mov     edi, WorkOut
            mov     edx, pMemWC
            mov     byte ptr[edx+edi], al
            mov     edx, pMemWN
            mov     byte ptr[edx+edi], al
            inc     WorkOut
            mov     edi, BytesOut
            mov     edx, pMemO

            inc     SavIn
            add     Num, 2
            inc     edi
            mov     eax, HexView
         .if Num == eax ;2 ;4 ;8 ;16
               mov     byte ptr[edx+edi], ' '
               inc     edi
               mov     Num, 0
         .endif
            dec     ecx
            mov     BytesOut, edi
      .endw

         dec     edi
      .if Num
            inc     edi
      .endif

      .if bytesread < 17    ; N O T E  !!!!!!!!!!!!!!!!!!!!!!!!!!
            inc     edi
            mov     BytesOut, edi
            mov     Len, 1
            jmp     NoMore
      .endif
         mov     byte ptr[edx+edi], ' '
         inc     edi
         mov     BytesOut, edi

         mov     edx, pMemS3
         mov     edi, SavS3
         mov     word ptr[edx+edi], 0A0Dh
         add     SavS3, 2

         mov     eax, bytesread
      .if SavIn < eax
            sub     eax, SavIn
         .if eax < 17
               inc     eax
               mov     Len, eax
         .endif
            add     Cnt, 16
            jmp     LoopIt
      .endif

NoMore:
         mov     edx, pMemS1
         mov     edi, SavS1
         mov     byte ptr[edx+edi], 0

         mov     edx, pMemO
         mov     edi, BytesOut
         mov     word ptr[edx+edi-1], 0A0Dh
         mov     byte ptr[edx+edi+1], 0

         mov     edx, pMemWC
         mov     edi, WorkOut
         mov     word ptr[edx+edi], 0A0Dh
         mov     byte ptr[edx+edi+2], 0

         mov     edx, pMemWN
         mov     word ptr[edx+edi], 0A0Dh
         mov     byte ptr[edx+edi+2], 0

         inc     BytesOut

         mov     edx, pMemS3
         mov     edi, SavS3
         add     edi, Len
         dec     edi
         mov     word ptr[edx+edi], 0A0Dh
         mov     byte ptr[edx+edi+2], 0

;INVOKE     CharToOem, pMemS3, pMemS3
;INVOKE     CharToOem, pMemO, pMemO

;         mov     stxt.flags, ST_KEEPUNDO ;or ST_SELECTION ;ST_DEFAULT ;ST_KEEPUNDO
;         mov     stxt.codepage, CP_ACP

      INVOKE     SendMessage, hSplit1, WM_SETTEXT, NULL, pMemS1
      INVOKE     SendMessage, hREdit, WM_SETTEXT, NULL, pMemO
;      INVOKE     SendMessage, hREdit, EM_SETTEXTEX, addr stxt, pMemO
      INVOKE     SendMessage, hWorkC, WM_SETTEXT, NULL, pMemWC
;      INVOKE     SendMessage, hWorkC, EM_SETTEXTEX, addr stxt, pMemWC
      INVOKE     SendMessage, hWorkN, WM_SETTEXT, NULL, pMemWN
;      INVOKE     SendMessage, hWorkN, EM_SETTEXTEX, addr stxt, pMemWN
      INVOKE     SendMessage, hSplit3, WM_SETTEXT, NULL, pMemS3

      INVOKE     HeapDestroy, hMemS1
      INVOKE     HeapDestroy, hMemO
      INVOKE     HeapDestroy, hMemWC
      INVOKE     HeapDestroy, hMemWN
      INVOKE     HeapDestroy, hMemS3

      .if !Refresh
         INVOKE     SendMessage, hREdit, EM_EMPTYUNDOBUFFER, 0, 0
         INVOKE     SendMessage, hWorkC, EM_EMPTYUNDOBUFFER, 0, 0
         INVOKE     SendMessage, hWorkN, EM_EMPTYUNDOBUFFER, 0, 0
      .endif
      INVOKE     SendMessage, hREdit, EM_SETMODIFY, 0, 0

      .if Refresh
         .if Refresh == 1
            INVOKE     SendMessage, hREdit, EM_SETMODIFY, 1, 0
         .endif
            jmp     GUnlock
      .endif
      INVOKE     CloseHandle, hFile

GUnlock:
      .if Refresh == 44
         INVOKE     HeapDestroy, hMem
      .else
         INVOKE     GlobalUnlock, pMem
         INVOKE     GlobalFree, hMem
      .endif
      INVOKE     BaseAscii, bytesread, addr szWorkS, 8, 10, 1, 0, 1
      INVOKE     lstrcpy, addr txtBuffer, addr szOpenedAt
      INVOKE     lstrcat, addr txtBuffer, addr szWorkS
      INVOKE     lstrcat, addr txtBuffer, addr bytes
      INVOKE     SendMessage, hwndStat, SB_SETTEXT, 0, addr txtBuffer
      .if szFileName
         INVOKE     SetWindowText, hWnd, addr szFileName
      .endif

      .if Refresh != 1
         INVOKE     GetScrollInfo, hSplit3, SB_VERT, addr sci
          MOVmd     sci.nPos, 0
         INVOKE     SetScrollInfo, hSplit3, SB_VERT, addr sci, 1
            xor     ecx, ecx
            mov     eax, SB_THUMBTRACK
            mov     cx, ax
         INVOKE     SendMessage, hSplit3, WM_VSCROLL, ecx, 0
            and     sw2, 0
            and     syPos, 0
           call     ScreenLines
      .endif

         and     Refresh, 0
      .if bytesread < 17 ;|| !NoSize ; N O T E !!!!!!!!!!!!!!!!!!!!
            jmp     NoFile
      .endif
      INVOKE     GetClientRect, hWnd, addr rect
         mov     ebx, rect.right
         mov     ecx, rect.bottom
         sub     ebx, rect.left
         sub     ecx, rect.top
         shl     ecx, 16
         mov     cx, 0
      INVOKE     SendMessage, hWnd, WM_SIZE, SIZE_RESTORED, ecx
         and     NoSize, 0

NoFile:
         ret
ReadEM endp

;======================================
;* Confirmation procedure
;======================================
Confirmation proc hwnd:DWORD

      INVOKE     MessageBox, hwnd, addr ConfirmMsg, addr szDisplayName,
                 MB_YESNOCANCEL or MB_ICONQUESTION
         ret
Confirmation endp

;======================================
;* Write file procedure
;======================================
WriteEM proc uses ebx edx esi edi lpFileName:DWORD, SW

LOCAL     hMemIN:DWORD, pMemIN, BytesO, SavIn, SavOut
LOCAL     txtBuffer[64], szWorkS[10]

         mov     SavIn, 0
         mov     SavOut, 0
         cmp     Refresh, 0
         jne     NoFile
      .if SW
         INVOKE     lstrlen, addr szBuff
            mov     BytesO, eax
            lea     eax, offset szBuff
            mov     pMemIN, eax
            lea     eax, offset szFind
            mov     pMem, eax
            jmp     LoopIt
      .endif

      INVOKE     CreateFile, lpFileName,\
                 GENERIC_READ or GENERIC_WRITE,\
                 FILE_SHARE_READ or FILE_SHARE_WRITE,\
                 0, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, 0
         mov     hFile, eax

NoFile:
      INVOKE     GlobalAlloc, GMEM_MOVEABLE or GMEM_ZEROINIT, MemSize
         mov     hMemIN, eax
      INVOKE     GlobalLock, hMemIN
         mov     pMemIN, eax
      INVOKE     SendMessage, hREdit, WM_GETTEXT, MemSize-1, pMemIN

         mov     BytesO, eax
      INVOKE     HeapCreate, HEAP_GENERATE_EXCEPTIONS, BytesO, 0
         mov     hMem, eax
      INVOKE     HeapAlloc, hMem, HEAP_GENERATE_EXCEPTIONS, BytesO
         mov     pMem, eax

LoopIt:
         mov     ecx, BytesO
      .while (SavIn <= ecx)
            mov     esi, SavIn
            mov     ebx, pMemIN
            mov     edi, SavOut
            mov     edx, pMem
            xor     eax, eax
            mov     al, byte ptr [ebx+esi]
         .if al == 0ah || al == 0dh || al == 20h
               inc     SavIn
               jmp     LoopIt
         .endif
            mov     ax, word ptr [ebx+esi]
            mov     word ptr szWorkS, ax
            mov     eax, 2
            xor     ecx, ecx
         .while (eax)
            .if byte ptr szWorkS[ecx] > 60h
                  sub     byte ptr szWorkS[ecx], 57h
            .elseif byte ptr szWorkS[ecx] > 40h
                  sub     byte ptr szWorkS[ecx], 37h
            .else
                  xor     byte ptr szWorkS[ecx], 30h
            .endif
               dec     eax
               inc     ecx
         .endw

            mov     al, byte ptr szWorkS
           imul     eax, 16
            mov     ecx, eax
            mov     al, byte ptr szWorkS+1
            and     eax, 000000ffh
            add     ecx, eax
         .if SW && SW != 17
            .if  cl < 20h || cl > 7fh
                  mov     cl, 2eh
            .endif
         .endif
            mov     byte ptr [edx+edi], cl
            add     SavIn, 2
            inc     SavOut
            jmp     LoopIt
      .endw
      .if SW
            mov     byte ptr [edx+edi], 0
            ret
      .endif
         dec     SavOut

      .if Refresh
mov     byte ptr [edx+edi], 0
         INVOKE     GlobalUnlock, pMemIN
         INVOKE     GlobalFree, hMemIN
          MOVmd     bytesread, SavOut
         INVOKE     ReadEM, addr szFileName, hREdit
            ret
      .endif

         mov     ecx, SavOut
      INVOKE     WriteFile, hFile, pMem, ecx, addr bytesread, NULL
      INVOKE     CloseHandle, hFile
      INVOKE     GlobalUnlock, pMemIN
      INVOKE     GlobalFree, hMemIN
      INVOKE     HeapDestroy, hMem
      INVOKE     BaseAscii, bytesread, addr szWorkS, 8, 10, 1, 0, 1
      INVOKE     lstrcpy, addr txtBuffer, addr szSavedAt
      INVOKE     lstrcat, addr txtBuffer, addr szWorkS
      INVOKE     lstrcat, addr txtBuffer, addr bytes
      INVOKE     SendMessage, hwndStat, SB_SETTEXT, 0, addr txtBuffer
      INVOKE     SendMessage, hREdit, EM_SETMODIFY, FALSE, 0
         ret

WriteEM endp

;======================================
;* Save file as procedure
;======================================
SaveFileAs proc

         mov     ofn.lStructSize, sizeof ofn
       MOVmd     ofn.hwndOwner, hWnd
       MOVmd     ofn.hInstance, hInst
         mov     ofn.lpstrFilter, offset szFilter
         mov     ofn.lpstrFile, offset szFileName
         mov     ofn.nMaxFile, sizeof szFileName
         mov     ofn.lpstrTitle, offset szTitleS
         mov     ofn.Flags, OFN_EXPLORER or OFN_OVERWRITEPROMPT or OFN_CREATEPROMPT
      INVOKE     GetSaveFileName, addr ofn
         cmp     eax, FALSE       ;Cancel'ed or error occurred
          je     NoFile
      INVOKE     WriteEM, addr szFileName, 0
      INVOKE     SetWindowText, hWnd, addr szFileName
NoFile:

    ret

SaveFileAs endp

;======================================
;* Save file procedure
;======================================
SaveFile proc

LOCAL     buffer[128]:BYTE

;---------- [Test if title is 'Untitled'] ----------
    INVOKE     GetWindowText, hWnd, addr buffer, 128
    INVOKE     lstrcmp, addr buffer, addr szUntitled
    .if eax == 0
       INVOKE     SaveFileAs
          ret
    .endif
    INVOKE     WriteEM ,addr buffer, 0

    ret

SaveFile endp

;=========================================================================
;* SCREEN LINES & CHAR'S PER LINE PROCEDURE                              *
;=========================================================================
ScreenLines PROC uses ebx edx

LOCAL            tm:TEXTMETRIC
LOCAL            rect:RECT
LOCAL            pt:POINT

      INVOKE     SendMessage, hREdit, EM_GETLINECOUNT, 0, 0    ; Returns total# of lines + 1
         dec     eax
         mov     Ltot, eax
      INVOKE     GetClientRect, hREdit, addr rect
      INVOKE     GetDC, hREdit
         mov     hDC, eax
      INVOKE     SelectObject, hDC, hFont
      INVOKE     GetTextMetrics, hDC, addr tm

;      INVOKE     GetTextExtentPoint32, hDC, addr szTest, sizeof szTest, addr pt
;DSPValue hWnd, pt.y
;      INVOKE     GetTextCharacterExtra, hDC
;DSPValue hWnd, eax

      INVOKE     ReleaseDC, hREdit, hDC
         mov     eax, tm.tmHeight
      .if charF.yHeight == 160
            add     eax, tm.tmInternalLeading
      .endif
         add     eax, tm.tmExternalLeading
         mov     cyChar, eax
         mov     eax, rect.bottom     ; Load dividend
         and     edx, 0
         div     cyChar
         mov     NScrL, eax           ; Number of lines per screen

;DSPValue hWnd, NScrL
;DSPValue hWnd, tm.tmHeight
;DSPValue hWnd, tm.tmAscent
;DSPValue hWnd, tm.tmDescent
;DSPValue hWnd, tm.tmInternalLeading
;DSPValue hWnd, tm.tmExternalLeading

         mov     ebx, LineCnt
         mov     eax, tm.tmAveCharWidth
         dec     eax
         mov     PPC, eax
        imul     eax, ebx
         inc     eax
         mov     Lmax, eax
         RET
ScreenLines ENDP

;======================================
;* Edit subclass procedure
;======================================
REditProc proc uses ebx edx esi edi hwnd:DWORD, wMsg, wParam, lParam
LOCAL     SavIn:DWORD, Cnt
LOCAL     szWorkS[10]:BYTE

         mov     eax, hwnd
      .if eax == hSplit1
         INVOKE     CallWindowProc, hREditSub, hwnd, wMsg, wParam, lParam
         .if !Split1
               xor     eax, eax
         .endif
            ret
      .endif

      .if wMsg == 4455
          MOVmd     SavPos, cr.cpMin
          MOVmd     xPos, cr.cpMin
            jmp     FromCutPaste
      .endif

      .if wMsg == WM_LBUTTONDBLCLK
            mov     eax, 1
            ret
      .endif

      .if wMsg == WM_LBUTTONDOWN ;|| wMsg == WM_KEYUP
         .if !w4
               mov     w4, 1
            INVOKE     SendMessage, hREdit, WM_LBUTTONDOWN, MK_LBUTTON, lParam
         .endif
         INVOKE     SendMessage, hREdit, EM_EXGETSEL, 0, addr cr
          MOVmd     cr.cpMax, cr.cpMin
         INVOKE     SendMessage, hREdit, EM_EXSETSEL, 0, addr cr
          MOVmd     xPos, cr.cpMin
          MOVmd     SavPos, cr.cpMin
            mov     eax, lParam
            and     eax, 0000ffffh
            mov     xCur, eax
         .if wMsg == WM_LBUTTONDOWN
               mov     sw1, 55
               jmp     FromLBD
         .endif
      .endif

      .if wMsg == WM_LBUTTONUP
            and     w4, 0
         INVOKE     SendMessage, hREdit, WM_GETTEXTLENGTH, 0, 0
            mov     TextLen, eax
         INVOKE     SendMessage, hREdit, EM_EXGETSEL, 0, addr cr
         INVOKE     SendMessage, hREdit, EM_EXLINEFROMCHAR, 0, cr.cpMin
            mov     Lnum, eax
            mov     eax, cr.cpMin
         .if eax == cr.cpMax
            INVOKE     SendMessage, hSplit3, EM_EXGETSEL, 0, addr cr
               mov     eax, cr.cpMin
            .if eax != cr.cpMax
               INVOKE     REditProc, hREdit, WM_MOUSEMOVE, MK_LBUTTON, 0
            .endif

         .else
            INVOKE     SendMessage, hREdit, EM_EXGETSEL, 0, addr cr
            INVOKE     SendMessage, hREdit, EM_GETSELTEXT, 0, addr szBuff
               mov     Len, eax
            .if byte ptr szBuff == 20h
                  inc     cr.cpMin
            .endif
               mov     ecx, eax
               and     Space, 0
               xor     esi, esi
            .while (ecx)
               .if byte ptr szBuff[esi] == 20h
                     add     Space, 1
               .endif
                  inc     esi
                  dec     ecx
            .endw
               sub     eax, Space
               xor     edx, edx
               mov     ebx, 2
               div     ebx
               mov     eax, xPos
            .if edx && eax <= cr.cpMin
                  inc     cr.cpMax
                  add     sMax, 1
            .elseif edx && eax > cr.cpMin
                  dec     cr.cpMin
                  dec     LineOff
                  sub     sMin,1
            .endif
            INVOKE     SendMessage, hREdit, EM_EXSETSEL, 0, addr cr
             MOVmd     cr.cpMin, sMin
             MOVmd     cr.cpMax, sMax
            INVOKE     SendMessage, hSplit3, EM_EXSETSEL, 0, addr cr

            INVOKE     SendMessage, hREdit, EM_GETSELTEXT, 0, addr szBuff
               mov     eax, LineOff
               shl     eax, 1
               mov     LineOff, eax
              call     WorkSel
         .endif
           call     EnableDisableMenuTool

      .elseif wMsg == WM_MOUSEMOVE
         .if wParam == MK_LBUTTON
               and     w4, 0

               mov     eax, lParam
               shr     eax, 16
               add     eax, 3
            .if eax > wHth      ; Don't select past the last line
                  xor     eax, eax
                  ret
            .endif

            INVOKE     SendMessage, hREdit, EM_EXGETSEL, 0, addr cr
               mov     eax, cr.cpMax
               sub     eax, cr.cpMin
            .if eax > 256
                  jmp     EndIt
            .endif

FromLBD:
            INVOKE     SendMessage, hREdit, EM_EXGETSEL, 0, addr cr
               mov     eax, cr.cpMax
               sub     eax, cr.cpMin
            .if eax > 256
                  jmp     EndIt
            .endif

            INVOKE     SendMessage, hREdit, EM_EXLINEFROMCHAR, 0, cr.cpMin
               mov     Lnum, eax
            INVOKE     SendMessage, hREdit, EM_LINEINDEX, Lnum, 0
               mov     FileOff, eax
               mov     word ptr szWork, 60
            INVOKE     SendMessage, hREdit, EM_GETLINE, Lnum, addr szWork
               mov     byte ptr szWork[eax], 0 
            INVOKE     SendMessage, hREdit, EM_GETSELTEXT, 0, addr szBuff
               mov     ecx, cr.cpMin
               sub     ecx, FileOff
               mov     LineOff, ecx
              push     ecx

               and     Space, 0
               and     LineOff, 0
               xor     esi, esi
               add     ecx, 2
            .while (esi < ecx)
               .if byte ptr szWork[esi] == 20h
                     add     Space, 1
                     inc     esi
               .endif
               .if byte ptr szWork[esi] != 20h
                     inc     LineOff
               .endif
                  add     esi, 2
            .endw
               dec     LineOff
               mov     ebx, Lnum
              imul     ebx, 16
               add     ebx, LineOff
               mov     FileOffS, ebx
             MOVmd     LineOffS, LineOff
            INVOKE     BaseAscii, ebx, addr szWorkS, 1, HexDec, 0, 1, 1
            INVOKE     lstrcpy, addr szStat, addr szFileOff
            INVOKE     lstrcat, addr szStat, addr szWorkS
            INVOKE     SendMessage, hwndStat, SB_SETTEXT, 1, addr szStat

            INVOKE     BaseAscii, LineOff, addr szWorkS, 1, HexDec, 0, 1, 1
            INVOKE     lstrcpy, addr szStat, addr szLineOff
            INVOKE     lstrcat, addr szStat, addr szWorkS
            INVOKE     SendMessage, hwndStat, SB_SETTEXT, 2, addr szStat

               pop     ecx

            .if sw1 == 55              ; From WM_LBUTTONDOWN
                  mov     eax, LineOff
                  shl     eax, 1
                  mov     LineOff, eax
                  and     Match, 0
                 call     WorkSel
                  and     sw1, 0
                  jmp     EndIt
            .endif

            .if byte ptr szWork[ecx+1] == 20h || byte ptr szWork[ecx] == 20h
                  sub     Space, 1
            .endif

               mov     eax, xPos
               mov     ebx, lParam
               and     ebx, 0000ffffh
            .if byte ptr szBuff == 20h && eax <= cr.cpMin && ebx > xCur
                  inc     cr.cpMin
                  inc     cr.cpMax
               INVOKE     SendMessage, hREdit, EM_EXSETSEL, 0, addr cr
            .endif

               mov     eax, xPos
               sub     eax, FileOff
               sub     eax, Space
               xor     edx, edx
               mov     ebx, 2
               div     ebx
               mov     eax, xPos
               mov     ebx, lParam
               and     ebx, 0000ffffh
            .if edx && eax == cr.cpMin && ebx > xCur
                  inc     cr.cpMin
                  inc     cr.cpMax
                  inc     xPos
               INVOKE     SendMessage, hREdit, EM_EXSETSEL, 0, addr cr
            .elseif edx && eax == cr.cpMin && ebx < xCur
                  dec     cr.cpMin
                  dec     cr.cpMax
               INVOKE     SendMessage, hREdit, EM_EXSETSEL, 0, addr cr
            .endif

            INVOKE     SendMessage, hREdit, EM_GETSELTEXT, 0, addr szBuff
            INVOKE     lstrlen, addr szBuff
            .if byte ptr szBuff[eax-1] == 20h || byte ptr szBuff[eax] == 20h
                  dec     cr.cpMax
               INVOKE     SendMessage, hREdit, EM_EXSETSEL, 0, addr cr
            .endif
            INVOKE     SendMessage, hREdit, EM_GETSELTEXT, 0, addr szBuff
               mov     Len, eax
               xor     ecx, ecx
               xor     esi, esi
            .while (eax)
               .if byte ptr szBuff[esi] == 20h
                     inc     ecx
               .endif
                  inc     esi
                  dec     eax
            .endw
               sub     Len, ecx
               mov     eax, Len
               xor     edx, edx
               mov     ebx, 2
               div     ebx

               mov     eax, xPos
               mov     ebx, lParam
               and     ebx, 0000ffffh
            .if edx && eax == cr.cpMin && ebx > xCur
                  dec     cr.cpMax
               INVOKE     SendMessage, hREdit, EM_EXSETSEL, 0, addr cr
            .endif
            INVOKE     SendMessage, hREdit, EM_GETSELTEXT, 0, addr szBuff

            INVOKE     SendMessage, hSplit3, EM_LINEINDEX, Lnum, 0
               add     eax, LineOff
               mov     Hold, eax
               and     SavIn, 0
               and     Cnt, 0
               mov     ecx, cr.cpMax
               sub     ecx, cr.cpMin

LoopIt:
            .while (ecx)
                  mov     esi, SavIn
                  mov     ebx, offset szBuff
                  xor     eax, eax
                  mov     al, byte ptr [ebx+esi]
               .if al == 20h
                     inc     SavIn
                     dec     ecx
                     jmp     LoopIt
               .endif
                  inc     SavIn
                  inc     Cnt
                  dec     ecx
            .endw

            INVOKE     SendMessage, hREdit, EM_EXLINEFROMCHAR, 0, cr.cpMax
               mov     LastLine, eax
               xor     edx, edx
               mov     eax, Cnt
               mov     ebx, 2
               div     ebx
             MOVmd     cr.cpMin, Hold 
             MOVmd     cr.cpMax, Hold 
               add     cr.cpMax, eax
               mov     eax, LastLine
               sub     eax, Lnum
               add     cr.cpMax, eax
            INVOKE     SendMessage, hSplit3, EM_EXSETSEL, 0, addr cr
             MOVmd     sMin, cr.cpMin
             MOVmd     sMax, cr.cpMax
         .endif
;  call     EnableDisableMenuTool

      .elseif wMsg == WM_KEYDOWN
         .if wParam == VK_PGUP || wParam == VK_PGDN || wParam == VK_UP || wParam == VK_DOWN
            INVOKE     SetFocus, hSplit3
               xor     eax, eax
               ret
         .endif

      .elseif wMsg == WM_KEYUP
         .if wParam == VK_F1
            INVOKE     ShellAbout, hWnd, addr szDisplayName, addr AboutMsg, hIcon

         .elseif wParam == VK_ESCAPE
            INVOKE     SendMessage, hWnd, WM_SYSCOMMAND, SC_CLOSE, NULL
               xor     eax, eax
               ret
         .endif
         INVOKE     SendMessage, hREdit, EM_GETMODIFY ,0, 0

         .if eax != 0
            INVOKE     SendMessage, hREdit, EM_EXGETSEL, 0, addr cr
            INVOKE     SendMessage, hREdit, EM_EXLINEFROMCHAR, 0, cr.cpMin
               mov     Lnum, eax
               mov     word ptr szBuff, 60
            INVOKE     SendMessage, hREdit, EM_GETLINE, Lnum, addr szBuff
               mov     byte ptr szBuff[eax], 0
               mov     Len, eax
               xor     esi, esi
               xor     edi, edi

;---------- [Validate user input characters] ----------
            INVOKE     lstrlen, addr szBuff
            .while (eax)
                  mov     bl, byte ptr szBuff[esi]
               .if bl != 20h
                  .if bl > 2fh && bl < 3ah || bl > 40h && bl < 47h ||\
                      bl > 60h && bl < 67h || bl == 0Ah || bl == 0Dh
                     .if bl > 60h && bl < 67h
                           sub     bl, 20h
                     .endif
                        mov     byte ptr szWork[edi], bl
                        inc     edi
                  .else
                     INVOKE     SendMessage, hREdit, WM_UNDO, 0, 0
                     INVOKE     MessageBeep, MB_OK
                        jmp     EndIt
                  .endif
               .endif
                  inc     esi
                  dec     eax
            .endw
               mov     byte ptr szWork[edi], 0

            INVOKE     lstrlen, addr szWork
               dec     eax    ; Don't count CR
               dec     Len    ; Don't count CR
               xor     edx, edx
               mov     ebx, 2
               div     ebx
            .if eax && !edx
               INVOKE     SendMessage, hWorkC, EM_LINEINDEX, Lnum, 0
                  mov     cr.cpMin, eax
                  mov     cr.cpMax, eax
                  add     cr.cpMax, 32
               INVOKE     SendMessage, hWorkC, EM_EXSETSEL, 0, addr cr
               INVOKE     SendMessage, hWorkC, EM_REPLACESEL, TRUE, addr szWork
               INVOKE     SendMessage, hWorkN, EM_EXSETSEL, 0, addr cr
               INVOKE     SendMessage, hWorkN, EM_REPLACESEL, TRUE, addr szWork
            .endif

               mov     eax, Len
               mov     ecx, eax
               xor     esi, esi
               xor     eax, eax
            .while (ecx)
               .if byte ptr szBuff[esi] != 20h
                     inc     eax
               .endif
                  inc     esi
                  dec     ecx
            .endw
               mov     ecx, eax
               xor     edx, edx
               mov     ebx, 2
               div     ebx
            .if !edx
;               .if ecx == 32
;                    call     CopyLine
;                     mov     eax, Ltot
;                  .if eax == Lnum && Ltot != eax
;                        inc     Lnum
;                     INVOKE     SendMessage, hREdit, EM_LINEINDEX, Lnum, 0
;                        mov     cr.cpMin, eax
;                        mov     cr.cpMax, eax
;                     INVOKE     SendMessage, hREdit, EM_EXSETSEL, 0, addr cr
;                  .endif
;               .elseif Len > 1
               .if Len > 1

;---------- [Check for insertion or deletions] ----------
FromCutPaste:
                  INVOKE     SendMessage, hREdit, WM_GETTEXTLENGTH, 0, 0
                  .if eax > TextLen
                     .if !InsNotify
                           jmp     DoIt
                     .endif
                     INVOKE     MessageBox, hWnd, addr szInsert, addr szDisplayName,
                                MB_YESNO or MB_ICONSTOP or MB_TASKMODAL
                     .if eax == IDYES
                           jmp     DoIt
                     .endif
                  .elseif eax < TextLen
                     .if !DelNotify
                           jmp     DoIt
                     .endif
                     INVOKE     MessageBox, hWnd, addr szDelete, addr szDisplayName,
                                MB_YESNO or MB_ICONSTOP or MB_TASKMODAL
                     .if eax == IDYES
                           jmp     DoIt
                     .endif
                  .else
                        jmp     DoIt
                  .endif
                     jmp     FixIt

DoIt:
                     mov     Refresh, 1
                    push     xPos
                  INVOKE     WriteEM, addr szFileName, 0
                     pop     xPos
                  INVOKE     SendMessage, hREdit, EM_LINEINDEX, Lnum, 0
                     mov     SavPos, eax
                    push     eax
                  INVOKE     SendMessage, hREdit, EM_LINELENGTH, SavPos, 0
                     add     SavPos, eax 
                  .if wMsg != 4455       ; From Cut Paste
                        add     xPos, 2
                      MOVmd     SavPos, xPos
                  .else
                      MOVmd     SavPos, xPos
                  .endif
                     mov     word ptr szBuff, 60
                  INVOKE     SendMessage, hREdit, EM_GETLINE, Lnum, addr szBuff
                     mov     byte ptr szBuff[eax], 0
                     pop     eax
                     mov     ebx, SavPos
                     sub     ebx, eax
                 .if byte ptr szBuff[ebx-2] == 20h || byte ptr szBuff[ebx+1] == 20h || ebx == 1
                       inc     SavPos
                 .endif
                   MOVmd     xPos, SavPos
                   MOVmd     cr.cpMin, SavPos
                   MOVmd     cr.cpMax, cr.cpMin
                  INVOKE     SendMessage, hREdit, EM_EXSETSEL, 0, addr cr
               .endif
                  jmp     NoFix

FixIt:
               INVOKE     SendMessage, hREdit, WM_UNDO, 0, 0
               INVOKE     SendMessage, hWorkC, WM_UNDO, 0, 0
               INVOKE     SendMessage, hWorkN, WM_UNDO, 0, 0

NoFix:
                 call     EnableDisableMenuTool
               .if wMsg == 4455   ; From cut/paste
                     xor     eax, eax
                     ret
               .endif
            .endif
         .endif
      .endif

EndIt:
      INVOKE     CallWindowProc, hREditSub, hwnd, wMsg, wParam, lParam
         ret

REditProc endp

;======================================
; Copy line from hex to ascii
;======================================
CopyLine proc

   INVOKE     SendMessage, hREdit, EM_EXGETSEL, 0, addr cr
   INVOKE     SendMessage, hREdit, EM_EXLINEFROMCHAR, 0, cr.cpMin
      mov     Lnum, eax

         mov     word ptr szBuff, 60
      INVOKE     SendMessage, hREdit, EM_GETLINE, Lnum, addr szBuff
         mov     byte ptr szBuff[eax], 0
      INVOKE     WriteEM, 0, 1
      INVOKE     SendMessage, hSplit3, EM_LINEINDEX, Lnum, 0
         mov     cr.cpMin, eax
         mov     cr.cpMax, eax
         mov     word ptr szBuff, 60
      INVOKE     SendMessage, hSplit3, EM_GETLINE, Lnum, addr szBuff
         dec     eax
         add     cr.cpMax, eax
      INVOKE     SendMessage, hSplit3, EM_EXSETSEL, 0, addr cr
      INVOKE     SendMessage, hSplit3, EM_REPLACESEL, FALSE, addr szFind ;TRUE
         ret

CopyLine endp

;=======================================
; Split subclass procedure Ascii window
;=======================================
SplitProc proc uses ebx edx esi hwnd:DWORD, wMsg, wParam, lParam
LOCAL     Cnt:DWORD, Num
LOCAL     Buff[512]:BYTE

      .if wMsg == WM_KEYUP
         .if wParam == VK_PGUP || wParam == VK_PGDN || wParam == VK_UP || wParam == VK_DOWN
            INVOKE     GetScrollInfo, hSplit3, SB_VERT, addr sci
               mov     eax, sci.nPos
               shl     eax, 16
               mov     ecx, SB_THUMBPOSITION
               mov     ax, cx
               mov     yPos, eax
               jmp     DoKeyBrd
         .endif
      .endif

      .if wMsg == 777
         INVOKE     lstrcpy, addr Buff, addr szBuff
            jmp     FromFind

      .elseif wMsg == WM_VSCROLL
         INVOKE     GetScrollInfo, hSplit3, SB_VERT, addr sci
            mov     sw3, 1
            mov     eax, wParam
            and     eax, 0000ffffh
         .if !sw2
               mov     sw2, 1
             finit
              fild     syPos
              fstp     R10
         .endif
         .if eax == SB_THUMBTRACK
               mov     eax, wParam
               shr     eax, 16
               mov     ecx, eax
            .if eax == syPos
                  jmp     PosOK
            .endif
            .if eax != xPos

            .endif
            .if eax > syPos

            .endif
               mov     syPos, eax
               shl     eax, 16
               mov     ecx, SB_THUMBPOSITION
               mov     ax, cx
               mov     yPos, eax
               and     sw3, 0

         .elseif eax == SB_LINEDOWN
               mov     eax, SB_LINEDOWN
               mov     yPos, eax

         .elseif eax == SB_LINEUP
               mov     eax, SB_LINEUP
               mov     yPos, eax

         .elseif eax == SB_PAGEDOWN
               mov     eax, SB_PAGEDOWN
               mov     yPos, eax

         .elseif eax == SB_PAGEUP
               mov     eax, SB_PAGEUP
               mov     yPos, eax
         .endif

         .if wParam == SB_ENDSCROLL
               and     sw2, 0

         .else
DoKeyBrd:
            INVOKE     SendMessage, hSplit1, WM_VSCROLL, yPos, 0
            INVOKE     SendMessage, hREdit, WM_VSCROLL, yPos, 0
               mov     eax, yPos
               shr     eax, 16
               and     eax, 0000ffffh
               mov     sci.nPos, eax
            INVOKE     SetScrollInfo, hSplit3, SB_VERT, addr sci, 1

PosOK:
      .endif

      .elseif wMsg == WM_LBUTTONDOWN
         .if !w4
               mov     w4, 1
            INVOKE     SendMessage, hSplit3, WM_LBUTTONDOWN, MK_LBUTTON, lParam
         .endif

      .elseif wMsg == WM_LBUTTONUP
            and     w4, 0
         INVOKE     SendMessage, hSplit3, EM_EXGETSEL, 0, addr cr
            mov     eax, cr.cpMin
         .if eax == cr.cpMax
            INVOKE     SendMessage, hREdit, EM_EXGETSEL, 0, addr cr
             MOVmd     cr.cpMax, cr.cpMin
            INVOKE     SendMessage, hREdit, EM_EXSETSEL, 0, addr cr
         .else
            INVOKE     SendMessage, hREdit, EM_GETSELTEXT, 0, addr szBuff
             MOVmd     LineOff, SavOff
               mov     eax, LineOff
               shl     eax, 1
               mov     LineOff, eax
              call     WorkSel
         .endif
           call     EnableDisableMenuTool

      .elseif wMsg == WM_MOUSEMOVE
         .if wParam == MK_LBUTTON
               and     w4, 0

               mov     eax, lParam
               shr     eax, 16
               add     eax, 3
            .if eax > wHth      ; Don't select past the last line
                  xor     eax, eax
                  ret
            .endif

            INVOKE     SendMessage, hSplit3, EM_EXGETSEL, 0, addr cr
            INVOKE     SendMessage, hSplit3, EM_EXLINEFROMCHAR, 0, cr.cpMin
               mov     Lnum, eax
            INVOKE     SendMessage, hSplit3, EM_LINEINDEX, Lnum, 0
               mov     FileOff, eax
               mov     word ptr szWork, 60
            INVOKE     SendMessage, hREdit, EM_GETLINE, Lnum, addr szWork
               mov     byte ptr szWork[eax], 0 
            INVOKE     SendMessage, hSplit3, EM_EXLINEFROMCHAR, 0, cr.cpMax
               mov     LastLine, eax
               mov     eax, cr.cpMax
               sub     eax, cr.cpMin ; Ascii selection length
               mov     Len, eax
            .if eax > 170 ;256
                  jmp     EndIt
            .endif
               mov     ecx, cr.cpMin
               sub     ecx, FileOff  ; Ascii start of select
               mov     SavOff, ecx
               xor     esi, esi
               mov     ebx, ecx
            .while (ebx)
                  add     esi, 2
               .if byte ptr szWork[esi] == 20h
                     inc     esi
               .endif
                  dec     ebx
            .endw
               mov     LineOff, esi  ; esi = hex line offset

            INVOKE     lstrcpy, addr Buff, addr szWork[esi]

FromFind:
               mov     eax, LastLine
               sub     eax, Lnum
               inc     eax
               mov     Cnt, eax
             MOVmd     Num, Lnum
            .while (Cnt)
                  add     Num, 1
                  mov     word ptr szWork, 60
               INVOKE     SendMessage, hREdit, EM_GETLINE, Num, addr szWork
                  mov     byte ptr szWork[eax], 0
               INVOKE     lstrcat, addr Buff, addr szWork
                  dec     Cnt
            .endw 

            INVOKE     SendMessage, hREdit, EM_LINEINDEX, Lnum, 0
               add     eax, LineOff
               mov     cr.cpMin, eax
               mov     cr.cpMax, eax
               mov     eax, LastLine
               sub     eax, Lnum
               mov     ecx, Len
            .if wMsg != 777            ; 777 is from Find
                  sub     ecx, eax
            .endif
               xor     esi, esi
            .while (ecx)
                  add     esi, 2
               .if wMsg == 777
                     dec     esi
               .endif
               .if byte ptr Buff[esi] == 20h
                     inc     esi
               .endif
                  dec     ecx
            .endw
            .if byte ptr Buff[esi-1] == 20h
                  dec     esi
            .endif
             MOVmd     cr.cpMax, cr.cpMin
               add     cr.cpMax, esi
            INVOKE     SendMessage, hREdit, EM_EXSETSEL, 0, addr cr
         .endif
      .endif

EndIt:
      INVOKE     CallWindowProc, hSplitSub, hwnd, wMsg, wParam, lParam
         ret

SplitProc endp

;======================================
; Set the select in the work windows
;======================================
WorkSel PROC  uses ebx esi edi
LOCAL    Val:DWORD

         xor     esi, esi
         xor     edi, edi
      INVOKE     lstrlen, addr szBuff
      .while (eax)
            mov     bl, byte ptr szBuff[esi]
         .if bl != 20h
               mov     byte ptr szWork[edi], bl
               inc     edi
         .endif
            inc     esi
            dec     eax
      .endw
         mov     byte ptr szWork[edi], 0

         lea     eax, offset szWork
         mov     ft.lpstrText, eax
      INVOKE     lstrlen, addr szWork
         mov     Len, eax
      INVOKE     SendMessage, hWorkC, EM_LINEINDEX, Lnum, 0
         add     eax, LineOff
         mov     Val, eax
         mov     ft.chrg.cpMin, eax
         mov     ft.chrg.cpMax, -1
         mov     Flag, 1
      INVOKE     SendMessage, hWorkC, EM_FINDTEXT, Flag, offset ft
      .if eax != -1
            mov     cr.cpMin, eax
            add     eax, Len
            mov     cr.cpMax, eax
         INVOKE     SendMessage, hWorkC, EM_EXSETSEL, 0, offset cr
         INVOKE     SendMessage, hWorkN, EM_EXSETSEL, 0, offset cr
      .elseif eax == -1 && sw1 == 55
          MOVmd     cr.cpMin, Val
          MOVmd     cr.cpMax, cr.cpMin
         INVOKE     SendMessage, hWorkC, EM_EXSETSEL, 0, offset cr
         INVOKE     SendMessage, hWorkN, EM_EXSETSEL, 0, offset cr
      .endif
         ret

WorkSel endp

;========================================================================
; Converts a Dec, Hex, Oct or Bin ascii string to a 32 bit num value.
;========================================================================
AsciiBase PROC Input:DWORD, Output, Base
      pushad
         mov     esi, Input
         mov     edi, Output
         mov     dword ptr[edi], 0
      INVOKE     lstrlen, Input
         xor     ecx, ecx
      .while (eax)
         .if byte ptr[esi+ecx] > 60h
               sub     byte ptr[esi+ecx], 57h
         .elseif byte ptr[esi+ecx] > 40h
               sub     byte ptr[esi+ecx], 37h
         .else
               xor     byte ptr[esi+ecx], 30h
         .endif
            dec     eax
            inc     ecx
      .endw
         mov     ebx, 1
         mov     esi, Input
         add     esi, ecx
         dec     esi
         xor     edx, edx
      .while (ecx)
            mov     al, byte ptr[esi]            ; Extract byte for conversion
            and     eax, 000000ffh
           imul     eax, ebx
            add     dword ptr[edi], eax          ; Accumulate output
           imul     ebx, Base
            dec     esi
            dec     ecx 
      .endw
       popad
          RET
AsciiBase ENDP

;=========================================================================
;  Converts a 32 bit num value to a Dec, Hex, Oct or Bin ascii string.
;=========================================================================
;INVOKE     BaseAscii, cnt, offset num, 2, 10, 0, 1, 0
BaseAscii PROC InPut:DWORD, OutPut, LEN, Base, Comma, Fill, TermA
LOCAL    LBuff[32]: BYTE

      pushad
         xor     esi, esi
         mov     eax, InPut                ; Input
         mov     ebx, OutPut
         mov     byte ptr [ebx], '0'
      .while (eax)
            xor     edx, edx
            div     Base                   ; Base 10, 16, 8, 2
         .if dl > 9h
               add     dl, 37h             ; Convert to hex ASCII
         .else
               add     dl, 30h             ; Convert to dec ASCII
         .endif
            mov     LBuff[esi], dl
            inc     esi
         .if Comma == 1 && Base == 10 && eax > 0
            .if esi == 3 || esi == 7 || esi == 11
                  mov     LBuff[esi], 2ch  ; Insert commas
                  inc     esi
            .endif
         .endif
      .endw
         xor     edi, edi
         mov     ecx, esi
      .if LEN > ecx && Fill == 1           ; Zero fill
            xor     eax, eax
         .while (eax < LEN)
               mov     byte ptr [ebx+eax], '0'
               inc     eax
         .endw
            sub     LEN, ecx
            add     edi, LEN
      .endif
      .while (ecx)
            mov     al, byte ptr LBuff[esi-1]
            mov     byte ptr [ebx+edi], al
            inc     edi
            dec     esi
            dec     ecx
      .endw
      .if TermA
         mov     byte ptr [ebx+edi], 0h
      .endif
       popad
          RET
BaseAscii ENDP

;=======================================
; Set Font Size
;=======================================
FontSize PROC
LOCAL     tm:TEXTMETRIC

            mov     charF.cbSize, sizeof charF
         INVOKE     GetDC, hWnd
            mov     hDC, eax
         INVOKE     GetDeviceCaps, eax, LOGPIXELSY  ; = 96
            mov     Hold, eax

          MOVmd     charF.yHeight, fSize            ; =  15,  12,  10,   9,   8 pt
            mov     eax, charF.yHeight              ; = 300, 240, 200, 180, 160
            mul     Hold
            mov     ecx, 1440
            div     ecx
            neg     eax                
            mov     lf.lfHeight, eax                ; = -20, -16, -13, -12, -10

         INVOKE     lstrcpy, addr lf.lfFaceName, addr FontName4
            mov     lf.lfWidth, 0
            mov     lf.lfWeight, 600
         INVOKE     CreateFontIndirect, addr lf
            mov     hFont, eax

         INVOKE     SelectObject, hDC, hFont
         INVOKE     GetTextMetrics, hDC, addr tm
         INVOKE     ReleaseDC, hWnd, hDC
            mov     eax, tm.tmAveCharWidth
            dec     eax
            mov     PPC, eax

            mov     al, lf.lfCharSet
            mov     charF.bCharSet, al
            mov     al, lf.lfPitchAndFamily
            mov     charF.bPitchAndFamily, al
         INVOKE     lstrcpy, offset charF.szFaceName, offset FontName4
         RET
FontSize ENDP

;=======================================
; Set Window Sizes
;=======================================
WinSize PROC
LOCAL    rect:RECT

         INVOKE     CreateWindowEx, 0, addr richedit, 0,
                    WS_CHILD or WS_VISIBLE or ES_MULTILINE,
                    0, 30, 150, 20, Hold, 41, hInst, NULL
            mov     Test4, eax
         INVOKE     SendMessage, Test4, WM_SETFONT, hFont, TRUE
         INVOKE     SendMessage, Test4, WM_SETTEXT, NULL, addr szTest
          MOVmd     charF.crTextColor, 00004000h
          MOVmd     charF.crBackColor, 0
            mov     charF.dwMask, CFM_FACE or CFM_SIZE or CFM_COLOR
         INVOKE     SendMessage,  Test4, EM_SETCHARFORMAT, SCF_ALL, offset charF
         INVOKE     GetClientRect, Test4, addr rect
          MOVmd     Hold, rect.right
         INVOKE     SizeEM, Test4, 40, 0, 30, Hold, 20, 0
         INVOKE     GetClientRect, Test4, addr rect
         INVOKE     DestroyWindow, Test4
            mov     w4, 40     ; Number of bytes for default word view

          finit
           fild     w4
          MOVmd     w4, rect.right
           fild     w4
           fdiv     ST(0), ST(1)
            mov     w4, 9
           fild     w4
           fmul     ST(0), ST(1)
          fistp     w1W
           fild     LineCnt
           fmul     ST(0), ST(1)
          fistp     w2W
            mov     w4, 17
           fild     w4
           fmul     ST(0), ST(1)
          fistp     w3W
            mov     w4, 32
           fild     w4
           fmul     ST(0), ST(1)
          fistp     w4W
            add     w4W, 16   ; Scrollbar width
           fstp     PixPC
         RET
WinSize ENDP

;=========================================================================|
;* TabCtlDlg Tab Control  DIALOG BOX PROCEDURE                            |
;=========================================================================|
TabCtlDlg PROC  uses ebx  hdlg:DWORD, wmsg:DWORD, wparam:DWORD, lparam:DWORD
LOCAL    Cnt:DWORD

         cmp     wmsg, WM_INITDIALOG
         jne     NotInit
         and     BytesS, 0
         and     BytesT, 0

      INVOKE     GetDlgItem, hdlg, 702            ; Get the handle of the Tab Control
         mov     hTab, eax                        ; Save it

;----------------- [Fill the Tab Control Item structure and insert the item] --------------------
         mov     tci.imask, TCIF_TEXT             ; Text
         mov     tci.lpReserved1, 0               ; Reserved
         mov     tci.lpReserved2, 0               ; Reserved
         mov     tci.pszText, offset TabTitle1    ; pointer to string containing tab text 
         mov     tci.cchTextMax, sizeof TabTitle1 ; Size of TabTitle1
         mov     tci.iImage, -1                   ; Index to tab control's image 
         mov     tci.lParam, 0                    ; Extra info
      INVOKE     SendMessage, hTab, TCM_INSERTITEM, 0, offset tci

         mov     tci.pszText, offset TabTitle2
         mov     tci.cchTextMax, sizeof TabTitle2
      INVOKE     SendMessage, hTab, TCM_INSERTITEM, 1, addr tci

         mov     tci.pszText, offset TabTitle3
         mov     tci.cchTextMax, sizeof TabTitle3
      INVOKE     SendMessage, hTab, TCM_INSERTITEM, 2, addr tci

         mov     tci.pszText, offset TabTitle4
         mov     tci.cchTextMax, sizeof TabTitle4
      INVOKE     SendMessage, hTab, TCM_INSERTITEM, 3, addr tci

;         mov     tci.pszText, offset TabTitle5
;         mov     tci.cchTextMax, sizeof TabTitle5
;      INVOKE     SendMessage, hTab, TCM_INSERTITEM, 4, addr tci

;----------------- [Load the dialog boxes in the Tab Controls] --------------------
      INVOKE     CreateDialogParam, hInst, 4800, hTab, offset ViewDlg, 0
         mov     hTabSeL1, eax

      INVOKE     CreateDialogParam, hInst, 4801, hTab, offset ColorFontDlg, 0
         mov     hTabSeL2, eax

      INVOKE     CreateDialogParam, hInst, 4802, hTab, offset CompareFiles, 0
         mov     hTabSeL3, eax

      INVOKE     CreateDialogParam, hInst, 4803, hTab, offset ExtractImg, 0
         mov     hTabSeL4, eax

      INVOKE     SendMessage, hTab, TCM_SETCURSEL, TabSelect, 0
         mov     eax, TabSelect                   ; Previous selected Tab
         mov     ebx, hTabSeL+[eax*4]             ; Extract previous Tabs handle
      INVOKE     ShowWindow, ebx, SW_SHOWDEFAULT
         jmp     GetOut

NotInit:
         cmp     wmsg, WM_NOTIFY
         je      wmnotify
         cmp     wmsg, WM_CLOSE
         je      CancelOut
         cmp     wmsg, WM_COMMAND
         jne     GetOut
         mov     eax, wparam
         cmp     eax, IDCANCEL
         je      CancelOut
         jmp     GetOut

wmnotify:
         mov     eax, lparam                      ; lParam is a pointer to a NMHDR Struct
         mov     eax, (NMHDR ptr [eax]).code      ; Check for TCN_SELCHANGE notify message
         cmp     eax, TCN_SELCHANGE
         je      SelectTab
         jmp     GetOut

SelectTab:
         mov     ebx, TabSelect                   ; Previous selected Tab
         mov     eax, hTabSeL+[ebx*4]             ; Extract previous Tabs handle
      INVOKE     ShowWindow, eax, SW_HIDE         ; Hide its window
      INVOKE     SendMessage, hTab, TCM_GETCURSEL, 0, 0  ; New selected Tab
         mov     TabSelect, eax                   ; Save the Tab ID
         mov     ebx, hTabSeL+[eax*4]             ; Extract new Tabs handle
      INVOKE     ShowWindow, ebx, SW_SHOWDEFAULT  ; Show its window
         jmp     GetOut

CancelOut:
;---------- [Clear any open resources] ----------
      .if BytesS
         INVOKE     GlobalUnlock, pMemS
         INVOKE     GlobalFree, hMemS
      .endif
      .if BytesT
         INVOKE     GlobalUnlock, pMemT
         INVOKE     GlobalFree, hMemT
      .endif
      .if pMap
         INVOKE     HeapDestroy, hMemL
         INVOKE     HeapDestroy, hMemI
         INVOKE     HeapDestroy, hMemID
         INVOKE     UnmapViewOfFile, pMap
         INVOKE     CloseHandle, hMap
            and     pMemI, 0
      .endif

;---------- [Close any open dialogs] ----------
         xor     eax, eax
         mov     Cnt, 30
      .while (Cnt)
         .if ImgArray[eax] != 0
               mov     ebx, ImgArray[eax]
               mov     ImgArray[eax], 0
              push     eax
            INVOKE     EndDialog, ebx, wparam
               pop     eax
         .endif
            add     eax, 4
            dec     Cnt
      .endw

      INVOKE     SendMessage, hwndClient, WM_MDIDESTROY, hwndChild1, 0
      INVOKE     SendMessage, hwndClient, WM_MDIDESTROY, hwndChild2, 0
      INVOKE     DestroyWindow, hwndClient
      INVOKE     DestroyWindow, hwndFrame
      INVOKE     EndDialog, hdlg, wparam
         mov     eax, TRUE
         jmp     TabCtlRet

GetOut:
         mov     eax, FALSE

TabCtlRet:
         RET
TabCtlDlg ENDP

;=======================================
; View Dialog
;=======================================
ViewDlg PROC    hdlg:DWORD, wmsg:DWORD, wparam:DWORD, lparam:DWORD
LOCAL     rect:RECT

      .if wmsg == WM_INITDIALOG      ; If message is INITDIALOG then
          MOVmd     hVDlg, hdlg
         .if HexDec == 16
            INVOKE     CheckDlgButton, hdlg, 21, BST_CHECKED
         .elseif HexDec == 10
            INVOKE     CheckDlgButton, hdlg, 22, BST_CHECKED
         .endif
         .if HexView == 2
            INVOKE     CheckDlgButton, hdlg, 31, BST_CHECKED
         .elseif HexView == 4
            INVOKE     CheckDlgButton, hdlg, 32, BST_CHECKED
         .elseif HexView == 8
            INVOKE     CheckDlgButton, hdlg, 33, BST_CHECKED
         .elseif HexView == 16
            INVOKE     CheckDlgButton, hdlg, 34, BST_CHECKED
         .endif
         INVOKE     SetFocus, hTab
            jmp     ViewDone

      .elseif wmsg != WM_COMMAND
            jmp     ViewDone
      .endif

         mov     eax, wparam
        cwde

      .if eax == IDOK
         .if byte ptr szFileName || bytesread > 17
               mov     NoSize, 1
               mov     Refresh, 44
            INVOKE     WriteEM, addr szFileName, 0
               mov     cr.cpMin, 0
               mov     cr.cpMax, 0
              call     EnableDisableMenuTool
         .else
            INVOKE     GetClientRect, hWnd, addr rect
               mov     ebx, rect.right
               mov     ecx, rect.bottom
               sub     ebx, rect.left
               sub     ecx, rect.top
               shl     ecx, 16
               mov     cx, 0
            INVOKE     SendMessage, hWnd, WM_SIZE, SIZE_RESTORED, ecx
         .endif
      .elseif eax == 21
         INVOKE     SendMessage, hwndTool, TB_CHECKBUTTON, 1110, MF_CHECKED or MF_BYCOMMAND
         INVOKE     SendMessage, hwndTool, TB_CHECKBUTTON, 1111, MF_UNCHECKED or MF_BYCOMMAND
         INVOKE     CheckDlgButton, hdlg, 21, BST_CHECKED
         INVOKE     CheckDlgButton, hdlg, 22, BST_UNCHECKED
            mov     HexDec, 16
           call     Renumber
            jmp     ViewDone
      .elseif eax == 22
         INVOKE     SendMessage, hwndTool, TB_CHECKBUTTON, 1111, MF_CHECKED or MF_BYCOMMAND
         INVOKE     SendMessage, hwndTool, TB_CHECKBUTTON, 1110, MF_UNCHECKED or MF_BYCOMMAND
         INVOKE     CheckDlgButton, hdlg, 22, BST_CHECKED
         INVOKE     CheckDlgButton, hdlg, 21, BST_UNCHECKED
            mov     HexDec, 10
           call     Renumber
            jmp     ViewDone
      .endif

      INVOKE     IsDlgButtonChecked, hdlg, 31
         .if eax
               mov     HexView, 2
               mov     LineCnt, 48
         .endif
      INVOKE     IsDlgButtonChecked, hdlg, 32
         .if eax
               mov     HexView, 4
               mov     LineCnt, 40
         .endif
      INVOKE     IsDlgButtonChecked, hdlg, 33
         .if eax
               mov     HexView, 8
               mov     LineCnt, 36
         .endif
      INVOKE     IsDlgButtonChecked, hdlg, 34
         .if eax
               mov     HexView, 16
               mov     LineCnt, 34
         .endif
         jmp     ViewDone

ViewDone:
         mov     eax, FALSE           ;return with FALSE

ViewRet:
         RET
ViewDlg ENDP

;=======================================
; ColorFontDlg Dialog
;=======================================
ColorFontDlg PROC  uses ebx  hdlg:DWORD, wmsg:DWORD, wparam:DWORD, lparam:DWORD
LOCAL    rect:RECT
LOCAL    Val:DWORD, Cnt, Chg

      .if wmsg == WM_INITDIALOG      ; If message is INITDIALOG then
         INVOKE     CreateWindowEx, 0, offset ComboClass, 0,
                    WS_VSCROLL or WS_VISIBLE or WS_CHILD or CBS_HASSTRINGS or\
                    CBS_DROPDOWN,
                    215, 24, 40, 150, hdlg, 83, hInst, 0
            mov     hFSize, eax
      INVOKE     SendMessage, hFSize, WM_SETFONT, hSFont, 1
      INVOKE     SendMessage, hFSize, CB_SETITEMHEIGHT, -1, 14
      INVOKE     SendMessage, hFSize, CB_SETITEMHEIGHT, 0, 13
         mov     esi, offset szSize
         xor     eax, eax
         mov     Cnt, 0
Getlen:
      .if byte ptr[esi+eax] == 2ch
            mov     Cnt, eax
            add     Cnt, 1 
            INVOKE     lstrcpyn, addr szWork, esi, Cnt
            INVOKE     SendMessage, hFSize, CB_ADDSTRING, 0, addr szWork
            add     esi, Cnt
            xor     eax, eax
            jmp     Getlen
      .elseif byte ptr[esi+eax] == 0h
            mov     eax, fSize
            mov     ebx, 20
            xor     edx, edx
            div     ebx
         INVOKE     BaseAscii, eax, addr szWork, 0, 10, 0, 0, 1
         INVOKE     SendMessage, hFSize, CB_SELECTSTRING, -1, addr szWork
            jmp     ColorFontRet
      .endif
         inc     eax
         jmp     Getlen
            jmp     ColorFontRet
      .endif

         cmp     wmsg, WM_COMMAND
         jne     ColorFontRet
      INVOKE     SendMessage, hREdit, EM_GETMODIFY, 0, 0
         mov     Chg, eax
         and     Val, 0
         mov     eax, wparam

      .if eax == 84               ; Apply font size
         INVOKE     SendMessage, hREdit, EM_GETMODIFY, 0, 0
            mov     Chg, eax
            mov     SizeWork, 1
         INVOKE     SendMessage, hFSize, CB_GETDROPPEDSTATE, 0, 0
         INVOKE     SendMessage, hFSize, CB_GETCURSEL, 0, 0
         INVOKE     SendMessage, hFSize, CB_GETLBTEXT, eax, addr szBuff
            mov     Hold, 0
         INVOKE     AsciiBase, addr szBuff, addr Hold, 10  ; PointSize
            mov     eax, Hold
           imul     eax, 20
            mov     fSize, eax
           call     FontSize
           call     ScreenLines
          MOVmd     Hold, hWnd
           call     WinSize
            mov     NoSize, 1
            mov     charF.dwMask, CFM_SIZE
         INVOKE     SendMessage,  hSplit1, EM_SETCHARFORMAT, SCF_ALL, offset charF
         INVOKE     SendMessage,  hREdit, EM_SETCHARFORMAT, SCF_ALL, offset charF
         INVOKE     SendMessage,  hSplit3, EM_SETCHARFORMAT, SCF_ALL, offset charF
         INVOKE     SendMessage,  hWorkC, EM_SETCHARFORMAT, SCF_ALL, offset charF
         INVOKE     SendMessage,  hWorkN, EM_SETCHARFORMAT, SCF_ALL, offset charF

         INVOKE     GetClientRect, hSplit1, addr rect
          MOVmd     w4, rect.bottom
         INVOKE     GetWindowRect, hWorkC, addr rect
            mov     eax, PPC
           imul     eax, 32
            mov     Hold, eax
         INVOKE     MoveWindow, hWorkC, rect.left, rect.top, w4W, w4, TRUE
         INVOKE     MoveWindow, hWorkN, rect.left, rect.top, w4W, w4, TRUE

         INVOKE     GetClientRect, hSplit1, addr rect
         INVOKE     MoveWindow, hSplit1, 0, 28, w1W, rect.bottom, TRUE
            mov     eax, w1W
            inc     eax
           push     eax
         INVOKE     MoveWindow, hREdit, eax, 28, w2W, rect.bottom, TRUE
            pop     eax
            add     eax, w2W
            inc     eax
           push     eax
         INVOKE     MoveWindow, hSplit3, eax, 28, w3W, rect.bottom, TRUE
            pop     eax
            add     eax, 26
            mov     w4, eax
         INVOKE     MoveWindow, hWnd, WxPos, WyPos, w4, Wht, TRUE
            jmp     ColorFontDone
      .endif

      .if eax > 40 && eax < 47 ;Color buttons
            mov     ebx, eax
            sub     ebx, 41
            mov     Val, ebx
         INVOKE     SendMessage, hREdit, EM_GETMODIFY, 0, 0
            mov     Chg, eax
            jmp     ColorBT
      .endif
         jmp     ColorFontDone

ColorBT:
         mov     ecx, Val
        imul     ecx, 4
       MOVmd     cc.rgbResult, c1T[ecx]
         mov     cc.lStructSize, sizeof cc
       MOVmd     cc.hwndOwner, hWnd
       MOVmd     cc.hInstance, hInst
         mov     cc.lpCustColors, offset CustClrs
         mov     cc.Flags, CC_FULLOPEN or CC_RGBINIT          
      INVOKE     ChooseColor, addr cc
         cmp     eax, FALSE         ;Cancel'ed or error occurred
          je     ColorFontDone
         mov     ecx, Val
        imul     ecx, 4
       MOVmd     c1T[ecx], cc.rgbResult
         mov     charF.dwMask, CFM_FACE or CFM_SIZE or CFM_COLOR
      INVOKE     SendMessage, hSplit1, EM_SETBKGNDCOLOR, 0, c1B
       MOVmd     charF.crTextColor, c1T
       MOVmd     charF.crBackColor, 0
      INVOKE     SendMessage, hSplit1, EM_SETCHARFORMAT, SCF_ALL, offset charF
      INVOKE     SendMessage, hREdit, EM_SETBKGNDCOLOR, 0, c2B
       MOVmd     charF.crTextColor, c2T
       MOVmd     charF.crBackColor, 0
      INVOKE     SendMessage,  hREdit, EM_SETCHARFORMAT, SCF_ALL, offset charF
      INVOKE     SendMessage, hSplit3, EM_SETBKGNDCOLOR, 0, c3B
       MOVmd     charF.crTextColor, c3T
       MOVmd     charF.crBackColor, 0
      INVOKE     SendMessage, hSplit3, EM_SETCHARFORMAT, SCF_ALL, offset charF

ColorFontDone:
      INVOKE     SendMessage, hREdit, EM_SETMODIFY, Chg, 0
      INVOKE     SendMessage, hREdit, EM_EMPTYUNDOBUFFER, 0, 0
      INVOKE     SendMessage, hWorkC, EM_EMPTYUNDOBUFFER, 0, 0
      INVOKE     SendMessage, hWorkN, EM_EMPTYUNDOBUFFER, 0, 0

ColorFontRet:
         mov     eax, FALSE           ;return with FALSE

         RET
ColorFontDlg ENDP

;=======================================
; CompareFiles Dialog
;=======================================
CompareFiles PROC  uses ebx edx esi edi  hdlg:DWORD, wmsg:DWORD, wparam:DWORD, lparam:DWORD
LOCAL     rect:RECT
LOCAL     ccs:CLIENTCREATESTRUCT
LOCAL     BytesC:DWORD, Base, Val, OffS, OffT, OffEdit1, OffEdit2

      .if wmsg == WM_INITDIALOG      ; If message is INITDIALOG then
            and     BytesC, 0
            and     BytesS, 0
            and     BytesT, 0

         INVOKE     GetDlgItem, hdlg, 43
         INVOKE     SendMessage, eax, EM_LIMITTEXT, 8, 0 ; Limit text size
         INVOKE     GetDlgItem, hdlg, 44
         INVOKE     SendMessage, eax, EM_LIMITTEXT, 8, 0 ; Limit text size
         INVOKE     GetDlgItem, hdlg, 45
         INVOKE     SendMessage, eax, EM_LIMITTEXT, 8, 0 ; Limit text size

         INVOKE     CheckDlgButton, hdlg, 31, BST_CHECKED

         INVOKE     SetFocus, hTab
            jmp     CompareFilesDone

      .elseif wmsg != WM_COMMAND
            jmp     CompareFilesDone
      .endif

         mov     eax, wparam
        cwde

      .if eax == 30

      .elseif eax == 31
         INVOKE     SwapHexDec, hdlg, 43, 10, 16
         INVOKE     SwapHexDec, hdlg, 44, 10, 16
         INVOKE     SwapHexDec, hdlg, 45, 10, 16
         INVOKE     SwapHexDec, hdlg, 46, 10, 16
         INVOKE     SwapHexDec, hdlg, 47, 10, 16

      .elseif eax == 32
         INVOKE     SwapHexDec, hdlg, 43, 16, 10
         INVOKE     SwapHexDec, hdlg, 44, 16, 10
         INVOKE     SwapHexDec, hdlg, 45, 16, 10
         INVOKE     SwapHexDec, hdlg, 46, 16, 10
         INVOKE     SwapHexDec, hdlg, 47, 16, 10

      .elseif eax == 81
            jmp     GetFile
      .elseif eax == 82
            jmp     GetFile
      .elseif eax == 83
         INVOKE     SetFocus, hTab
    INVOKE     DestroyWindow, hwndFrame
    INVOKE     LoadMenu, hInst, 602
       mov     hFrameMenu, eax
            jmp     DoIt
      .endif
         jmp     CompareFilesDone

GetFile:
         mov     szBuff, 0
         mov     ofn.lStructSize, sizeof ofn
       MOVmd     ofn.hwndOwner, hREdit
       MOVmd     ofn.hInstance, hInst
         mov     ofn.lpstrFilter, offset szFilter
         mov     ofn.lpstrFile, offset szBuff
         mov     ofn.nMaxFile, sizeof szBuff
         mov     ofn.lpstrTitle, offset szTitleO
         mov     ofn.Flags, OFN_EXPLORER or OFN_PATHMUSTEXIST or OFN_FILEMUSTEXIST or OFN_HIDEREADONLY
      INVOKE     GetOpenFileName, addr ofn
         cmp     eax, FALSE           ; Cancel'ed or error occurred
          je     CompareFilesDone

      INVOKE     CreateFile, addr szBuff,\
                 GENERIC_READ, FILE_SHARE_READ,\
                 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0

      .if eax == -1
         INVOKE     MessageBox, hWnd, addr szAccess, addr szDisplayName, MB_OK
            jmp     CompareFilesDone
      .endif
         mov     hFile, eax

      INVOKE     GlobalAlloc, GMEM_MOVEABLE or GMEM_ZEROINIT, MemSize
         mov     hMem, eax
      INVOKE     GlobalLock, hMem
         mov     pMem, eax
      INVOKE     ReadFile, hFile, pMem, MemSize-1, addr BytesC, NULL

      .if wparam == 81             ; Source browse button
          MOVmd     hMemS, hMem
          MOVmd     pMemS, pMem
          MOVmd     BytesS, BytesC
         INVOKE     SetDlgItemText, hdlg, 41, addr szBuff
         INVOKE     BaseAscii, BytesC, addr szWork, 1, 16, 0, 1, 1
         INVOKE     SetDlgItemText, hdlg, 46, addr szWork
         INVOKE     CloseHandle, hFile
      .else                        ; Target browse button
          MOVmd     hMemT, hMem
          MOVmd     pMemT, pMem
          MOVmd     BytesT, BytesC
         INVOKE     SetDlgItemText, hdlg, 42, addr szBuff
         INVOKE     BaseAscii, BytesC, addr szWork, 1, 16, 0, 1, 1
         INVOKE     SetDlgItemText, hdlg, 47, addr szWork
         INVOKE     CloseHandle, hFile
      .endif
         jmp     CompareFilesDone

DoIt:
      INVOKE     IsDlgButtonChecked, hdlg, 31 ; Hex
      .if eax
            mov     Base, 16
      .else
            mov     Base, 10
      .endif
      INVOKE     ValHexDec, hdlg, 44, Base, 10
         cmp     eax, 1
          je     NoComp
      INVOKE     AsciiBase, addr szWork, addr OffS, Base
      INVOKE     ValHexDec, hdlg, 45, Base, 10
         cmp     eax, 1
          je     NoComp
      INVOKE     AsciiBase, addr szWork, addr OffT, Base
         mov     ebx, BytesS
         sub     ebx, OffS
         mov     edx, BytesT
         sub     edx, OffT

      .if BytesS == 0 || BytesT == 0
            jmp     NoComp
      .endif
         mov     eax, BytesS
      .if ebx > edx
            mov     Len, edx
      .else
            mov     Len, ebx
      .endif
      INVOKE     IsDlgButtonChecked, hdlg, 30 ; All
      .if eax
         INVOKE     BaseAscii, Len, addr szWork, 1, Base, 0, 1, 1
         INVOKE     SetDlgItemText, hdlg, 43, addr szWork
      .endif
      INVOKE     ValHexDec, hdlg, 43, Base, 10
         cmp     eax, 1
          je     NoComp
      INVOKE     AsciiBase, addr szWork, addr Val, Base
         mov     eax, Val
      .if Len > eax
            mov     Len, eax
      .endif
      INVOKE     BaseAscii, Len, addr szWork, 1, Base, 0, 1, 1
      INVOKE     SetDlgItemText, hdlg, 43, addr szWork

         xor     esi, esi
         xor     edi, edi
         mov     ebx, pMemS
         mov     edx, pMemT
         add     esi, OffS
         add     edi, OffT
      .while (Len)
            mov     al, byte ptr [ebx+esi]
         .if al == byte ptr [edx+edi]
               inc     esi
               inc     edi
               dec     Len
         .else
            .break
         .endif
      .endw

      .if Len
            xor     eax, eax
            mov     ecx, 12
         .while (ecx)
               mov     byte ptr szSource[eax], ' '
               inc     eax
               dec     ecx
         .endw
            mov     OffEdit1, esi
            mov     OffEdit2, edi
         INVOKE     BaseAscii, esi, addr szSource, 1, Base, 0, 1, 0
         INVOKE     BaseAscii, edi, addr szTarget, 1, Base, 0, 1, 1
         INVOKE     MessageBox, hWnd, addr szError5, addr szDisplayName, MB_OK

         INVOKE     CreateWindowEx, WS_EX_TOPMOST, addr MDIFrameClass, addr szCompFiles,\
                    WS_POPUPWINDOW or WS_CAPTION or WS_THICKFRAME or WS_CLIPCHILDREN,\
                    100, 100, 570, 300, hWnd, 0, hInst, 0
            mov     hwndFrame, eax
         .if !eax
            INVOKE     MessageBox, hWnd, addr szError9, addr szDisplayName, MB_OK
         .endif
         INVOKE     ShowWindow, hwndFrame, SW_SHOWNORMAL
         INVOKE     UpdateWindow, hwndFrame

; or MDIS_ALLCHILDSTYLES
         INVOKE     GetSubMenu, hFrameMenu, 2 ;1
            mov     ccs.hWindowMenu, eax
            mov     ccs.idFirstChild, 100
         INVOKE     CreateWindowEx, NULL, addr MDIClientClass, NULL,\
                    WS_CHILD or WS_VISIBLE or WS_CLIPCHILDREN,\
                    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,\
                    hwndFrame, NULL, hInst, addr ccs
            mov     hwndClient, eax

;---------- [Initialize the MDICREATESTRUCT] ----------
;         INVOKE     GetDlgItemText, hdlg, 41, addr szBuff, sizeof szBuff
;            mov     mdicreate.szClass, offset MDIChildClass
;            mov     mdicreate.szTitle, offset szBuff ;MDIChildClass
;           Push     hInst
;            pop     mdicreate.hOwner
;            mov     mdicreate.x, CW_USEDEFAULT
;            mov     mdicreate.y, CW_USEDEFAULT
;            mov     mdicreate.lx, 200 ;CW_USEDEFAULT
;            mov     mdicreate.ly, 100 ;CW_USEDEFAULT
;            mov     mdicreate.style, 0 ;WS_HSCROLL or WS_VSCROLL 
;            mov     mdicreate.lParam, 0
;         INVOKE     SendMessage, hwndClient ,WM_MDICREATE, 0, addr mdicreate
;            mov     hwndChild1, eax
;         INVOKE     GetDlgItemText, hdlg, 42, addr szBuff, sizeof szBuff
;            mov     mdicreate.szTitle, offset szBuff
;         INVOKE     SendMessage, hwndClient ,WM_MDICREATE, 0, addr mdicreate
;            mov     hwndChild2, eax

         INVOKE     GetDlgItemText, hdlg, 41, addr szBuff, sizeof szBuff
         INVOKE     CreateMDIWindow, offset MDIChildClass, offset szBuff, 0,\
                    CW_USEDEFAULT, CW_USEDEFAULT, 200, 100, hwndClient, hInst, NULL
            mov     hwndChild1, eax
         INVOKE     GetDlgItemText, hdlg, 42, addr szBuff, sizeof szBuff
         INVOKE     CreateMDIWindow, offset MDIChildClass, offset szBuff, 0,\
                    CW_USEDEFAULT, CW_USEDEFAULT, 200, 100, hwndClient, hInst, NULL
            mov     hwndChild2, eax

         INVOKE     CreateWindowEx, 0, addr richedit, 0,\
                    WS_CHILD or WS_VISIBLE or WS_HSCROLL or WS_VSCROLL or ES_MULTILINE or\
                    ES_READONLY or ES_NOHIDESEL, CW_USEDEFAULT, CW_USEDEFAULT, 200, 100,\
                    hwndChild1, 97, hInst, NULL
            mov     hEdit1, eax
         INVOKE     CreateWindowEx, 0, addr richedit, 0,\
                    WS_CHILD or WS_VISIBLE or WS_HSCROLL or WS_VSCROLL or ES_MULTILINE or\
                    ES_READONLY or ES_NOHIDESEL, CW_USEDEFAULT, CW_USEDEFAULT, 200, 100,\
                    hwndChild2, 98, hInst, NULL
            mov     hEdit2, eax
         INVOKE     SendMessage, hEdit1, EM_LIMITTEXT, 2000000, 0
         INVOKE     SendMessage, hEdit1, WM_SETFONT, hFont, TRUE
         INVOKE     SendMessage, hEdit2, EM_LIMITTEXT, 2000000, 0
         INVOKE     SendMessage, hEdit2, WM_SETFONT, hFont, TRUE

         INVOKE     SetFocus, hwndChild1
         INVOKE     SendMessage, hwndClient, WM_MDITILE, MDITILE_HORIZONTAL, 0
         INVOKE     GetClientRect, hwndChild1, addr rect
         INVOKE     MoveWindow, hEdit1, rect.left, rect.top, rect.right, rect.bottom, TRUE
         INVOKE     MoveWindow, hEdit2, rect.left, rect.top, rect.right, rect.bottom, TRUE
         INVOKE     FillEdit, hEdit1, pMemS, BytesS, Base, OffEdit1
         INVOKE     FillEdit, hEdit2, pMemT, BytesT, Base, OffEdit2
      .else
         INVOKE     MessageBox, hWnd, addr szError6, addr szDisplayName, MB_OK
      .endif

NoComp:

CompareFilesDone:
         xor     eax, eax           ; Return with FALSE

CompareFilesRet:

         RET
CompareFiles ENDP

;=======================================
; Extract Images Dialog
;=======================================
ExtractImg PROC  uses ebx edx esi edi  hdlg:DWORD, wmsg, wparam, lparam
LOCAL    ici:ICONINFO
LOCAL    VirAddr:DWORD, PTRData, TypePE, Diff, BytesO, NumIds1, NumIds2
LOCAL    MemPos:DWORD, OffPosS, OffPosID, RsrcID, Cnt, CntID, hTemp, pTemp, sw, w1
LOCAL    szWorkS[20]:BYTE

      .if wmsg == WM_INITDIALOG      ; If message is INITDIALOG then
         INVOKE     GetDlgItem, hdlg, 401
            mov     hCur, eax
         INVOKE     GetDlgItem, hdlg, 402
            mov     hBmp, eax
         INVOKE     GetDlgItem, hdlg, 403
            mov     hIco, eax
and     Test4, 0
      .endif

      .if wmsg != WM_COMMAND
            jmp     ExtractImgDone
      .endif

         mov     eax, wparam
        cwde

      .if eax == 401
         INVOKE     SendMessage, hBmp, LB_SETCURSEL, -1, 0
         INVOKE     SendMessage, hIco, LB_SETCURSEL, -1, 0
            jmp     ExtractImgDone
      .endif
      .if eax == 402
         INVOKE     SendMessage, hCur, LB_SETCURSEL, -1, 0
         INVOKE     SendMessage, hIco, LB_SETCURSEL, -1, 0
            jmp     ExtractImgDone
      .endif
      .if eax == 403
         INVOKE     SendMessage, hCur, LB_SETCURSEL, -1, 0
         INVOKE     SendMessage, hBmp, LB_SETCURSEL, -1, 0
            jmp     ExtractImgDone
      .endif

      .if eax == 82
            jmp     Dsplay
      .endif

      .if eax != 81
            jmp     ExtractImgDone
      .endif

         and     TypePE, 0
;         and     pMap, 0
         and     NumOfIDs, 0
         and     NumOfMatchIDs, 0
         mov     szBuff, 0
         mov     ofn.lStructSize, sizeof OPENFILENAME
       MOVmd     ofn.hwndOwner, hREdit
       MOVmd     ofn.hInstance, hInst
         mov     ofn.lpstrFilter, offset szPE
         mov     ofn.lpstrFile, offset szBuff
         mov     ofn.nMaxFile, sizeof szBuff
         mov     ofn.lpstrTitle, offset szTitleO
         mov     ofn.Flags, OFN_EXPLORER or OFN_PATHMUSTEXIST or OFN_FILEMUSTEXIST or OFN_HIDEREADONLY
      INVOKE     GetOpenFileName, addr ofn
         cmp     eax, FALSE           ; Cancel'ed or error occurred
          je     ExtractImgDone

      .if pMap
         INVOKE     HeapDestroy, hMemL
         INVOKE     HeapDestroy, hMemI
         INVOKE     HeapDestroy, hMemID
         INVOKE     UnmapViewOfFile, pMap
         INVOKE     CloseHandle, hMap
      .endif

      INVOKE     CreateFile, addr szBuff,\
                 GENERIC_READ, FILE_SHARE_READ,\
                 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0

      .if eax == -1
         INVOKE     MessageBox, hWnd, addr szAccess, addr szDisplayName, MB_OK
            jmp     ExtractImgDone
      .endif
         mov     hFile, eax

      INVOKE     CreateFileMapping, hFile, NULL, PAGE_READONLY, 0, 0, 0
         cmp     eax, FALSE           ; Error occurred
          je     ExtractImgDone
         mov     hMap, eax
      INVOKE     MapViewOfFile, hMap, FILE_MAP_READ, 0, 0, 0
         cmp     eax, FALSE           ; Error occurred
          je     ExtractImgDone
         mov     pMap, eax

;---------- [Clear the list boxes and close any open dialogs] ----------
      INVOKE     SendMessage, hCur, LB_RESETCONTENT, 0, 0
      INVOKE     SendMessage, hBmp, LB_RESETCONTENT, 0, 0
      INVOKE     SendMessage, hIco, LB_RESETCONTENT, 0, 0
      INVOKE     CloseHandle, hFile

         xor     eax, eax
         mov     Cnt, 30
      .while (Cnt)
         .if ImgArray[eax] != 0
               mov     ebx, ImgArray[eax]
               mov     ImgArray[eax], 0
              push     eax
            INVOKE     EndDialog, ebx, wparam
               pop     eax
         .endif
            add     eax, 4
            dec     Cnt
      .endw 

;---------- [List box array] ----------
         mov     BytesO, 10000
      INVOKE     HeapCreate, HEAP_GENERATE_EXCEPTIONS, BytesO, 0
         mov     hMemL, eax
      INVOKE     HeapAlloc, hMemL, HEAP_GENERATE_EXCEPTIONS, BytesO
         mov     pMemL, eax

;---------- [Group ID array] ----------
         mov     BytesO, 10000
      INVOKE     HeapCreate, HEAP_GENERATE_EXCEPTIONS, BytesO, 0
         mov     hMemID, eax
      INVOKE     HeapAlloc, hMemID, HEAP_GENERATE_EXCEPTIONS, BytesO
         mov     pMemID, eax

;---------- [Check for PE type file] ----------
      INVOKE     GetFileSize, hFile, 0
      .if eax < 3ch
            jmp     NoRsrc
      .endif
         mov     ebx, pMap
         mov     ax, word ptr [ebx]
      .if ax == 'ZM'                                         ; IMAGE_DOS_SIGNATURE  -DOS MZ header-
            mov     edx, 3ch
            xor     eax, eax
            mov     al, byte ptr [ebx+edx]
            add     ebx, eax
            mov     eax, dword ptr [ebx]
         .if eax == 00004550h                                ; IMAGE_NT_SIGNATURE   -PE header-
               mov     TypePE, 1
         .endif
      .endif
         cmp     TypePE, 0
          je     NoRsrc

         and     w4, 0
         mov     edi, pMap
      assume edi:ptr IMAGE_DOS_HEADER
         add     edi, [edi].e_lfanew
      assume edi:ptr IMAGE_NT_HEADERS
         mov     ax, [edi].FileHeader.NumberOfSections
         mov     NumOfSections, ax
         add     edi, sizeof IMAGE_NT_HEADERS
         mov     esi, edi
         mov     ax, NumOfSections
       movzx     eax, ax
         mov     edi, eax
      assume esi:ptr IMAGE_SECTION_HEADER
      .while edi > 0
         INVOKE     lstrcpyn, addr szWorkS, addr [esi].Name1, 8
         .if dword ptr szWorkS+1 == 'crsr'                   ; Resource header
               mov     w4, esi
             MOVmd     VirAddr, [esi].VirtualAddress
             MOVmd     PTRData, [esi].PointerToRawData
               mov     eax, VirAddr
               sub     eax, PTRData
               mov     Diff, eax
            .break
         .endif
            dec     edi
            add     esi, sizeof IMAGE_SECTION_HEADER
      .endw

      .if !w4
            jmp     NoRsrc
      .endif
         and     Lnum, 0
         and     OffPosS, 0
         and     OffPosID, 0
         mov     esi, pMap
         add     esi, PTRData

;---------- [In Resource Directory (Type)] ----------
      assume esi:ptr IMAGE_RESOURCE_DIRECTORY                ; Resource Directory (Type)
            xor     eax, eax
            mov     ax, [esi].NumberOfIdEntries
            mov     NumIds1, eax                             ; Total num of ID entries
            and     SavPos, 0
            xor     eax, eax
      .while (NumIds1)                                       ; In Resource Directory (Type)
            mov     eax, SavPos
            add     eax, 10h
            mov     SavPos, eax
            sub     SavPos, 8

;---------- [Check for Cursor, Icon, or Bitmap ID  1-2-3] ----------
         .if dword ptr [esi+eax] > 0h && dword ptr [esi+eax] < 4h ||\
             dword ptr [esi+eax] == 0ch || dword ptr [esi+eax] == 0eh
             MOVmd     ID, dword ptr [esi+eax]               ; Save the ID
               add     eax, 4
               mov     ebx, dword ptr [esi+eax]              ; Offset to Resource Directory (Name ID)
               and     ebx, 0000ffffh
               add     ebx, 0eh                              ; Offset to Total num of ID's for group
               xor     ecx, ecx
               mov     cx, word ptr [esi+ebx]
               mov     NumIds2, ecx                          ; Total num of ID's for group
            .if !ecx
                  mov     cx, word ptr [esi+ebx-2]
                  mov     NumIds2, ecx                       ; Total num of named ID's for group  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            .endif
               sub     ebx, 2

;---------- [In Resource Directory (Name ID)] ----------
            .while (NumIds2)                                 ; In Resource Directory (Name ID)
                  add     ebx, 8
                MOVmd     RsrcID, dword ptr [esi+ebx-4]      ; Save the resource or matching ID
                  mov     edx, dword ptr [esi+ebx]           ; Offset to Directory (Language)
                  and     edx, 0000ffffh
                  add     edx, 14h
                  mov     edi, esi
                  mov     ecx, dword ptr [edi+edx]           ; Offset to Directory (Data Entry)
                  mov     edx, ecx
                  mov     ecx, dword ptr [edi+edx]           ; Virtual address of resource
                  sub     ecx, Diff                          ; Actual address of resource in the file

;---------- [Build an array of IDs - ID, actual offset, and size minus header] ---------- 
                 push     esi
               .if ID > 3
                     mov     esi, pMemID
                     mov     eax, OffPosID
               .else
                     mov     esi, pMemL
                     mov     eax, OffPosS
               .endif

                MOVmd     dword ptr [esi+eax], ID
                  mov     dword ptr [esi+eax+4], ecx         ; Actual address in the resource
                MOVmd     dword ptr [esi+eax+8], dword ptr [edi+edx+4]  ; Size of image or group
                MOVmd     dword ptr [esi+eax+12], RsrcID     ; Resource or matching ID for detail and group
                MOVmd     dword ptr [esi+eax+16], RsrcID     ; Resource or matching ID for detail and group
                  mov     dword ptr [esi+eax+20], 0
                  mov     dword ptr [esi+eax+24], 0

;---------- [Modify the ID array] ----------
               .if ID > 3
                   MOVmd     Hold, dword ptr [edi+edx+4]     ; Group size
                     xor     edx, edx
                     mov     edi, pMap
                     mov     dword ptr [esi+eax+16], 0
                     mov     dl, byte ptr [edi+ecx+18]
                     mov     byte ptr [esi+eax+16], dl       ; Matching ID for detail and group
                     mov     dword ptr [esi+eax+20], 0
                     mov     dword ptr [esi+eax+24], 0
                     mov     dword ptr [esi+eax+28], 0

                  .if Hold > 20
                        sub     Hold, 20
                        add     ecx, 20
                        add     eax, 16
                     .while (Hold)
                        inc     eax
                        add     ecx, 14
                        xor     edx, edx
                        mov     dl, byte ptr [edi+ecx-2]
                        mov     byte ptr [esi+eax], dl       ; Matching ID for detail and group
                        sub     Hold, 14
                     .endw
                  .endif
                     add     OffPosID, 32                    ; Length of ID array
                     add     NumOfMatchIDs, 1
               .else
                     add     OffPosS, 32                     ; Length of List array
                     add     NumOfIDs, 1
               .endif

                  pop     esi
                  dec     NumIds2
            .endw
         .endif
            dec     NumIds1
      .endw

;---------- [Copy the resource IDs to the list box array] ----------
       MOVmd     Cnt, NumOfIDs
         and     OffPosS, 0
         mov     esi, pMemL
      .while (Cnt)
            mov     eax, OffPosS
         .if dword ptr [esi+eax] != 2                        ; Bitnap IDs
               mov     cl, byte ptr [esi+eax+16]             ; Match ID
             MOVmd     CntID, NumOfMatchIDs
               and     OffPosID, 0
               mov     edi, pMemID
            .while (CntID)
                  mov     ebx, OffPosID
                  add     ebx, 16
                  mov     edx, 16
               .while (edx)
                  .if byte ptr [edi+ebx] == cl
                        mov     ebx, OffPosID
                       push     eax
                        mov     eax, dword ptr [edi+ebx+12]
                        and     eax, 0000ffffh                                 ; In case a named ID
                        mov     dword ptr [edi+ebx+12], eax
                        pop     eax
                      MOVmd     dword ptr [esi+eax+12], dword ptr [edi+ebx+12] ; Resource ID
                      MOVmd     dword ptr [esi+eax+20], dword ptr [edi+ebx+4]  ; Offset to group
                      MOVmd     dword ptr [esi+eax+24], dword ptr [edi+ebx+8]  ; Size of group
                        jmp     GotOne
                  .endif
                     inc     ebx
                     dec     edx
               .endw
                  dec     CntID
                  add     OffPosID, 32
            .endw
GotOne:
         .endif
            dec     Cnt
            add     OffPosS, 32
      .endw

;---------- [Build a record for combined images] ----------
      INVOKE     HeapCreate, HEAP_GENERATE_EXCEPTIONS, 10000, 0
         mov     hTemp, eax
      INVOKE     HeapAlloc, hTemp, HEAP_GENERATE_EXCEPTIONS, 10000
         mov     pTemp, eax
         mov     esi, pMemL
         mov     edi, pTemp
         mov     ecx, NumOfIDs
        imul     ecx, 8
      .while (ecx)
            mov     eax, dword ptr [esi]
            mov     dword ptr [edi], eax
            add     esi, 4
            add     edi, 4
            dec     ecx
      .endw

         mov     esi, pTemp
         mov     edi, pMemL
         mov     ebx, NumOfIDs
      .while (ebx)
         .if dword ptr [esi] == 1 || dword ptr [esi] == 3
               mov     edx, dword ptr [esi+12]
            .if dword ptr [esi+24] > 20 && edx != sw
                MOVmd     sw, dword ptr [esi+12]
                  mov     ecx, 8
               .while (ecx)
                     mov     eax, dword ptr [esi]
                     mov     dword ptr [edi], eax
                     add     esi, 4
                     add     edi, 4
                     dec     ecx
               .endw
                  mov     dword ptr [edi-4], 44
                  mov     dword ptr [edi-16], 0FFFF0000h
                  sub     esi, 32
                  inc     NumOfIDs
            .endif
         .endif

            mov     ecx, 8
         .while (ecx)
               mov     eax, dword ptr [esi]
               mov     dword ptr [edi], eax
               add     esi, 4
               add     edi, 4
               dec     ecx
         .endw
            dec     ebx
      .endw

      INVOKE     HeapDestroy, hTemp

;---------- [Fill the list boxes] ----------
      INVOKE     SendMessage, hCur, LB_RESETCONTENT, 0, 0
      INVOKE     SendMessage, hBmp, LB_RESETCONTENT, 0, 0
      INVOKE     SendMessage, hIco, LB_RESETCONTENT, 0, 0
       MOVmd     Cnt, NumOfIDs
         and     OffPosS, 0
         mov     esi, pMemL
      .while (Cnt)
            add     Lnum, 1
         INVOKE     BaseAscii, Lnum, addr szWorkS, 2, 10, 0, 1, 1
         INVOKE     lstrcpy, addr szWork, addr szWorkS
         INVOKE     lstrcat, addr szWork, addr szSpace

            mov     esi, pMemL
            mov     eax, OffPosS
          MOVmd     ID, dword ptr [esi+eax]
            mov     ecx, dword ptr [esi+eax+12]              ; Resource ID
            mov     edx, dword ptr [esi+eax+16]              ; Multible ID
         .if dword ptr [esi+eax+24] == 20 || ID == 2         ; If 20 not mult image or bmp
               xor     edx, edx
         .endif
           push     edx
         INVOKE     BaseAscii, ecx, addr szWorkS, 1, 10, 0, 1, 1
         INVOKE     lstrcat, addr szWork, addr szWorkS
         INVOKE     lstrcat, addr szWork, addr szSpace
            pop     edx
         .if edx == 0ffff0000h                               ; Combined images
            INVOKE     lstrcat, addr szWork, addr szComb
         .else
            INVOKE     BaseAscii, edx, addr szWorkS, 0, 16, 0, 0, 1
            INVOKE     lstrcat, addr szWork, addr szWorkS
         .endif
         INVOKE     lstrcat, addr szWork, addr szSpace
         .if ID == 1 ;|| ID == 0ch
            INVOKE     SendMessage, hCur, LB_ADDSTRING, 0, addr szWork
         .elseif ID == 2
            INVOKE     SendMessage, hBmp, LB_ADDSTRING, 0, addr szWork
         .elseif ID == 3 ;|| ID == 0eh
            INVOKE     SendMessage, hIco, LB_ADDSTRING, 0, addr szWork
         .endif
            add     OffPosS, 32 ;20
            dec     Cnt
      .endw
         jmp     ExtractImgDone

Dsplay:
         and     ID, 0
      INVOKE     SendMessage, hCur, LB_GETCURSEL, 0, 0
      .if eax != LB_ERR
         INVOKE     SendMessage, hCur, LB_GETTEXT, eax, addr szWork
            mov     ID, 1
         INVOKE     SetFocus, hCur
      .endif
      INVOKE     SendMessage, hBmp, LB_GETCURSEL, 0, 0
      .if eax != LB_ERR
         INVOKE     SendMessage, hBmp, LB_GETTEXT, eax, addr szWork
            mov     ID, 2
         INVOKE     SetFocus, hBmp
      .endif
      INVOKE     SendMessage, hIco, LB_GETCURSEL, 0, 0
      .if eax != LB_ERR
            mov     sw1, eax
         INVOKE     SendMessage, hIco, LB_GETTEXT, eax, addr szWork
            mov     ID, 3
         INVOKE     SetFocus, hIco
      .endif
      .if !ID
            jmp     ExtractImgDone
      .endif

;---------- [Image files] ----------
         mov     BytesO, 250000
      INVOKE     HeapCreate, HEAP_GENERATE_EXCEPTIONS, BytesO, 0
         mov     hMemI, eax
      INVOKE     HeapAlloc, hMemI, HEAP_GENERATE_EXCEPTIONS, BytesO
         mov     pMemI, eax

      INVOKE     lstrcpyn, addr szWorkS, addr szWork, 3
      INVOKE     AsciiBase, addr szWorkS, addr Cnt, 10
         dec     Cnt
         mov     eax, Cnt
         mov     SavStart, eax
         inc     SavStart
        imul     eax, 32

         mov     Hold, eax
         mov     w1, eax
         mov     Cnt, 8
      .while (Cnt)
            mov     esi, pMemL
            mov     eax, w1
            mov     ebx, dword ptr [esi+eax]
         INVOKE     BaseAscii, ebx, addr szWorkS, 8, 16, 0, 1, 1
            mov     eax, w1
         .if eax == Hold
            INVOKE     lstrcpy, addr szImage, addr szWorkS
         .else
            INVOKE     lstrcat, addr szImage, addr szWorkS
         .endif
            add     w1, 4
            dec     Cnt
      .endw
      INVOKE     BaseAscii, SavStart, addr szWorkS, 8, 16, 0, 1, 1
      INVOKE     lstrcat, addr szImage, addr szWorkS

;INVOKE     MessageBox, hWnd, addr szImage, addr szDisplayName, MB_OK
         mov     eax, Hold
         mov     esi, pMemL
       MOVmd     ID, dword ptr [esi+eax]
         mov     ebx, dword ptr [esi+eax+4]                  ; Offset of the image in the file
         mov     ecx, dword ptr [esi+eax+8]                  ; Image size minus header
         mov     edx, dword ptr [esi+eax+20]                 ; Offset to group
       MOVmd     Hold, dword ptr [esi+eax+16]                ; Group ID
       MOVmd     Len, dword ptr [esi+eax+24]                 ; Group length

      .if ID == 1
            jmp     ViewBMP
      .elseif ID == 2
            jmp     ViewBMP
      .elseif ID == 3
            jmp     ViewBMP
      .endif
         jmp     ExtractImgDone

ViewBMP:
      INVOKE     CreateDialogParam, hInst, 4820, hWnd, offset ViewBMPDlg, 0
         jmp     ExtractImgDone

NoRsrc:
      INVOKE     MessageBox, hWnd, addr szError8, addr szDisplayName, MB_OK

ExtractImgDone:
         mov     eax, FALSE                                  ; Return with FALSE

         RET
ExtractImg ENDP

;========================================
; Build A Cursor Or Icon Procedure
;========================================
BuildCurIco PROC  uses ebx edx esi edi  iID:DWORD, iOff, iLen, iGrpID, iOffGrp, iLenGrp, iFlag
LOCAL    Cnt:DWORD, SavSize, TotLen, Restart

         mov     ebx, iOff
         mov     ecx, iLen
         mov     edx, iOffGrp
      .if iFlag != 44
            jmp     SingleImg
      .endif

;---------- [Build a mult Icon or Cursor header from the group] ----------
         mov     Cnt, 6
         mov     esi, pMap
         mov     edi, pMemI                    ; Image file
         add     esi, iOffGrp
         mov     eax, dword ptr [esi]
         mov     dword ptr [edi], eax
         mov     ax, word ptr [esi+4]
         mov     word ptr [edi+4], ax
         xor     ecx, ecx
         mov     cx, ax
         add     esi, 6
         add     edi, 6
        push     ecx
      .while (ecx)
         .if iID == 1
               mov     al, byte ptr [esi]
               mov     byte ptr [edi], al      ; Width
               mov     byte ptr [edi+1], al    ; Height
               mov     ax, 0
               mov     word ptr [edi+2], ax    ; Fill
              push     esi
               mov     esi, pMap
               add     esi, iOff
               mov     eax, dword ptr [esi]
               mov     dword ptr [edi+4], eax  ; x/y hotspot
               pop     esi
         .else
               mov     eax, dword ptr [esi]
               mov     dword ptr [edi], eax    ; 
               mov     eax, dword ptr [esi+4]
               mov     dword ptr [edi+4], eax  ; 
         .endif
            mov     eax, dword ptr [esi+8]     ; Size
         .if iID == 1
               sub     eax, 4
         .endif
            mov     dword ptr [edi+8], eax
            add     esi, 14
            add     edi, 16
            dec     ecx
      .endw
         mov     eax, edi
         sub     eax, pMemI
         mov     SavSize, eax

;---------- [Update the offsets to the images] ----------
         mov     edi, pMemI                    ; Image file
         add     edi, 14
         pop     ecx
         mov     eax, ecx
        imul     eax, 16
         add     eax, 6
         mov     dword ptr [edi+4], eax        ; Offset to the image header
         dec     ecx
      .while (ecx)
            mov     eax, dword ptr [edi]
            add     eax, dword ptr [edi+4]
            mov     dword ptr [edi+20], eax
            add     edi, 16
            dec     ecx
      .endw

       MOVmd     TotLen, SavSize

;---------- [Build the Icon or Cursor file] ----------
         mov     esi, pMemI
         xor     ebx, ebx
         mov     bx, word ptr [esi+4]
      .while (ebx)
            mov     eax, SavStart
           imul     eax, 32
            mov     esi, pMemL
            add     esi, eax
            mov     edx, dword ptr [esi+4]
            mov     ecx, dword ptr [esi+8]
            mov     esi, pMap
            add     esi, edx
         .if iID == 1
               add     esi, 4
               sub     ecx, 4
               sub     TotLen, 4
         .endif
            mov     edi, pMemI                 ; Image array
            add     edi, TotLen
         .if iID == 1
               add     edi, 4
               add     TotLen, ecx
               add     TotLen, 4
         .else
            add     TotLen, ecx
         .endif
            xor     edx, edx
         .while (ecx)
               mov     al, byte ptr [esi+edx]
               mov     byte ptr [edi], al
               inc     edx
               inc     edi
               dec     ecx
         .endw
            inc     SavStart
            dec     ebx
      .endw

         mov     ebx, iOff
         mov     esi, pMap
         add     esi, ebx
       MOVmd     Hold, TotLen
         mov     ecx, Hold
         jmp     CreateCurIco

SingleImg:
;---------- [Build a single Icon or Cursor header from the group] ----------
         mov     esi, pMap
         mov     edi, pMemI                ; Image file
         add     esi, edx
        push     ebx
        push     ecx
         xor     ebx, ebx
         mov     ecx, 22                   ; Length of single header
      .while (ecx)
            mov     al, byte ptr [esi+ebx]
            mov     byte ptr [edi+ebx], al
            inc     ebx
            dec     ecx
      .endw

         mov     byte ptr [edi+4], 1       ; Sets number of images to one

         mov     ax, word ptr iGrpID
         xor     ebx, ebx
      .if word ptr [esi+ebx+18] != ax      ; Check for mult group entries
         .if iLenGrp > 20
               sub     iLenGrp, 20
               mov     ebx, 20
            .while (iLenGrp)
               .if word ptr [esi+ebx+12] == ax
                     mov     ecx, 14
                     mov     edx, 6
                  .while (ecx)             ; Get matching group info
                        mov     al, byte ptr [esi+ebx]
                        mov     byte ptr [edi+edx], al
                        inc     ebx
                        inc     edx
                        dec     ecx
                  .endw
                  .break
               .endif
                  add     ebx, 14
                  sub     iLenGrp, 14
            .endw
         .endif
      .endif

      .if iID == 1              ; Fix the size for cursors
            xor     ebx, ebx
            mov     al, byte ptr [edi+ebx+6]
            mov     byte ptr [edi+ebx+7], al
            mov     ax, word ptr [edi+ebx+12]
            mov     word ptr [edi+ebx+8], ax
      .endif
         pop     ecx
         pop     ebx
        push     ebx
        push     ecx

;---------- [Build the Icon or Cursor file] ----------
         mov     esi, pMap
         add     esi, ebx
         mov     edi, pMemI     ; Image array
         add     edi, 22
         xor     ebx, ebx

      .if iID ==1
            sub     dword ptr [edi+ebx-8], 4 ; Image size
            mov     eax, dword ptr [esi]
            mov     dword ptr [edi+ebx-12], eax
            add     esi, 4
            sub     ecx, 4
      .endif

         mov     dword ptr [edi+ebx-4], 16h  ; Offset from header
      .while (ecx)
            mov     al, byte ptr [esi+ebx]
            mov     byte ptr [edi+ebx], al
            inc     ebx
            dec     ecx
      .endw
         pop     ecx
         pop     ebx
         mov     esi, pMap
         add     esi, ebx

         mov     Hold, ecx
         add     Hold, 22                    ; 22 = header size

CreateCurIco:
      .if iID == 3
         INVOKE     CreateIconFromResourceEx, esi, ecx, 1, 30000h, 32, 32, LR_DEFAULTCOLOR   ; Icon
      .else
            mov     edi, pMemI
            add     edi, 6
            xor     eax, eax
            mov     al, byte ptr [edi]
            mov     ebx, eax
            mov     al, byte ptr [edi+1]
            mov     edx, eax
      .if iFlag != 44
            sub     Hold, 4
      .endif
         INVOKE     CreateIconFromResourceEx, esi, ecx, 0, 30000h, ebx, edx, LR_DEFAULTCOLOR ; Cursor
      .endif
         mov     hIC, eax

         RET
BuildCurIco ENDP

;========================================
; Build A Bitmap Procedure
;========================================
BuildBmp PROC  uses ebx edx esi edi  iOff:DWORD, iLen

         mov     ebx, iOff
         mov     ecx, iLen

;---------- [Bitmap header] ----------
         mov     esi, pMap
         xor     eax, eax
         mov     edi, pMemI
         mov     word ptr [edi+eax], 'MB'
         add     ecx, 0eh
         mov     dword ptr [edi+eax+2], ecx   ; Bitmap size
         xor     edx, edx
         mov     dword ptr [edi+eax+6], edx   ; 0 fill
         mov     edx, 36h
         mov     dword ptr [edi+eax+10], edx  ; Bitmap bits offset

;---------- [Adjust the offset to the bitmap bits. Find the length of the color table] ----------
         xor     edx, edx
         mov     dx, word ptr [esi+ebx+14]    ; biBitCount
       MOVmd     Hold, dword ptr [esi+ebx+32]
      .if edx == 8 && Hold == 0
            mov     edx, 100h                 ; 1024 bits
      .elseif edx == 4 && Hold == 0
            mov     edx, 10h                  ; 64 bits
      .else
            mov     edx, dword ptr [esi+ebx+32]  ; biClrUsed 'color array'
      .endif
        imul     edx, 4
         add     dword ptr [edi+eax+10], edx
         add     esi, ebx                     ; Offset of the Bitmap in the file
         add     edi, 0eh                     ; Offset of the Bitmap header
         mov     Hold, ecx
         sub     ecx, 0eh                     ; Remove the header size
         xor     ebx, ebx
      .while (ecx)
            mov     al, byte ptr [esi+ebx]
            mov     byte ptr [edi+ebx], al
            inc     ebx
            dec     ecx
      .endw

         RET
BuildBmp ENDP

;========================================
; Display Images Procedure
;========================================
ViewBMPDlg PROC  uses ebx ecx edx esi edi  hdlg:DWORD, wmsg, wparam, lparam
LOCAL    rect:RECT
LOCAL    szWorkS[10]:BYTE
LOCAL    iArray[8]:DWORD
LOCAL    hBmp1:DWORD, hOldBmp1, hMemDC, XP, YP, Iw, Ih, Cnt, Incr, sw

      .if wmsg == WM_INITDIALOG
            xor     eax, eax
            mov     ecx, 30
         .while     ecx
            .if ImgArray[eax] == 0
                MOVmd     ImgArray[eax], hdlg
               .break
            .endif
               add     eax, 4
               dec     ecx
         .endw
         INVOKE     SetWindowText, hdlg, addr szImage
         INVOKE     PostMessage, hdlg, WM_LBUTTONDOWN, 44, 0 ; Post to display opened image
            jmp     ViewDone

;      .elseif wmsg == WM_CTLCOLORDLG
;         INVOKE     SetBkColor, wparam, 00000000h       ; Background color is black
;         INVOKE     GetStockObject, BLACK_BRUSH         ; Select the black brush for background
;            jmp     ViewRet                             ; Return with brush in eax

      .elseif wmsg == WM_RBUTTONUP
;          MOVmd     hDLG, hdlg
         INVOKE     GetWindowRect, hdlg, addr rect
            mov     ecx, lparam                         ; x/y pos of window
            mov     ebx, ecx
            and     ebx, 0000ffffh                      ; ebx = LOWORD(lparam) = x pos
            shr     ecx, 16                             ; eax = HIWORD(lparam) = y pos
            add     ebx, rect.left
            add     ecx, rect.top
            add     ebx, 3                              ; x Position
            add     ecx, 20                             ; y Position
         INVOKE     TrackPopupMenu, hSubMenu, TPM_LEFTALIGN or TPM_LEFTBUTTON, ebx, ecx, 0, hdlg, addr rect

      .elseif wmsg == WM_PAINT && hdlg != 0
         INVOKE     PostMessage, hWnd, WM_PAINT, 0, 0   ; Need for NT
            jmp     DisplayEM

      .elseif wmsg == WM_LBUTTONDOWN
         .if wparam != 44
            INVOKE     PostMessage, hdlg, WM_NCLBUTTONDOWN, HTCAPTION, 0 ; Post to drag window in the client area
         .endif
            jmp     ViewDone ;DisplayEM

      .elseif wmsg != WM_COMMAND
            jmp     ViewDone
      .endif

         mov     eax, wparam
         cmp     eax, 404             ; Save as
          je     Export
         cmp     eax, 405             ; Close
          je     RemoveDlg
         jmp     ViewDone

Export:
         mov     sw, 1
         jmp     BuildImg

DisplayEM:
         and     sw, 0
      .if !pMemI                      ; For closing the tab control
            jmp     CancelOut
      .endif
      INVOKE     GetWindowRect, hdlg, addr rect
       MOVmd     XP, rect.left
       MOVmd     YP, rect.top

BuildImg:
      INVOKE     GetWindowText, hdlg, addr szBuff, Lengthof szBuff

         mov     Cnt, 8
         and     Incr, 0
      .while (Cnt)
            mov     ebx, Incr
         INVOKE     lstrcpyn, addr szWorkS, addr szBuff[ebx], 9
         INVOKE     AsciiBase, addr szWorkS, addr Hold, 16
            mov     ebx, Incr
            shr     ebx, 1
          MOVmd     dword ptr iArray[ebx], Hold
            add     Incr, 8
            dec     Cnt
      .endw
         mov     ebx, Incr
      INVOKE     lstrcpyn, addr szWorkS, addr szBuff[ebx], 9
      INVOKE     AsciiBase, addr szWorkS, addr SavStart, 16


      .if dword ptr iArray != 2
         INVOKE     BuildCurIco, dword ptr iArray, dword ptr iArray+4, dword ptr iArray+8,\
                    dword ptr iArray+16, dword ptr iArray+20, dword ptr iArray+24, dword ptr iArray+28
      .else
         INVOKE     BuildBmp, dword ptr iArray+4, dword ptr iArray+8
      .endif
         cmp     sw, 1
          je     ExportImg

      INVOKE     GetDC, hdlg                              ; Get dc the of the window
         mov     hDC, eax
         mov     esi, pMemI

         mov     eax, 10
         mov     ebx, dword ptr [esi+eax]
       MOVmd     Iw, dword ptr [esi+eax+8]
       MOVmd     Ih, dword ptr [esi+eax+12]
         add     esi, ebx
      .if dword ptr iArray != 2
            jmp     ID13
      .endif

         mov     edi, pMemI
         add     edi, 14                                 ; Pointer to bitmap size and format data
      INVOKE     CreateDIBitmap, hDC, edi, CBM_INIT, esi, edi, 0 ; Creates a device-dependent bitmap from a device-independent bitmap
         mov     hBmp1, eax
      INVOKE     CreateCompatibleDC, hDC                 ; Create a compatible dc in memory
         mov     hMemDC, eax
      INVOKE     SelectObject, hMemDC, hBmp1             ; Select the opened bitmap into the dc
       MOVmd     ebx, Iw
       MOVmd     ecx, Ih
         add     ebx, 6
         add     ecx, 6
      INVOKE     MoveWindow, hdlg, XP, YP, ebx, ecx, 1

ID13:
      .if dword ptr iArray != 2
            mov     edi, pMemI
            add     edi, 6
            xor     eax, eax
            mov     al, byte ptr [edi]
            mov     Iw, eax
            mov     al, byte ptr [edi+1]
            mov     Ih, eax
         INVOKE     CreateCompatibleDC, hDC              ; Create a compatible dc in memory
            mov     hMemDC, eax
         INVOKE     CreateCompatibleBitmap, hDC, Iw, Ih
            mov     hBmp1, eax
         INVOKE     SelectObject, hMemDC, hBmp1          ; Select the opened bitmap into the dc
            mov     hOldBmp1, eax
          MOVmd     ebx, Iw
          MOVmd     ecx, Ih
            add     ebx, 6
            add     ecx, 6
         INVOKE     MoveWindow, hdlg, XP, YP, ebx, ecx, 1
         INVOKE     DrawIconEx, hDC, 0, 0, hIC, Iw, Ih, 0, 0, DI_NORMAL
         INVOKE     SelectObject, hMemDC, hOldBmp1       ; Select the old bitmap into the dc
            jmp     NoBitBlt
      .endif

      INVOKE     BitBlt, hDC, 0, 0, Iw, Ih, hMemDC, 0, 0, SRCCOPY ; Copy the bitmap

NoBitBlt:
      INVOKE     DeleteDC, hMemDC                        ; Delete the memory dc
      INVOKE     ReleaseDC, hdlg, hDC     
      INVOKE     DeleteObject, hBmp1
      INVOKE     CloseHandle, hIC
         jmp     ViewDone 

ExportImg:
;         mov     szBuff, 0
      .if dword ptr iArray == 1
         INVOKE     lstrcpy, addr szBuff, addr szCur
      .elseif dword ptr iArray == 2
         INVOKE     lstrcpy, addr szBuff, addr szBmp
      .elseif dword ptr iArray == 3
         INVOKE     lstrcpy, addr szBuff, addr szIco
      .endif
         mov     ofn.lStructSize, sizeof ofn
       MOVmd     ofn.hwndOwner, hWnd
       MOVmd     ofn.hInstance, hInst
         mov     ofn.lpstrFilter, offset szFilterI
         mov     ofn.lpstrFile, offset szBuff
         mov     ofn.nMaxFile, sizeof szBuff
         mov     ofn.lpstrTitle, offset szTitleS
         mov     ofn.Flags, OFN_EXPLORER or OFN_OVERWRITEPROMPT or OFN_CREATEPROMPT
      INVOKE     GetSaveFileName, addr ofn
         cmp     eax, FALSE       ; Cancel'ed or error occurred
          je     ViewDone

      INVOKE     CreateFile, addr szBuff,\
                 GENERIC_READ or GENERIC_WRITE,\
                 FILE_SHARE_READ or FILE_SHARE_WRITE,\
                 0, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, 0
         mov     hFile, eax
         mov     ecx, dword ptr iArray+8
         mov     ecx, Hold
      INVOKE     WriteFile, hFile, pMemI, ecx, addr Cnt, NULL
      INVOKE     CloseHandle, hFile
         jmp     ViewDone 

RemoveDlg:
         xor     eax, eax
         mov     ecx, 30
      .while (ecx)                                       ; Find handle of active window in the array
            mov     edx, hdlg
         .if ImgArray[eax] == edx
             MOVmd     ImgArray[eax], ImgArray[eax+4]
               add     eax, 4
               dec     ecx
            .while (ecx)                                 ; Shift the array to the left
                MOVmd     ImgArray[eax], ImgArray[eax+4]
                  add     eax, 4
                  dec     ecx
            .endw
            .break  
         .endif
            add     eax, 4
            dec     ecx
      .endw

CancelOut:
      INVOKE     EndDialog, hdlg, wparam
         mov     eax, TRUE          ; Return
         jmp     ViewRet            ; with TRUE

ViewDone:
         mov     eax, FALSE         ; Return with FALSE

ViewRet:
         RET
ViewBMPDlg ENDP


;=======================================
; Convert Hex - Dec text
;=======================================
SwapHexDec PROC hdlg:DWORD, Ident, CF, CT
LOCAL    Val:DWORD

      INVOKE     ValHexDec, hdlg, Ident, CF, 10
         cmp     eax, 1
          je     NoSwap

      INVOKE     GetDlgItemText, hdlg, Ident, addr szBuff, 10
      INVOKE     AsciiBase, addr szBuff, addr Val, CF
      INVOKE     BaseAscii, Val, addr szWork, 1, CT, 0, 1, 1
      INVOKE     SetDlgItemText, hdlg, Ident, addr szWork

NoSwap:
         RET
SwapHexDec ENDP

;=======================================
; Validate user input
;=======================================
ValHexDec PROC hdlg:DWORD, Ident, Base, len

         INVOKE     GetDlgItemText, hdlg, Ident, addr szWork, len
            xor     esi, esi
         .while (eax)
               mov     bl, byte ptr szWork[esi]
            .if Base == 16
               .if bl > 2fh && bl < 3ah || bl > 40h && bl < 47h || bl > 60h && bl < 67h
                     jmp     HexDecOK
               .else
                     jmp     ValidateErr
               .endif
            .else
               .if bl > 2fh && bl < 3ah
                     jmp     HexDecOK
               .else
                     jmp     ValidateErr
               .endif
            .endif

HexDecOK:
               inc     esi
               dec     eax
         .endw
         mov     eax, FALSE
         RET

ValidateErr:
      INVOKE     lstrcpy, addr szHexDec, addr szWork
      INVOKE     MessageBox, hWnd, addr szError4, addr szDisplayName, MB_OK
;         mov     szWork, 0
;      INVOKE     SetDlgItemText, hdlg, ID, addr szWork
         mov     eax, TRUE
         RET
ValHexDec ENDP

;===============================
; Fill compare windows
;===============================
FillEdit PROC  uses ebx edx esi edi  hEdit:DWORD, InFile, len, Base, OffEdit
LOCAL    hMemO:DWORD, pMemO, BytesO, SavIn, SavOut, Cnt, Num, BuffOff, Val

         mov     eax, len
        imul     eax, 5
         mov     BytesO, eax

      INVOKE     HeapCreate, HEAP_GENERATE_EXCEPTIONS, BytesO, 0
         mov     hMemO, eax
      INVOKE     HeapAlloc, hMemO, HEAP_GENERATE_EXCEPTIONS, BytesO
         mov     pMemO, eax

         mov     SavIn, 0
         mov     SavOut, 0
         mov     Cnt, 0
         mov     Len, 17

LoopIt:
         mov     Num, 0
         mov     BuffOff, 0
         mov     edi, SavOut
         mov     eax, pMemO
         add     eax, edi
mov     Hold, edi
      INVOKE     BaseAscii, Cnt, eax, 8, Base, 0, 1, 1
         mov     ecx, Len
         dec     ecx
         add     SavOut, 9
         mov     edi, SavOut
         mov     edx, pMemO
   mov     byte ptr[edx+edi-1], ' '

      .while (ecx)
            mov     esi, SavIn
            mov     ebx, InFile ;pMem
            mov     al, byte ptr [ebx+esi]
            mov     esi, BuffOff
         .if al == 0ah || al == 0dh || al == 09h || al < 20h || al > 7fh
               mov     byte ptr szBuff[esi], 2eh
         .else
               mov     byte ptr szBuff[esi], al
         .endif
            shr     eax, 4
            and     eax, 0fh
         .if eax > 9
            add     eax, 37h
         .else
            add     eax, 30h
         .endif
            mov     byte ptr[edx+edi], al
            mov     esi, SavIn
            mov     ebx, InFile ;pMem
            mov     al, byte ptr [ebx+esi]
            and     eax, 0fh
         .if eax > 9
               add     eax, 37h
         .else
               add     eax, 30h
         .endif
            inc     edi
            mov     byte ptr[edx+edi], al
            inc     BuffOff
            inc     SavIn
            add     Num, 2
            inc     edi
         .if Num == 4
               mov     byte ptr[edx+edi], ' '
               inc     edi
               mov     Num, 0
         .endif
            dec     ecx
      .endw

         mov     esi, BuffOff
         mov     byte ptr szBuff[esi], 0
         dec     edi
      .if Num == 2
            inc     edi
      .endif
         mov     SavOut, edi
         mov     word ptr[edx+edi], '  '
         inc     edi
         inc     edi
         mov     eax, 17
      .if Len < eax
            mov     eax, edi
            sub     eax, Hold
            mov     ecx, 50
            sub     ecx, eax
         .while (ecx)
               mov     byte ptr[edx+edi], ' '
               inc     edi
               dec     ecx
         .endw
      .endif

;---------- [Ascii characters] ---------- 
         mov     edx, pMemO
         mov     ecx, 16
         xor     ebx, ebx
      .while (ecx)
            mov     al, byte ptr szBuff[ebx]
            mov     byte ptr[edx+edi], al
            inc     edi
            inc     ebx
            dec     ecx
      .endw

         add     Cnt, 16
;INVOKE     MessageBox, hWnd, pMemO, addr szDisplayName, MB_OK
         mov     eax, len
      .if SavIn < eax
            sub     eax, SavIn
         .if eax < 17
               inc     eax
               mov     Len, eax
         .endif
            mov     edx, pMemO
            mov     edi, SavOut
            add     edi, 18
            mov     word ptr[edx+edi], 0A0Dh
            add     SavOut, 20
            jmp     LoopIt
      .endif

      INVOKE     SendMessage, hEdit, WM_SETTEXT, NULL, pMemO
      INVOKE     HeapDestroy, hMemO

      INVOKE     BaseAscii, OffEdit, addr szWork, 8, Base, 0, 1, 1
         mov     ft.chrg.cpMin, 0
         mov     ft.chrg.cpMax, -1
         mov     Cnt, 15

      INVOKE     AsciiBase, addr szWork, addr Val, Base
         mov     eax, Val
         xor     edx, edx
         div     Base
        imul     eax, Base
      INVOKE     BaseAscii, eax, addr szWork, 8, Base, 0, 1, 1

DoAgain:
         lea     eax, offset szWork
         mov     ft.lpstrText, eax
      INVOKE     SendMessage, hEdit, EM_FINDTEXT, FR_DOWN, offset ft
         cmp     eax, -1                 ; Nothing found?
         jne     FoundIt
      .while (Cnt)
            and     Val, 0
         INVOKE     AsciiBase, addr szWork, addr Val, Base
            dec     Val
         INVOKE     BaseAscii, Val, addr szWork, 8, Base, 0, 1, 1
            dec     Cnt
            jmp     DoAgain
      .endw
         jmp     Pass

FoundIt:
         mov     cr.cpMin, eax
         add     eax, 8
         mov     cr.cpMax, eax
      INVOKE     SendMessage, hEdit, EM_EXSETSEL, 0, offset cr
      INVOKE     SendMessage, hEdit, EM_GETSELTEXT, 0, addr szWork
      INVOKE     AsciiBase, addr szWork, addr Val, Base
         mov     eax, OffEdit
         sub     eax, Val
         mov     OffEdit, eax
         mov     word ptr szWork, 60
      INVOKE     SendMessage, hEdit, EM_GETLINE, 0, addr szWork
         mov     eax, OffEdit
         shl     eax, 1
         mov     ecx, eax
         inc     ecx
         mov     ebx, 9
      .while (ecx)
         .if byte ptr szWork[ebx] == 20h
               inc     eax
               inc     ebx
         .else
               inc     ebx
               dec     ecx
         .endif
      .endw
         add     eax, 9
         add     cr.cpMin, eax
       MOVmd     cr.cpMax, cr.cpMin
         add     cr.cpMax, 2
      INVOKE     SendMessage, hEdit, EM_EXSETSEL, 0, offset cr

Pass:
         RET
FillEdit ENDP

end start
;INVOKE     MessageBox, hWnd, addr szWork, addr szDisplayName, MB_OK

