| Index | Manual | Download | Source | Macros | Embedded word Case ins.
Sitemap | Links | Forum | Tests | Projects

# dirswing.htm
Data
Data
Procedures
FindToBuffer
MainGui
PaintMarks
RenameButtons
WndCreate
WndPaint
WndProc
WndResize

This is a GUI module of EuroTool program EuroDirs for Windows.

         EUROASM CPU=X64, SIMD=Yes, Unicode=No, MaxInclusions=100, DumpWidth=36
    dirswing PROGRAM Format=COFF,Width=64, MaxExpansions=90K
               %DROPMACRO *
               EXTERN BufferStore@RT, FileAssignW64@RT, FileNameParseW64@RT
               INCLUDEHEAD1 argument.htm
               INCLUDE1 winansi.htm,fastcall.htm,winabi.htm,winsgui.htm,winsdlg.htm,winf64.htm
               INCLUDE1 cpuext.htm,status32.htm,memory64.htm,string64.htm
               LINK ../objlib/winapi.lib

↑ Data

    FIND_INDEX       STRUC     ; Structure saved in FindBuffer.
    .LineNr            D DWORD ; Ordinal number of a line from the selected buffer. 1,2,3...MaxLineNr
    .Offset            D DWORD ; 0,2,4,,,Offset of the found text from the start of line in bytes.
                     ENDSTRUC FIND_INDEX
    CP_UTF8          = 65001
    ScanDirBrowseId  = 0x8001
    ScanDirEditId    = 0x8002
    OlderSelectBtnId = 0x8005
    OlderEditId      = 0x8006
    NewerSelectBtnId = 0x8007
    NewerEditId      = 0x8008
    Btn1Id           = 0x8011
    Btn2Id           = 0x8012
    Btn3Id           = 0x8013
    Btn4Id           = 0x8014
    Btn5Id           = 0x8015
    FindEditId       = 0x8021
    FindBtnId        = 0x8022
    ColorFind        = 0x0080EEEE
    ColorCursor      = 0x00F0C0F0
    ColorWhite       = 0x00FFFFFF
    WheelPerLine     = 40      ; wParamHigh = 120 or -120 to scroll 3 rows up or down.
    [.rodata]
    ;;NameEURODIRS         DU "EURODIRS",0
    ;;MainWindowName       DU "EuroDirs",0
    ScanFilter           DU "Scan files",0,"*.scan",0,"All files",0,"*",0,0
    [.bss]
    FindIndex            DS FIND_INDEX
    Msg                  DS MSG                  ; Window message.
    WndClassEx           DS WNDCLASSEX ; Definition of the window class structure.
    ScanDirFileDlg       DS OPENFILENAME
    InpFileDlg           DS OPENFILENAME
    OutFileDlg           DS OPENFILENAME
    PaintStruct          DS PAINTSTRUCT
    TextMetric           DS TEXTMETRICW
    ScrollInfo           DS SCROLLINFO
    MainWindowRect       DS RECT
    DirWindowRect        DS RECT
    ScanDirBrowseHandle  D QWORD
    ScanDirEditHandle    D QWORD
    OlderTitleHandle     D QWORD
    OlderSelectBtnHandle D QWORD
    OlderEditHandle      D QWORD
    NewerTitleHandle     D QWORD
    NewerSelectBtnHandle D QWORD
    NewerEditHandle      D QWORD
    FindBuffer           D QWORD
    FindChars            D DWORD ; Number of unichars in FindText.
    PenHandle            D QWORD
    Handles:
    Btn1Handle           D QWORD
    Btn2Handle           D QWORD
    Btn3Handle           D QWORD
    Btn4Handle           D QWORD
    Btn5Handle           D QWORD
    FindTextHandle       D QWORD
    FontHandle           D QWORD
    MainWindowHandle     D QWORD ; Handle of the main window.
    DirWindowHandle      D QWORD ; Handle of the window with volumes and dir names.
    hDirDC               D QWORD ; Handle of device context used in painting DirWindow.
    hMainDC              D QWORD ; Handle of device context used in painting MainWindow.
    hBrushFind           D QWORD ; Handle of brush in Find window.
    ClientY              D QWORD ; Y-coordinate of the client line (0,10,20,,ClientLines*10).
    ClientLines          D DWORD ; Number of lines which will fit into client area.
    ClientLinesMinus2    D DWORD
    WindowWidth          D DWORD
    WindowHeight         D DWORD
    PreviousPos          D DWORD
    SelectedLineNr       D DWORD   ; Number of line from [BufferSelected] (0..MaxLineNr::).
    CursorLineNr         D DWORD   ; Line with a cursor (0..MaxLineNr::).
    WheelCnt             D DWORD   ; Accumulated WheelPerLine value when mouse wheel is rolled.
    ScanDir              D 260 * UNICHAR
    FindText             D 260 * UNICHAR
    [.text]

MainGui
  This is the graphic entry procedure.

    MainGui:: PROC
         CALL WndCreate               ; Initialize the main program window.
         CALL WndResize
         WinABI ShowWindow,[MainWindowHandle],SW_SHOW
         WinABI UpdateWindow,[MainWindowHandle]
         WinABI PostMessage,[MainWindowHandle],WM_COMMAND,Btn2Id,0
    .MsgLoop:
         WinABI GetMessage, Msg,0,0,0
         TEST RAX
         JZ .MsgQuit:                                 ; ZF signalizes message WM_QUIT - request for program termination.
         WinABI TranslateMessage, Msg                 ; Remap character keys from national keyboards.
         WinABI DispatchMessage,  Msg                 ; Let Windows call our WndProc.
         JMP .MsgLoop:                                ; Wait for another message.
    .MsgQuit:
         JMP MainCon.Terminate::
       ENDP MainGui

WndProc, hWnd, uMsg, wParam, lParam

  This is a callback procedure which receives and handles messages for the MainWindow. Message parameters are by FastCall convention provided in registers RCX, RDX, R8, R9, we'll save them to shadow space with macro SaveToShadow . Thanks to this their contents will be available by formal names ( `[%hWnd], [%uMsg], [%wParam], [%lParam]`), too, in the entire WndProc body.

  Messages obtained from Windows are dispatched by WndProc to their handlers.
  Unhandled messages are passed to DefWindowProc.

