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
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:: 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
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.
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 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:: 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:: 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
This is a procedure which repaints the client area of DirWindow.
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
For each line from BufferSelected it will store FIND_INDEX record to FindBuffer.
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
Paint little yellow marks on the right side of the main window.
It relies on BufferFind filled by FindToBuffer.
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