Handler input
  RCX=[%hWnd] is the main window handle (the same as static [MainWindowHandle] obtained by WndCreate).
  RDX=[%uMsg] is message identifier,
  R8=[%wParam] is message w-parameter,
  R9=[%lParam] is message l-parameter.
Handler output
  RAX=0 if the message was completely processed by the handler. Otherwise the message is processed by WinAPI DefWindowProc and RAX outputs its return value.
  Scratch registers RCX,RDX,R8..R11 may be destroyed in the handlers.
  Callee-save registers RBX,RSI,RDI,R12..R15 must be restored, if used in the handlers. This provides macro Uses.
Invoked by
  WinAPI DispatchMessage.

    WndProc Procedure hWnd, uMsg, wParam, lParam ; These parameters are provided in RCX,RDX,R8,R9.
        SaveToShadow
        Uses RBX,RBP,RSI,RDI ; It's only necessary if some of callee-save registers was used in this fastcalled procedure.
        ; Fork message uMsg=RDX to its handler using macro Dispatch:
         Dispatch EDX, WM_CREATE, WM_PAINT, WM_SIZE, WM_VSCROLL, \
                  WM_MOUSEWHEEL, WM_KEYDOWN, WM_SYSKEYDOWN, WM_COMMAND, WM_DESTROY,  \
                  WM_LBUTTONDOWN, WM_RBUTTONDOWN, WM_RBUTTONUP ;;;;;;;;;;;;;;, WM_CTLCOLOREDIT
    .Def:WinABI DefWindowProc,[%hWnd],[%uMsg],[%wParam],[%lParam]  ; Pass ignored event to DefWindowProc with unchanged arguments.
         JMP .Ret:  ; Go to EndProcedure with result value RAX as returned from DefWindowProc.
         ; All message handlers terminate with a jump to label .Def: or .Ret0:.
    .WM_CREATE: ; MainWindow is created.
       WinABI GetClientRect,[MainWindowHandle],MainWindowRect
       MOV EDX,[MainWindowRect.right]
       MOV ECX,[MainWindowRect.bottom]
       MOV [WindowWidth],EDX
       MOV [WindowHeight],ECX
       WinABI GetDC,[MainWindowHandle]
       MOV [hDirDC],RAX
       WinABI GetTextMetrics,RAX,TextMetric
       WinABI ReleaseDC,[MainWindowHandle],[hDirDC]
       JMP .Ret0:
    .WM_PAINT:  ; Window needs to repaint its contents. Use procedure WndPaint.
         CALL WndPaint
         JMP .Ret0:
    .WM_SIZE:
         CALL WndResize
         JMP .Ret0:
    .WM_LBUTTONDOWN:        ; Mouse button will move line-cursor in DirWindow.
    .WM_RBUTTONDOWN:
         SHR R9,16
         MOVZX RAX,R9W      ; RAX is y-coordinate.
         XOR EDX,EDX
         MOV EDI,[TextMetric.tmHeight]
         DIV RDI
         ADD EAX,[SelectedLineNr]
         MOV [CursorLineNr],EAX
         WinABI InvalidateRect,[DirWindowHandle],0,-1 ; Repaint DirWindow.
         JMP .Ret:
    .WM_RBUTTONUP:          ; When the right mouse button is released, it starts a new window
          MOV EBX,[CursorLineNr]  ; with the directory selected by line-cursor.
          CALL OneLine2Dir::
          MOV RDI,RSI
          MOV AX,' '
          REPNE SCASW
          JNE .Ret0:
          WinABI ShellExecuteW,[DirWindowHandle],0,RDI,0,0,SW_SHOWNORMAL
          JMP .Ret:
    .WM_KEYDOWN:   ; Non-character hot key R8D=wParam was pressed.
         MOV EAX,[SelectedLineNr]    ; Prepare EAX and ECX for the cursor keys.
         MOV ECX,[MaxLineNr::]
         SUB ECX,[ClientLinesMinus2] ; Maximal position of the selected line.
         JGE .10:
         XOR ECX,ECX
    .10: Dispatch R8D, VK_UP,VK_DOWN,VK_NEXT,VK_PRIOR,VK_HOME,VK_END,VK_ESCAPE, \ Dispatch the cursor keys.
                  'B','S','E','F','1','2','3','4','5','a','b','c','d','e'
         JMP .Def: ; Pass unhandled keys to WinABI DefWindowProc.
    .WM_SYSKEYDOWN:     ; A key pressed together with Alt.
       Dispatch R8W,'B','S','E','F','1','2','3','4','5','a','b','c','d','e'
       JMP .Def:
    .Saturate: ; SelectedLineNr in EAX will be saturated to the range 0..ECX=MaxLineNr-ClientLinesMinus2.
         TEST EAX
         JNS .20:
         XOR EAX,EAX
    .20: CMP EAX,ECX
         JB .30:
         MOV EAX,ECX
    .30: MOV [SelectedLineNr],EAX
         MOV [ScrollInfo.nPos],EAX
         MOV [PreviousPos],EAX
         WinABI SetScrollInfo,[DirWindowHandle],SB_VERT,ScrollInfo,-1
         WinABI InvalidateRect,[DirWindowHandle],0,0
         JMP .Ret0:
    .SB_LINEUP:
    .VK_UP:
         DEC EAX
         JMP .Saturate:
    .SB_LINEDOWN:
    .VK_DOWN:
         INC EAX
         JMP .Saturate:
    .SB_PAGEDOWN:
    .VK_NEXT:
         ADD EAX,[ClientLinesMinus2]
         JMP .Saturate:
    .SB_PAGEUP:
    .VK_PRIOR:
         SUB EAX,[ClientLinesMinus2]
         JMP .Saturate:
    .SB_TOP:
    .VK_HOME:
         XOR EAX,EAX
         JMP .Saturate:
    .SB_BOTTOM:
    .VK_END:
         MOV EAX,ECX
         JMP .Saturate:
    .WM_VSCROLL:     ; LOWORD R8 is nScrollCode (SB_TOP,SB_BOTTOM, SB_LINEUP etc).
         MOV [ScrollInfo.cbSize],SIZE# SCROLLINFO
         MOV [ScrollInfo.fMask],SIF_ALL
         WinABI GetScrollInfo,[DirWindowHandle],SB_VERT,ScrollInfo
         MOV EAX,[ScrollInfo.nPos]
         MOV [PreviousPos],EAX
         MOV ECX,[MaxLineNr::]
         MOV EAX,[SelectedLineNr]    ; Prepare EAX and ECX for the cursor keys.
         SUB ECX,[ClientLinesMinus2]
         JGE .40:
         XOR ECX,ECX
    .40: MOVZX EDX,R8W
         Dispatch EDX,SB_TOP,SB_BOTTOM,SB_LINEUP,SB_LINEDOWN,SB_PAGEUP,SB_PAGEDOWN,SB_THUMBTRACK
         JMP .Def:
    .SB_THUMBTRACK:
         MOV EAX,[ScrollInfo.nTrackPos]
         MOV [ScrollInfo.nPos],EAX
         MOV [SelectedLineNr],EAX
         MOV [ScrollInfo.fMask],SIF_POS
         WinABI SetScrollInfo,[DirWindowHandle],SB_VERT,ScrollInfo,-1
         WinABI GetScrollInfo,[DirWindowHandle],SB_VERT,ScrollInfo
         MOV EDX,[PreviousPos]
         SUB EDX,[ScrollInfo.nPos]
         JZ .Ret0:
         MOV EAX,[TextMetric.tmHeight]
         IMUL RDX
         WinABI ScrollWindow,[DirWindowHandle],0,RAX,0,0
         WinABI UpdateWindow,[DirWindowHandle]
         JMP .Ret0:
    .WM_MOUSEWHEEL:
         SAR R8D,16              ; R8D is now +120 or -120 on mouse-wheel roll.
         ADD [WheelCnt],R8D      ; Accumulate scroll requests.
         MOV R9D,[WheelCnt]
     .RollUp:
         CMP R9D,WheelPerLine
         JL  .RollDown:
         SUB R9D,WheelPerLine
         MOV [WheelCnt],R9D
         WinABI SendMessage,[DirWindowHandle],WM_VSCROLL,SB_LINEUP,0
         JMP .RollUp:
     .RollDown:
         CMP R9D,0
         JGE .Ret0:
         ADD R9D,WheelPerLine
         MOV [WheelCnt],R9D
         WinABI SendMessage,[DirWindowHandle],WM_VSCROLL,SB_LINEDOWN,0
         JMP .RollDown:
    .WM_COMMAND:: ; id=LOWORD R8
         MOVZX EDX,R8W
         Dispatch EDX, Btn1Id,Btn2Id,Btn3Id,Btn4Id,Btn5Id,                     \
                 ScanDirBrowseId,ScanDirEditId,OlderSelectBtnId,OlderEditId,   \
                 NewerSelectBtnId,NewerEditId,FindEditId,FindBtnId
         JMP .Def:               ; Let other commands handle by DefWindowProc().
    .F:
    .FindBtnId:
        LEA RCX,[FindText]
        WinABI GetWindowTextW,[FindTextHandle],RCX,260
        MOV [FindChars],EAX
        WinABI InvalidateRect,[DirWindowHandle],0,-1
        WinABI SetFocus,[MainWindowHandle]
        JMP .Ret0:
    .FindEditId:   ; An character was added/subtracted to the edit field FindText.
        LEA RCX,[FindText]
        WinABI GetWindowTextW,[FindTextHandle],RCX,SIZE# FindText /2
        MOV [FindChars],EAX
        CALL FindToBuffer
        CALL PaintMarks
        ; Invalidate marks on the right side.
        LEA RBX,[MainWindowRect]
        WinABI GetClientRect,[MainWindowHandle],RBX
        MOV EAX,[RBX+RECT.right]
        SUB EAX,10
        MOV [RBX+RECT.left],EAX
        WinABI InvalidateRect,[MainWindowHandle],RBX,-1
        WinABI InvalidateRect,[DirWindowHandle],0,-1
        JMP .Ret0:
    .1:
    .a:
    .Btn1Id:
         MOV AL,1
         JMP .50:
    .2:
    .b:
    .Btn2Id:
         MOV AL,2
         JMP .50:
    .3:
    .c:
    .Btn3Id:
         MOV AL,3
         JMP .50:
    .4:
    .d:
    .Btn4Id:
         MOV AL,4
         JMP .50:
    .5:
    .e:
    .Btn5Id:
         MOV AL,5
    .50: MOVZX EAX,AL
         MOV [ArgViewDirs::],EAX
         LEA RBX,[8*RAX-8+Buffers::]
         MOV [BufferSelected::],RBX
         BufferRetrieve RBX
         SHR ECX,4
         MOV [MaxLineNr],ECX
         MOVD [CursorLineNr],-1
         MOV EAX,ECX
         SUB EAX,[ClientLinesMinus2]
         JS .60:
         JAE .70:
    .60: XOR EAX,EAX
    .70: MOV [SelectedLineNr],EAX ; When the ViewDirs has changed, position the DirWindow to the bottom.
         WinABI PostMessage,[Btn1Handle],BM_SETSTATE,0,0 ; Unpush all five buttons first.
         WinABI PostMessage,[Btn2Handle],BM_SETSTATE,0,0
         WinABI PostMessage,[Btn3Handle],BM_SETSTATE,0,0
         WinABI PostMessage,[Btn4Handle],BM_SETSTATE,0,0
         WinABI PostMessage,[Btn5Handle],BM_SETSTATE,0,0
         MOV EAX,[ArgViewDirs::]
         MOV RBX,[Handles+8*RAX-8]                    ; RBX is now the handle of the selected button.
         WinABI PostMessage,RBX,BM_SETSTATE,-1,0      ; Make it pushed.
         WinABI InvalidateRect,[MainWindowHandle],0,-1
         WinABI SetFocus,[MainWindowHandle]
         CALL FindToBuffer
         CALL PaintMarks
         CALL WndResize
         JMP .Ret0:
     .B:                     ; Hotkey 'B' pressed.
    .ScanDirBrowseId:        ; Button [Browse] pressed.
         WinABI GetOpenFileNameW,ScanDirFileDlg
         TEST RAX
         JZ .Ret0:
         MOV RSI,[ScanDirFileDlg.lpstrFile]
         MOVZXW ECX,[ScanDirFileDlg.nFileOffset]
         LEA RDI,[ScanDirUTF16::]
         MOV RDX,RDI
         REP MOVSW
         XOR EAX,EAX
         STOSW
         MOV RSI,RDX
         WinABI SetWindowTextW,[ScanDirEditHandle],RSI
         LEA RDI,[ArgScanDir::]
         WinABI WideCharToMultiByte,CP_UTF8,0,RSI,-1,RDI,264,0,0
         JMP .Ret0
    .S:                     ; Hotkey 'S' pressed.
    .OlderSelectBtnId:      ; Button [Select] older scan file pressed.
         WinABI GetOpenFileNameW,InpFileDlg
         TEST RAX
         JZ .Ret0:
         MOV RSI,[InpFileDlg.lpstrFile]
         LEA RDI,[InputFileNameUTF16::]
         MOV RDX,RDI
    .73: LODSW
         STOSW
         TEST AX
         JNZ .73:
         MOV RSI,RDX
         WinABI SetWindowTextW,[OlderEditHandle],RSI
         LEA RDI,[ArgInputFile::]
         WinABI WideCharToMultiByte,CP_UTF8,0,RSI,-1,RDI,264,0,0
         FileAssign File_scanOlder::,RSI, Unicode=yes
         CALL LoadAndCompareScans::
         CALL RenameButtons
         BufferClear [FindBuffer]
         WinABI SetFocus,[DirWindowHandle]
         WinABI InvalidateRect,[DirWindowHandle],0,-1
         WinABI PostMessage,[DirWindowHandle],WM_COMMAND,Btn2Id,0
         JMP .Ret0
    .E:                     ; Hotkey 'E' pressed.
    .NewerSelectBtnId:      ; Button [Select] newer scan file pressed.
         WinABI GetOpenFileNameW,OutFileDlg
         TEST RAX
         JZ .Ret0:
         MOV RSI,[OutFileDlg.lpstrFile]
         LEA RDI,[OutputFileNameUTF16::]
         MOV RDX,RDI
    .76: LODSW
         STOSW
         TEST AX
         JNZ .76:
         MOV RSI,RDX
         WinABI SetWindowTextW,[NewerEditHandle],RSI
         LEA RDI,[ArgOutputFile::]
         WinABI WideCharToMultiByte,CP_UTF8,0,RSI,-1,RDI,264,0,0
         FileAssign File_scanNewer::,RSI, Unicode=yes
         CALL LoadAndCompareScans::
         CALL RenameButtons
         BufferClear [FindBuffer]
         WinABI InvalidateRect,[DirWindowHandle],0,-1
         WinABI PostMessage,[DirWindowHandle],WM_COMMAND,Btn2Id,0
         JMP .Ret0:
    .ScanDirEditId
    .OlderEditId:
    .NewerEditId
         JMP .Def:
    .VK_ESCAPE:                       ; Terminate program.
    .WM_DESTROY:                      ; Program terminates.
         WinABI PostQuitMessage,0     ; Tell Windows to quit this program with errorlevel 0.
    .Ret0:XOR EAX,EAX                 ; RAX=0 signalizes that the message was processed here.
    .Ret:EndProcedure WndProc

RenameButtons
  This procedure is called when a view has been changed by pressing one of five buttons.
  It changes titles of those five buttons to reflect new selected pair of scan files.
Called by
  WndProc (private calling convention).

    RenameButtons PROC
         LEA RDI,[Dir::]
         Concat$ RDI,=U"Inserted ",Number1W::,=U" new directories (&1)",Size=100, Unicode=yes
         WinABI SetWindowTextW,[Btn1Handle],RDI
         Concat$ RDI,=U"Increased ",Number2W::,=U" directories (&2)",Size=100, Unicode=yes
         WinABI SetWindowTextW,[Btn2Handle],RDI
         Concat$ RDI,=U"Unchanged ",Number3W::,=U" directories (&3)",Size=100, Unicode=yes
         WinABI SetWindowTextW,[Btn3Handle],RDI
         Concat$ RDI,=U"Decreased ",Number4W::,=U" directories (&4)",Size=100, Unicode=yes
         WinABI SetWindowTextW,[Btn4Handle],RDI
         Concat$ RDI,=U"Deleted ",Number5W::,=U" old directories (&5)",Size=100, Unicode=yes
         WinABI SetWindowTextW,[Btn5Handle],RDI
         MOVD [ArgViewDirs::],ArgViewDirsInc
         WinABI SendMessage,[Btn1Handle],BM_SETSTATE,0,0
         WinABI SendMessage,[Btn2Handle],BM_SETSTATE,-1,0
         WinABI SendMessage,[Btn3Handle],BM_SETSTATE,0,0
         WinABI SendMessage,[Btn4Handle],BM_SETSTATE,0,0
         WinABI SendMessage,[Btn5Handle],BM_SETSTATE,0,0
         WinABI InvalidateRect,[DirWindowHandle],0,-1
         RET
        ENDP RenameButtons

WndCreate
  Register window class and create all windows.
Called by
  MainGui

    WndCreate:: PROC
        PUSH RBX,RSI,RDI
        BufferCreate FindBuffer,Size=2M
        MOV [FindBuffer],RAX
        ; Register WndClassEx for the main window.
        MOV [WndClassEx.cbSize],SIZE# WndClassEx
        MOV [WndClassEx.lpszClassName],EuroDirs
        MOV [WndClassEx.style],CS_HREDRAW|CS_VREDRAW
        MOV [WndClassEx.lpfnWndProc],WndProc
        WinABI GetModuleHandle,0
        MOV [WndClassEx.hInstance],RAX
        WinABI LoadIcon,RAX,1             ; The 1st and only icon from [.rsrc] section.
        MOV [WndClassEx.hIcon],RAX
        WinABI GetStockObject,WHITE_BRUSH ; Default window background colour.
        MOV [WndClassEx.hbrBackground],RAX
        WinABI RegisterClassEx, WndClassEx
        ; Create the main window.
        LEA RSI,[EuroDirs::]
        WinABI CreateWindowEx, WS_EX_CLIENTEDGE,        \
               RSI, RSI, WS_OVERLAPPEDWINDOW, \
               CW_USEDEFAULT,CW_USEDEFAULT,1100,600,    \
               0, 0, [WndClassEx.hInstance], 0
        MOV [MainWindowHandle],RAX
       ; Initialize ScanDirExplore dialogue.
        MOV [ScanDirFileDlg.lStructSize],SIZE# OPENFILENAME
        MOV RAX,[MainWindowHandle]
        MOV [ScanDirFileDlg.hwndOwner],RAX
        MOV [ScanDirFileDlg.lpstrTitle],=U"Choose any file and click 'Open'"
        LEA RSI,[ScanDirUTF16::]
        LEA RDI,[ScanDir]
        MOV [ScanDirFileDlg.lpstrFile],RDI
        MOV [ScanDirFileDlg.nMaxFile],260
        MOV [ScanDirFileDlg.lpstrFilter],ScanFilter
    .10:LODSW
        TEST AX
        JZ .20:
        STOSW
        JMP .10:
    .20:MOV AX,'\'
        CMP [RDI-2],AX
        JE .30:
        STOSW
    .30:MOV EAX,'*'
        STOSD
     ; Initialize OlderExplore dialogue.
        MOV [InpFileDlg.lStructSize],SIZE# OPENFILENAME
        MOV RAX,[MainWindowHandle]
        MOV [InpFileDlg.hwndOwner],RAX
        MOV [InpFileDlg.lpstrTitle],=U"Select an older scan"
        LEA RAX,[InputFileNameUTF16::]
        MOV [InpFileDlg.lpstrFile],RAX
        MOV [InpFileDlg.nMaxFile],260
        MOV [InpFileDlg.lpstrFilter],ScanFilter
        MOV [InpFileDlg.Flags],OFN_FILEMUSTEXIST+OFN_PATHMUSTEXIST
     ; Initialize NewerExplore dialogue.
        MOV [OutFileDlg.lStructSize],SIZE# OPENFILENAME
        MOV RAX,[MainWindowHandle]
        MOV [OutFileDlg.hwndOwner],RAX
        MOV [OutFileDlg.lpstrTitle],=U"Select a newer scan"
        LEA RAX,[OutputFileNameUTF16::]
        MOV [OutFileDlg.lpstrFile],RAX
        MOV [OutFileDlg.nMaxFile],260
        MOV [OutFileDlg.lpstrFilter],ScanFilter
        MOV [OutFileDlg.Flags],OFN_FILEMUSTEXIST+OFN_PATHMUSTEXIST
        ; EuroDirs icon.
        WinABI CreateWindowEx,0,="STATIC",="#1",WS_CHILD+WS_VISIBLE+SS_ICON,\
               12,0,16,16,[MainWindowHandle],0,[WndClassEx.hInstance],0
        WinABI SendMessage,RAX,STM_SETICON,[WndClassEx.hIcon],0
       ; Title EuroDirs version.
        WinABI CreateWindowExA,0,=B"STATIC", Version::,\
               WS_CHILD+WS_VISIBLE,50,10,180,20,[MainWindowHandle],0,[WndClassEx.hInstance],0
        ; Title of ScanDirExplore dialogue.
        WinABI CreateWindowExA,0,=B"STATIC", =B"A folder with scan files:",\
               WS_CHILD+WS_VISIBLE,\
               240,10,156,20,[MainWindowHandle],0,[WndClassEx.hInstance],0
        ; Edit field of ScanDirExplore.
        MOV EDX,[WindowWidth]
        SUB EDX,331
        WinABI CreateWindowExW,0,=U'EDIT',ScanDirUTF16::,WS_CHILD+WS_VISIBLE+WS_BORDER, \
               300,10,RDX,20,[MainWindowHandle],ScanDirEditId,[WndClassEx.hInstance],0
        MOV [ScanDirEditHandle],RAX
       ; Output ScanDirExplore button.
        MOV EDX,[WindowWidth]
        SUB EDX,100
        WinABI CreateWindowExA,0,=B'BUTTON',=B"&Browse",WS_CHILD+WS_VISIBLE+BS_DEFPUSHBUTTON,\
               RDX,10,90,20,[MainWindowHandle],ScanDirBrowseId,[WndClassEx.hInstance],0
        MOV [ScanDirBrowseHandle],RAX
        MOV ECX,[WindowWidth]
        SUB ECX,5*10+2*90
        SHR ECX,1
        WinABI CreateWindowExA,0,=B"STATIC",=B" Select an older scan file",WS_CHILD+WS_VISIBLE ,\
              10,40,RCX,20,[MainWindowHandle],0,[WndClassEx.hInstance],0
        MOV [OlderTitleHandle],RAX
        ; Input OlderExplore button.
        MOV EDX,[WindowWidth] ; MainWindows width.
        SUB EDX,5*10+2*90
        SHR EDX,1
        ADD EDX,2*10
        WinABI CreateWindowExA,0,=B'BUTTON',=B"&Select",WS_CHILD+WS_VISIBLE+BS_DEFPUSHBUTTON,\
               RDX,40,90,20,[MainWindowHandle],OlderSelectBtnId,[WndClassEx.hInstance],0
        MOV [OlderSelectBtnHandle],RAX
        ; Title NewerExplore dialogue.
        MOV EDX,[WindowWidth]
        MOV ECX,EDX
        SUB EDX,5*10+2*90
        SHR EDX,1
        MOV ECX,EDX
        ADD EDX,3*10+90
        WinABI CreateWindowExA,0,=B"STATIC",=B" and compare it with a newer scan file",WS_CHILD+WS_VISIBLE ,\
             RDX,40,RCX,20,[MainWindowHandle],0,[WndClassEx.hInstance],0
        MOV [NewerTitleHandle],RAX
       ; Output NewerExplore button.
        MOV EDX,[WindowWidth]
        SUB EDX,10+90
        WinABI CreateWindowExA,0,=B'BUTTON',=B"S&elect",WS_CHILD+WS_VISIBLE+BS_DEFPUSHBUTTON,\
               RDX,40,90,20,[MainWindowHandle],NewerSelectBtnId,[WndClassEx.hInstance],0
        MOV [NewerSelectBtnHandle],RAX
       ; Edit OlderExplore file name.
        MOV ECX,[WindowWidth]
        SUB ECX,3*10
        SHR ECX,1
        WinABI CreateWindowExW,0,=U'EDIT',File_scanOlder.Name::,WS_CHILD+WS_VISIBLE+WS_BORDER+ES_AUTOHSCROLL, \
               10,64,RCX,24,[MainWindowHandle],OlderEditId,[WndClassEx.hInstance],0
        MOV [OlderEditHandle],RAX
        ; Edit NewerExplore file name
        MOV EDX,[WindowWidth]
        SUB EDX,3*10
        SHR EDX,1
        MOV ECX,EDX
        ADD EDX,2*10
        WinABI CreateWindowExW,0,=U'EDIT',File_scanNewer.Name::,WS_CHILD+WS_VISIBLE+WS_BORDER+ES_AUTOHSCROLL, \
               RDX,64,RCX,24,[MainWindowHandle],NewerEditId,[WndClassEx.hInstance],0
        MOV [NewerEditHandle],RAX
        ; Buttons /ViewDirs=
        MOV EAX,[WindowWidth]
        SUB EAX,6*10
        XOR EDX,EDX
        MOV ECX,5
        DIV RCX
        MOV R12,RAX
        LEA RDI,[Dir::]
       ; Output Button1 - Inserted.
        Concat$ RDI,=U"Inserted ",Number1W::,=U" new directories (&1)",Size=100,Unicode=yes
        WinABI CreateWindowExW,0,=U'BUTTON',RDI,WS_CHILD+WS_VISIBLE+BS_PUSHBUTTON+BS_LEFT,\
               10,98,R12,20,[MainWindowHandle],Btn1Id,[WndClassEx.hInstance],0
        MOV [Btn1Handle],RAX
       ; Output Button2 - Incremented.
        Concat$ RDI,=U"Increased ",Number2W::,=U" directories (&2)",Size=100,Unicode=yes
        LEA RDX,[R12+2*10]
        WinABI CreateWindowExW,0,=U'BUTTON',RDI,WS_CHILD+WS_VISIBLE+BS_PUSHBUTTON+BS_LEFT,\
               RDX, 98,R12,20,[MainWindowHandle],Btn2Id,[WndClassEx.hInstance],0
        MOV [Btn2Handle],RAX
       ; Output Button3 - Unchanged.
        Concat$ RDI,=U"Unchanged ",Number3W::,=U" directories (&3)",Size=100,Unicode=yes
        LEA RDX,[R12+R12+3*10]
        WinABI CreateWindowExW,0,=U'BUTTON',RDI,WS_CHILD+WS_VISIBLE+BS_PUSHBUTTON+BS_LEFT,\
               RDX, 98,R12,20,[MainWindowHandle],Btn3Id,[WndClassEx.hInstance],0
        MOV [Btn3Handle],RAX
       ; Output Button4 - Decremented.
        Concat$ RDI,=U"Decreased ",Number4W::,=U" directories (&4)",Size=100,Unicode=yes
        LEA RDX,[R12+2*R12+4*10]
        WinABI CreateWindowExW,0,=U'BUTTON',RDI,WS_CHILD+WS_VISIBLE+BS_PUSHBUTTON+BS_LEFT,\
               RDX, 98,R12,20,[MainWindowHandle],Btn4Id,[WndClassEx.hInstance],0
        MOV [Btn4Handle],RAX
       ; Output Button5 - Deleted.
        Concat$ RDI,=U"Deleted ",Number5W::,=U" old directories (&5)",Size=100,Unicode=yes
        LEA RDX,[4*R12+5*10]
        WinABI CreateWindowExW,0,=U'BUTTON',RDI,WS_CHILD+WS_VISIBLE+BS_PUSHBUTTON+BS_LEFT,\
               RDX, 98,R12,20,[MainWindowHandle],Btn5Id,[WndClassEx.hInstance],0
        MOV [Btn5Handle],RAX
       ; Create Find static text.
        WinABI CreateWindowExA,0,=B"STATIC", =B"Find this text:",WS_CHILD+WS_VISIBLE,\
               10,127,94,20,[MainWindowHandle],0,[WndClassEx.hInstance],0
       ; Create FindText edit window.
        MOV EDX,[WindowWidth]
        SUB EDX,134
        WinABI CreateWindowExW,0,=U'EDIT',0,WS_CHILD+WS_VISIBLE +WS_BORDER, \
               114,127,RDX,20,[MainWindowHandle],FindEditId,[WndClassEx.hInstance],0
        MOV [FindTextHandle],RAX
       ; Create brush for Find window.
       WinABI CreateSolidBrush, ColorFind
       MOV [hBrushFind],RAX
       ; Create DirWindow for displaying of directories.
        MOV EDX,[WindowWidth]
        SUB EDX,22
        MOV ECX,[WindowHeight]
        SUB ECX,168
        LEA RSI,[EuroDirs::]
        WinABI CreateWindowExA, WS_EX_CLIENTEDGE,       \
               RSI, 0, WS_CHILD+WS_VISIBLE+WS_BORDER+WS_VSCROLL, \
               10,158,RDX,RCX,[MainWindowHandle], 0, [WndClassEx.hInstance], 0
        MOV [DirWindowHandle],RAX
        POP RDI,RSI,RBX
        RET
       ENDP WndCreate

WndResize
  Dimensions of the MainWindow changed.
Called from
  WndProc.WM_SIZE.

    WndResize:: PROC
        PUSH RBX,RSI,RDI,R12
        LEA RBX,[MainWindowRect]
        WinABI GetClientRect,[MainWindowHandle],RBX
        MOV ECX,[RBX+RECT.right]
        MOV EAX,[RBX+RECT.bottom]
        MOV [WindowWidth],ECX
        MOV [WindowHeight],EAX
        CMP EAX,190                      ; Minimal height.
        JA .20:
        WinABI GetWindowRect,[MainWindowHandle],RBX
        MOV EDX,[RBX+RECT.left]
        MOV ECX,[RBX+RECT.top]
        MOV EBX,[RBX+RECT.right]
        SUB EBX,EDX
        WinABI MoveWindow,[MainWindowHandle],RDX,RCX,RBX,230,-1
        JMP .80:                         ; Do not let the height of MainWindow drop under 190 px.
    .20:SUB EAX,129                      ; Fixed height of common dialogues and buttons above DirWindow.
        MOV ECX,[TextMetric.tmHeight]
        XOR EDX,EDX
        DIV RCX
        MOV [ClientLines],EAX
        ; Set vertical scroll info.
        DEC EAX,EAX
        MOV [ClientLinesMinus2],EAX
        MOV [ScrollInfo.nPage],EAX
        MOV [ScrollInfo.cbSize],SIZE# SCROLLINFO
        MOV [ScrollInfo.fMask],SIF_RANGE | SIF_PAGE | SIF_POS
        MOV [ScrollInfo.nMin],0
        MOV EAX,[MaxLineNr::]
        MOV [ScrollInfo.nMax],EAX
        MOV EAX,[SelectedLineNr]
        MOV [ScrollInfo.nPos],EAX
        WinABI SetScrollInfo,[DirWindowHandle],SB_VERT,ScrollInfo,-1
        ; ScanDirExplore edit.
        MOV EDX,[WindowWidth]
        SUB EDX,411+  102
        WinABI MoveWindow,[ScanDirEditHandle],400,10,RDX,20,1
        ; ScanDirExplore button.
        MOV EDX,[WindowWidth]
        SUB EDX,90+10
        WinABI MoveWindow,[ScanDirBrowseHandle],RDX,10,90,20,1
        ; Title of OlderExplore dialogue.
        MOV ECX,[WindowWidth]
        SUB ECX,5*10+2*90
        SHR ECX,1
        WinABI MoveWindow,[OlderTitleHandle],10,40,RCX,20,1
        ; Input OlderExplore button.
        MOV EDX,[WindowWidth]
        SUB EDX,5*10+2*90
        SHR EDX,1
        ADD EDX,2*10
        WinABI MoveWindow,[OlderSelectBtnHandle],RDX,40,90,20,1
        ; Title NewerExplore dialogue.
        MOV EDX,[WindowWidth]
        MOV ECX,EDX
        SUB EDX,5*10+2*90
        SHR EDX,1
        MOV ECX,EDX
        ADD EDX,3*10+90
        WinABI MoveWindow,[NewerTitleHandle],RDX,40,RCX,20,1
        ; Output NewerExplore button.
        MOV EDX,[WindowWidth]
        SUB EDX,5*10+2*90
        ADD EDX,4*10+1*90
        WinABI MoveWindow,[NewerSelectBtnHandle],RDX,40,90,20,1
        ; Edit OlderExplore file name.
        MOV ECX,[WindowWidth]
        SUB ECX,3*10
        SHR ECX,1
        WinABI MoveWindow,[OlderEditHandle],10,64,RCX,24,1
        ; Edit NewerExplore file name
        MOV EDX,[WindowWidth]
        SUB EDX,3*10
        SHR EDX,1
        MOV ECX,EDX
        ADD EDX,2*10
        WinABI MoveWindow,[NewerEditHandle],RDX,64,RCX,24,1
       ; Five buttons /ViewDirs=
        MOV EAX,[WindowWidth]
        SUB EAX,6*10
        XOR EDX,EDX
        MOV ECX,5
        DIV RCX
        MOV R12,RAX
        ; Output insButton.
        WinABI MoveWindow,[Btn1Handle],10, 98,R12,20,1
        ; Output incButton.
        LEA RDX,[R12+2*10]
        WinABI MoveWindow,[Btn2Handle],RDX, 98,R12,20,1
        ; Output unchButton.
        LEA RDX,[R12+R12+3*10]
        WinABI MoveWindow,[Btn3Handle],RDX, 98,R12,20,1
        ; Output decButton.
        LEA RDX,[R12+2*R12+4*10]
        WinABI MoveWindow,[Btn4Handle],RDX, 98,R12,20,1
        ; Output delButton.
        LEA RDX,[4*R12+5*10]
        WinABI MoveWindow,[Btn5Handle],RDX, 98,R12,20,1
        ; Find text edit window.
        MOV EDX,[WindowWidth]
        SUB EDX,124
        WinABI MoveWindow,[FindTextHandle],114,127,RDX,20,1
        ; DirWindow.
        MOV EDX,[WindowWidth]
        SUB EDX,22
        MOV ECX,[WindowHeight]
        SUB ECX,128+10+20+9
        WinABI MoveWindow,[DirWindowHandle],10,128+30,RDX,RCX,1
    .80:POP R12,RDI,RSI,RBX
        RET
    ENDP WndResize

WndPaint

  This is a procedure which repaints the client area of DirWindow.

Input
  [BufferSelected] is BUFFER with INDEXes.
  SelectedLineNr is the topmost 0-based line number in client area.
Output
  -
Called by
  WndProc.WM_PAINT

    WndPaint:: PROC
       PUSH RBX,RSI,RDI,R12
        WinABI BeginPaint, [DirWindowHandle], PaintStruct
        MOV [hDirDC],RAX
        WinABI CreateFont,0,0,0,0,0,0,0,0,DEFAULT_CHARSET, \  Create an unproportional font.
               OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DRAFT_QUALITY,FIXED_PITCH|FF_DONTCARE,0
        MOV [FontHandle],RAX
        WinABI SelectObject,[hDirDC],RAX
        WinABI GetTextMetrics,[hDirDC],TextMetric
        BufferRetrieve [BufferSelected::]
        SHR ECX,4
        MOV [MaxLineNr::],ECX
        MOV ECX,[TextMetric.tmHeight]
        MOV EAX,[WindowHeight]
        SUB EAX,129+27
        JNA .90:
        XOR EDX,EDX
        DIV RCX
        MOV [ClientLines],EAX    ; EAX=number of visible lines of text.
        SUB EAX,2
        MOV [ClientLinesMinus2],EAX
        MOV ECX,[TextMetric.tmAveCharWidth]
        MOV EAX,[WindowWidth]
        XOR EDX,EDX
        DIV RCX                  ; EAX=Number of columns per client width. Complete with spaces.
        MOV R12,RAX              ; R12 is the number of chars in client window.
        XOR EAX,EAX
        MOV [ClientY],RAX        ; Start painting with pixel line 0.
        MOV ECX,[ClientLines]
        MOV EBX,[SelectedLineNr] ; EBX specifies the line from the selected buffer (1,2,3,,,MaxLineNr::).
    .20:PUSH RCX                 ; This loop displays [ClientLines] of text in the client area.
          CALL OneLine2Dir::     ; Dir (RSI) is filled with RCX bytes of WIDE text. Or RCX=0 when out of buffer.
          MOV R8,RSI             ; R8 points at the beginning of the line text.
          LEA R9,[RSI+RCX]       ; R9 points at the end of the line text.
          SHR ECX,1              ; Convert bytes to characters.
          MOV EAX,ColorCursor
          CMP EBX,[CursorLineNr]
          JE .25:
          MOV EAX,ColorWhite
    .25:  WinABI SetBkColor,[hDirDC],RAX,Fastmode=no
          MOV R10,R12
          SUB R10,RCX            ; R10 is the required number of spaces.
          JA .30:
          MOV R10,RCX
    .30:  MOV AX,' '
          MOV R11,RCX            ; Temporary save RCX=number of chars in line.
          MOV RCX,R12
          MOV RDI,R9
          REP STOSW
          MOV R9,RDI             ; R9 points now at the end of client columns.
          MOV RCX,R11            ; Restore RCX=number of characters in line.
          MOV EDX,[FindChars]    ; Size of FindText in characters.
    .40:  MOV EAX,10
          MOV RDI,R8
          TEST EDX
          JZ .60:                ; Do not search when the size of FindText is 0.
          CMP EBX,[CursorLineNr]
          JE .60:                ; Do not search when the current line is CursorLineNr.
          LEA R11,[RDX-1]        ; R11 is FindSize-1.
          CMP EDX,ECX
          JA  .60:
          MOV RDI,RSI            ; Start searching here.
          LEA RSI,[FindText]
          LODSW                  ; Load AX with the first character of FoundText.
          XOR EDX,EDX
    .50:  REPNE SCASW
          JNE .40:
          PUSH RCX,RSI,RDI
            MOV RCX,R11
            REPE CMPSW
          POP RDI,RSI,RCX
          JNE .50:                 ; Continue search for the first character.
          MOV EDX,[FindChars]
          ; FindText was found. Display RDI-2-R8 white chars,
          ;   then RDX yellow, then the rest in white again.
          SUB RDI,R8
          SHR EDI,1
          DEC EDI
          WinABI TextOutW,[hDirDC],10,[ClientY],R8,RDI,Fastmode=No
          WinABI SetBkColor,[hDirDC],ColorFind,Fastmode=no
          LEA RSI,[R8+2*RDI]
          MOV EAX,[TextMetric.tmAveCharWidth]
          MUL RDI
          ADD EAX,10
          MOV EDX,[FindChars]
          LEA RDI,[RSI+2*RDX]
          WinABI TextOutW,[hDirDC],RAX,[ClientY],RSI,RDX,Fastmode=No
          WinABI SetBkColor,[hDirDC],0x00FFFFFF
          MOV EAX,[TextMetric.tmAveCharWidth]
          MOV RCX,RDI
          SUB RCX,R8
          SHR ECX,1
          MUL RCX
          ADD EAX,10
    .60:  SUB R9,RDI
          SHR R9,1
          WinABI TextOutW,[hDirDC],RAX,[ClientY],RDI,R9,Fastmode=No
        POP RCX
        MOV EAX,[TextMetric.tmHeight]
        ADD [ClientY],RAX
        INC EBX                  ; Next line.
        DEC ECX
        JNZ .20:
    .90:WinABI DeleteObject,[FontHandle]
        WinABI EndPaint,  [DirWindowHandle], PaintStruct
        CALL PaintMarks
       POP R12,RDI,RSI,RBX
       RET
      ENDP WndPaint

FindToBuffer

  For each line from BufferSelected it will store FIND_INDEX record to FindBuffer.

Input
  [BufferSelected] is BUFFER with INDEXes.
  SelectedLineNr is the topmost 0-based line number in client area.
Output
  -
Calls
  OneLine2Dir::.
Called by
  WndProc.WM_PAINT

    FindToBuffer PROC
        BufferClear [FindBuffer]
        JC .90:
        CMPD [FindChars],0
        JZ .90:
        SUB EBX,EBX
    .10:INC EBX
        CALL OneLine2Dir::  ; RSI=Dir is filled with RCX bytes of WIDE text. Or RCX=0 when out of buffer.
        JRCXZ .90:
        MOV R8,RSI
        MOV RDI,RSI
        LEA RSI,[FindText]
        XOR EAX,EAX
        LODSW
        SHR ECX,1
    .20:REPNE SCASW          ; Search for the first UNICHAR of the FindText string in Dir.
        JNE .10:
        PUSH RCX,RSI,RDI
          MOV ECX,[FindChars]
          DEC ECX
          CMP ESI,EDI   ; Set ZF=0.
          REPE CMPSW
        POP RDI,RSI,RCX
        JNE .20:
        MOV [FindIndex.LineNr],EBX  ; FindText was found in this line.
        SUB RDI,2
        SUB RDI,R8
        MOV [FindIndex.Offset],EDI
        BufferStore [FindBuffer],FindIndex,SIZE# FIND_INDEX
        JMP .10:        ; Read the next line.
    .90:RET
       ENDP FindToBuffer

PaintMarks

  Paint little yellow marks on the right side of the main window.
  It relies on BufferFind filled by FindToBuffer.

Called by
  WndProc.WM_PAINT

    PaintMarks PROC
        WinABI BeginPaint,[MainWindowHandle],PaintStruct
        MOV [hMainDC],RAX
        LEA RDI,[MainWindowRect]
        WinABI GetClientRect,[MainWindowHandle],RDI
        LEA RSI,[DirWindowRect]
        WinABI GetClientRect,[DirWindowHandle],RSI
        MOV EAX,[RDI+RECT.right]
        SUB EAX,[RSI+RECT.right]
        CMP EAX,30                 ; 40 if vertical scrollbar exists, 24 otherwise.
        JNA .80:                   ; Do not paint marks when the scrollbar is not visible.
        BufferRetrieve [FindBuffer]
        JNA .80:
        PUSH RCX
         WinABI CreatePen,PS_SOLID,3,ColorFind
         MOV [PenHandle],RAX
         WinABI SelectObject,[hMainDC],RAX
         MOV EDI,[DirWindowRect.bottom]
         SUB EDI,2*17
        POP RCX
        SHR ECX,3
    .20:PUSH RCX
         MOV EAX,[RSI+FIND_INDEX.LineNr]
         MUL RDI
         MOV ECX,[MaxLineNr::]
         DIV RCX  ; RAX is now vertical coordinate of the mark, related to DirWindowRect.top.
         LEA EBX,[EAX+175]
         MOV ECX,[DirWindowRect.right]
         ADD ECX,35
         WinABI MoveToEx,[hMainDC],RCX,RBX,0
         ADD ECX,5
         WinABI LineTo,[hMainDC],RCX,RBX
         ADD RSI,SIZE# FIND_INDEX
        POP RCX
        DEC ECX
        JNZ .20:
        WinABI DeleteObject,[PenHandle]
    .80:WinABI EndPaint,[MainWindowHandle],PaintStruct
        RET
        ENDP PaintMarks

      ENDPROGRAM dirswing

▲Back to the top▲