EuroAssembler Index Manual Download Source Macros


Sitemap Links Forum Tests Projects

viewwing.htm
Data
Data
Procedures
CreateLstIndex
FileIndexReopen
FileWriteOutput
Main
ReadFileIni
SaveViewIndex
ViewEpilogue
ViewPrologue
WndCreateMain
WndFont
WndPaintMain
WndProcMain
WndResizeMain
WndTitle

This is a module of EuroTool program EuroView for Windows.


     EUROASM CPU=X64,SIMD=Yes, Unicode=No, MaxInclusions=128
viewwing PROGRAM Format=COFF, Width=64 ,MaxExpansions=128K
     %DROPMACRO *
     INCLUDEHEAD argument.htm, viewmain.htm
     INCLUDE1 winabi.htm,winsgui.htm,winsdlg.htm,winsfile.htm,winf64.htm, \
              cpuext64.htm,cpuext.htm,status32.htm,memory64.htm,string64.htm,fastcall.htm,
     LINK winapi.lib
     PUBLIC BufferCreate@RT
Data
                 ; Constants.
OptimalWidth     = 640
MinimalWidth     = 500
MinimalHeight    = 440
FontSizeMax      = 48
FontSizeDef      = 16  ; Standard font height to begin with.
FontSizeMin      = 10
CtrlStep         =  5  ; Cursor keys move the screen by 1, or by CtrlStep characters when Ctrl is pressed.
WheelPerLine     = 120 ; wParamHigh = 120 or -120 to scroll 1 row up or down.
ColorDump        = 0x00D0D0D0 ; Dump.
ColorRem         = 0x00D0FFFF ; Remark.
Color1           = 0x00D0FFD0 ; Level 1.
Color2           = 0x0030FFFF ; Level 2.
Color3           = 0x00D0D0FF ; Level 3.
Color4           = 0x00FFD0D0 ; Level 4.
TopLine          = ScrollInfo.nPos   ; Ordinal of the listing line displayed in the top row of the window.
Rows             = ScrollInfo.nPage  ; Number of rows in the current window.
Lines            = ScrollInfo.nMax   ; Number of physical lines in listing.
[.rodata]        ; Constant texts.
Help:
 DB 13,10
 DB "EuroView version %^DATE",13,10,10
 DB " Use to inspect binary, object, library",10
 DB "   or executable ""InputFile"":",9,9,"euroview.exe ""InputFile""",13,10,10
 DB " It also accepts arguments from the command-line:",13,10
 DB 9,"/InputFile=       ",9,9,"Input file name to be inspected.",13,10
 DB 9,"/FileFormat=      ",9,9,"Default is Autodetect. /FF=? for the list of accepted formats.",13,10
 DB 9,"/OutputFile=      ",9,9,"Temporary file; default is ""%%TEMP%%\InputFile.lst"".",13,10
 DB 9,"/LeaveTemporary=no",  9,"Do not erase OutputFile when EuroView terminates.",13,10,10
 DB " Accepted file formats:",13,10
 %i %SETA 1
 %WHILE "%FileFormats{%i}"
 DB 9,"%FileFormats{%i+0}"
 DB 9," %FileFormats{%i+1}"
 DB 9," %FileFormats{%i+2}"
 DB 9," %FileFormats{%i+3}"
 DB 9," %FileFormats{%i+4}"
 DB 9," %FileFormats{%i+5}"
 %i %SETA %i+6
 DB 13,10
 %ENDWHILE
EndHelp:
 DB 13,10," Keys:",13,10
 DB 9,"F1  ",9,9,9,"this help",10
 DB 9,"O   ",9,9,9,"open another file",10
 DB 9,"Shift Tab | Right button",9," increase nesting level (more compact)",10
 DB 9,"Tab | Left button",9,9,"decrease nesting level (more detailed)",10
 DB 9,"Ctrl + ",9,9,9,"increase font size",10
 DB 9,"Ctrl - ",9,9,9,"decrease font size",10
 DB 9,"Ctrl 0 ",9,9,9,"default font size",10
 DB 9,"Home   ",9,9,9,"beginning of the document",10
 DB 9,"End    ",9,9,9,"end of the document",10
 DB 9,"PgUp | PgDn ",9,9,"page up | down",10
 DB 9,"Up | Dn | Mouse scroll",9,"line up | down",10
 DB 9,"Esc",9,9,9,"close window",10
 DB 0
FormatNames:
FF %FOR %FileFormats
     DB "%FF",0
   %ENDFOR FF
EndFormatNames:
[.bss]           ; Variable data.
Msg              DS MSG          ; Window message.
WndClassEx       DS WNDCLASSEX   ; Window class structure.
InpFileDlg       DS OPENFILENAME
PaintStruct      DS PAINTSTRUCT
RectMainWindow   DS RECT
TextMetric       DS TEXTMETRICA
ScrollInfo       DS SCROLLINFO
LstIndex:        DS LST_INDEX
FileIni          DS FILE64
FileInput        DS FILE64
FileOutput::     DS FILE64
FileIndex        DS FILE64
hWindowMain      D QWORD         ; Window handles.
hWindowHelp      D QWORD
hFont            D QWORD
hDC              D QWORD         ; Handle of device context.
cxWindow         D QWORD         ; Horizontal coordinate in px.
cyWindow         D QWORD         ; Vertical coordinate in px.
WindowWidth      D DWORD         ; Client area width  in px.
WindowHeight     D DWORD         ; Client area height in px.
cxChar           D DWORD         ; Width  of one character in px.
cyChar           D DWORD         ; Height of one character in px.
FontSize         D DWORD         ; Height of font in px.
Cols             D DWORD         ; Number of cols in current window.
WheelCnt         D DWORD         ; Accumulated WheelPerLine value when mouse wheel is rolled.
Level            D DWORD         ; What level of headers to display (0..4).
LevelPrevious    D DWORD
Spaces           D 800 * B
NameUTF16::      D 800 * UNICHAR ; Temporary working space for file names in UTF-16.
NameUTF8::       D 800 * BYTE    ; Temporary working space for file names in UTF-8.
[.text]          ; Program code.
Main
Program entry in console subsystem.
Main:: PROC
    StdOutput EuroView::, Version::, Eol=yes
    ; Try to load arguments from the configuration file "%AppData%\eurotool\euroview.ini".
    WinABI GetEnvironmentVariableW,=U'AppData',NameUTF16,SIZE# NameUTF16
    TEST RAX
    JZ .10:
    LEA RBX,[FileIni]
    FileAssign RBX,NameUTF16,=U'\eurotool\euroview.ini',Unicode=yes
    FileExists? RBX
    JC .10:
    CALL ReadFileIni                   ; Read arguments from the configuration file.
.10:; Read arguments from the command-line.
    MOV EAX,[ArgNr::]
    INC EAX                  ; The next argument.
    MOV [ArgNr::],EAX
    GetArg RAX, Unicode=yes  ; RSI,RCX gets the line with one argument in UTF-16.
    JC .40:                  ; When they are no more arguments.
    SHR ECX,1                ;  Size in bytes.
    LEA RDI,[NameUTF8]
    WinABI WideCharToMultiByte,65001,0,RSI,RCX,RDI,SIZE#NameUTF8/2,0,0 ; Convert to UTF-8 in NameUTF8.
    MOVB [RDI+RAX],0
    MOV RSI,RDI
    GetLength$ RSI
    CALL ArgParse::          ; Use ArgParse to translate UTF-8 string RSI,RCX to a public symbol Arg***.
    JNC .10:                 ; Parse the next argument when no error.
    LEA RSI,[ErrorMessage::] ; Error in arguments.
    GetLengthUTF8 RSI
    WinABI MultiByteToWideChar,65001,0,RSI,RCX,NameUTF16,MAX_PATH_SIZE
    StdOutput NameUTF16,Console=yes,Unicode=yes
    JSt [Status::],ArgEnc?|ArgLoc?|ArgFF?,.30:
    LEA RCX,[EndHelp::]
    LEA RAX,[Help:]
    SUB RCX,RAX
    StdOutput Help, Size=RCX, Unicode=no                 ; On error write help and terminate.
.30:TerminateProgram 8
.40:; All arguments are accepted..
    BufferCreate Size=256K                               ; Create five level buffers.
    JC ErrorAlloc
    MOV [Level0Buffer::],RAX
lvl %FOR 1..4
      BufferCreate Size=64K
      JC ErrorAlloc:
      MOV [Level%lvl{}Buffer::],RAX
    %ENDFOR
    LEA RAX,[FileIndexReopen:]
    MOV [FileIndexReopenProc::],RAX
    LEA RAX,[FileWriteOutput:]
    MOV [FileWriteOutputProc::],RAX
    MOVD [Level],0
    MOVD [TopLine],1
    CMPB [ArgInputFile::],0
    JZ .50:                 ; Skip when no file was specified on the command line.
    CALL ViewPrologue:      ; Read the ArgInputFile, prepare output files.
    JC ErrorFileInput:      ; If error, InputFile not found etc.
    CALL ViewCreate::       ; Generate FileIndex and write FileOutput.
    CALL ViewEpilogue:
.50:CALL WndCreateMain
    CALL WndResizeMain
    CMPB [ArgInputFile::],0
    JNZ .60:
    WinABI PostMessage,[hWindowMain],WM_KEYDOWN,VK_F1,0 ; Display Help when no file specified.
.60:WinABI ShowWindow,[hWindowMain],SW_SHOW
    WinABI UpdateWindow,[hWindowMain]
    CALL WndTitle
.MsgLoop:
     WinABI GetMessage, Msg,0,0,0
     TEST RAX
     JZ .MsgQuit:                                 ; ZF signalizes message WM_QUIT - request for termination.
     WinABI TranslateMessage, Msg                 ; Remap character keys from national keyboards.
     WinABI DispatchMessage,  Msg                 ; Let Windows call our WndProc.
     JMP .MsgLoop:                                ; Wait for another message.
ErrorHelp::
     StdOutput Help:,Eol=yes
     JMP .90:
ErrorFileOutput:
     LEA RSI,[FileOutput.Name]
     JMP ErrorFile:
ErrorFileInput:
     LEA RSI,[FileInput.Name]
     JMP ErrorFile:
ErrorFileIndex:
     LEA RSI,[FileOutput.Name]
ErrorFile:
     StdOutput =U'Error in file "',RSI,=U'"',Eol=yes,Unicode=yes,Console=yes
     JMP .MsgQuit:
ErrorAlloc::
     StdOutput =B"Error on memory allocation.",Eol=yes
.MsgQuit:
     BufferDestroy [Level0Buffer::],[Level1Buffer::],[Level2Buffer::],[Level3Buffer::],[Level4Buffer::]
     FileClose FileInput, FileOutput, FileIndex
     JSt [Status::],ArgLeaveTemporary,.90:
     FileDelete FileOutput, FileIndex
.90: TerminateProgram 0
   ENDP Main
ViewPrologue
Windows function which will read ArgInputFile, memory-map it to InputPtr..InputEnd, then create files FileOutput and FileIndex with filenames ArgOutputFile (if not empty) or %TEMP%\ArgInputFileName.lst, %TEMP%\ArgInputFileName.lst.index (if ArgOutputFile= is empty).
Input
ArgInputFile, ArgOutputFile, ArgFileFormat
Output
CF=0, ArgOutputFile, ArgFileFormat (detected), FileOutput, FileIndex.
Error
CF=1 when ArgInputFile is empty or unable to read.
ViewPrologue: PROC
    LEA RSI,[ArgInputFile::]           ; Memory-map FileInput.
    CMPB [RSI],0
    STC
    JE .90:
    FileClose FileInput, FileIndex, FileOutput
    JSt [Status::],ArgLeaveTemporary, .10:
    FileDelete FileIndex, FileOutput   ; Delete temporary file from previous run.
.10:LEA RDI,[NameUTF16]
    WinABI MultiByteToWideChar,65001,0,RSI,-1,RDI,SIZE# NameUTF16/2
    LEA RBX,[FileInput]
    FileAssign RBX, RDI, Unicode=yes
    FileMapOpen RBX
    JC .90:
    MOV [InputPtr::],RSI
    MOV [InputSize::],RAX
    LEA RDX,[RSI+RAX]
    MOV [InputEnd::],RDX
    BSR ECX,EAX
    MOV EDX,4
    ADD ECX,EDX
    SHR ECX,2
    CMP ECX,EDX                        ; Number of address digits (4..8) in listing.
    JA .20:
    MOV ECX,EDX
.20:MOV [AddressDigits::],ECX
    MOV EDX,[ArgFileFormat::]          ; Find file format.
    TEST EDX
    JNZ .30:
    CALL AutodetectFileFormat::
    MOV [FormatProcPtr::],RAX          ; FormatELF32, FormatBIN etc.
    MOV [ArgFileFormat::],ECX          ; Ordinal format number.
.30: MOV EDX,[ArgFileFormat::]          ; Set by AutodetectFormat or by cmd-line argument.
    LEA RDI,[FormatNames:]
    MOV ECX,EndFormatNames-FormatNames
    XOR EAX,EAX
.45:DEC EDX
    JZ .40:
    REPNE SCASB
    JMP .45:
.40:MOV [FormatNamePtr::],RDI
    LEA RDI,[NameUTF16]                ; Create output and index files.
    LEA RSI,[ArgOutputFile::]
    WinABI MultiByteToWideChar,65001,0,RSI,RCX,RDI,SIZE# NameUTF16 /2
    CMPW [RDI],0
    JNZ .80:                           ; When ArgFileOutput is not empty, use it as is.
    ; If ArgOutputFile is not specified (default), use %TEMP% and filename without path for temporary names.
    WinABI GetEnvironmentVariableW, =U"Temp", RDI, SIZE# NameUTF16
    SAL EAX,1                          ; Size in characters.
    ADD RDI,RAX
    MOV AX,'\'
    CMP [RDI-2],AX
    JE .50:
    STOSW
.50:LEA RSI,[FileInput.Name]
    MOV EAX,[FileInput.NameOffs]
    ADD RSI,RAX                        ; Use the plain filename without path.
.60:LODSW
    CMP AX,0
    JE .70:
    STOSW
    JMP .60:
.70:LEA RSI,[=U".lst"]
    MOV ECX,4+1
    REP MOVSW
    LEA RDI,[NameUTF16]
.80:FileAssign FileOutput, RDI, Unicode=yes
    FileCreate FileOutput
    JC .90:
    LEA RDX,[FileOutput.Name]
    FileAssign FileIndex, RDX, =U".index", Unicode=yes
    FileCreate FileIndex
.90:RET
   ENDP ViewPrologue
ViewEpilogue
Windows function which will convert indexes written to FileIndex to listing lines and store the lines to FileOutput. Then it will close FileInput and FileIndex, reopen FileOutput, memory-map it to OutputPtr..OutputEnd, sort it, store indexes of listing lines to LevelnBuffer.
Input
OutputPtr..OutputEnd
Output
CF=0LevelnBuffer (n=0..4)
Error
CF=1
ViewEpilogue: PROC
     FileClose FileOutput, FileIndex
     FileMapOpen FileOutput
     JC ErrorFileOutput
     MOV [OutputPtr::],RSI
     MOV [OutputSize::],RAX
     ADD RAX,RSI
     MOV [OutputEnd::],RAX
     FileMapOpen FileIndex
     JC ErrorFileIndex
     MOV [IndexPtr::],RSI
     ADD RAX,RSI
     MOV [IndexEnd::],RAX
     CALL CreateLstIndex::   ; Toss the index to five memory buffers for levels 0..4.
     MOVD [Level],0
     MOVD [TopLine],1
     RET
  ENDP ViewEpilogue
FileIndexReopen
OS dependent proxy function.
FileIndexReopen: PROC
    LEA RBX,[FileIndex]
    FileClose RBX
    FileMapCreate RBX                ; Reopen and sort FileIndex. Returns the contents in RDI,RAX.
    JC ErrorFileIndex:
    RET
  ENDP FileIndexReopen:
FileWriteOutput
OS dependent proxy function.
FileWriteOutput: PROC
    FileWrite FileOutput,RSI,RCX
    JC ErrorFileOutput:
    RET
  ENDP FileWriteOutput:
WndCreateMain
Register window class and create the main window.
Called by
Main.
WndCreateMain: PROC
    MOV EAX,'    '
    LEA RDI,[Spaces]
    MOV ECX,SIZE# Spaces / 4
    REP STOSD
    ; Register WndClassEx for the main window.
    MOVD [WndClassEx.cbSize],SIZE# WndClassEx
    LEA RSI,[EuroView::]
    MOVQ [WndClassEx.lpszClassName],RSI
    MOVD [WndClassEx.style],CS_HREDRAW|CS_VREDRAW
    MOVQ [WndClassEx.lpfnWndProc],WndProcMain
    WinABI GetModuleHandle,0
    MOVQ [WndClassEx.hInstance],RAX
    WinABI LoadIcon,RAX,1             ; The 1st and only icon from [.rsrc] section.
    MOVQ [WndClassEx.hIcon],RAX
    WinABI LoadCursor,0,IDC_ARROW
    MOVQ [WndClassEx.hCursor],RAX
    MOVQ [WndClassEx.hbrBackground],COLOR_BTNFACE+1
    WinABI RegisterClassExA, WndClassEx

    ; Create the main window.
    WinABI CreateWindowExA,0,                                         \
           RSI,RSI,WS_OVERLAPPEDWINDOW|WS_VSCROLL,                    \
           CW_USEDEFAULT,CW_USEDEFAULT,OptimalWidth*2,MinimalHeight*2,\
           0, 0, [WndClassEx.hInstance], 0
    MOV [hWindowMain],RAX
    MOV RBX,RAX
    MOV [ScrollInfo.cbSize], SIZE# SCROLLINFO
    MOV [ScrollInfo.fMask], SIF_RANGE | SIF_PAGE
    MOV [ScrollInfo.nMin],1
    WinABI SetScrollInfo, RBX,SB_VERT,ScrollInfo,1
    MOV [FontSize], FontSizeDef
    CALL WndFont

    ; Initialize InpFileDlg.
    MOV [InpFileDlg.lStructSize],SIZE# OPENFILENAME
    MOV RAX,[WndClassEx.hInstance]
    MOV RDX,[hWindowMain]
    LEA RDI,[NameUTF16:]
    MOVW [RDI],0
    MOV [InpFileDlg.hInstance],RAX
    MOV [InpFileDlg.hwndOwner],RDX
    MOV [InpFileDlg.lpstrFile],RDI
    MOV [InpFileDlg.nMaxFile],SIZE# NameUTF16 /2
    SetSt [InpFileDlg.Flags],OFN_FILEMUSTEXIST+OFN_HIDEREADONLY

    LEA RCX,[Help:]           ; Create Help window but don't show it yet.
    WinABI CreateWindowExA,WS_EX_OVERLAPPEDWINDOW  + WS_EX_TOPMOST + WS_EX_TRANSPARENT,  \
           =B"STATIC",RCX, WS_CHILD, \
           40,80,640,520, \
           [hWindowMain], 0, [WndClassEx.hInstance], 0
    MOV [hWindowHelp],RAX
    RET
   ENDP WndCreateMain
WndProcMain, 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 WndProcMain to their handlers.
Unhandled messages are passed to DefWindowProc.

Window hWindowMain displays the lines from listing (output file). In this example we have window height 5 Rows, file length 10 Lines and Level 0. In Level 1..4 only lines with those number of # are selected.
Handler input
RCX=[%hWnd] is the main window handle (the same as static [hWindowMain].
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.
WndProcMain Procedure hWnd, uMsg, wParam, lParam ; These parameters are provided in RCX,RDX,R8,R9.
    Uses RBX,RBP,RSI,RDI ; It's only necessary if some of callee-save registers was used in this fastcalled procedure.
    SaveToShadow
    MOV RBX,RCX
    MOV RAX,RDX
    MOV RSI,R8
    MOV RDI,R9 ; Preload msg attributes for handler's convenience.
    ; Fork message uMsg=RAX to its handler using macro Dispatch:
     MOV RSI,R8
     Dispatch EDX, WM_VSCROLL,WM_LBUTTONUP,WM_RBUTTONUP,WM_PAINT,WM_SIZE,WM_MOUSEWHEEL,WM_KEYDOWN,WM_DESTROY
.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:.
     ; Here are two helper subprocedures for keyboard and scrollbox event handlers:
.GetCtrl2ECX: PROC  ; Returns RCX=1 when Ctrl is pressed, otherwise RCX=0. RAX,RDX clobbered.
     WinABI GetKeyState,VK_CONTROL ; Returns bit 15 of RAX set when Ctrl was pressed.
     XOR ECX,ECX
     SAL AX,1      ; Shift MSbit to CF.
     RCL ECX,1     ; Virtual key handlers receive RCX=1 when Ctrl was pressed, otherwise RCX=0.
     RET
    ENDP .GetCtrl2ECX:
.GetShift2ECX: PROC ; Returns RCX=1 when Shift is pressed, otherwise RCX=0. RAX,RDX clobbered.
     WinABI GetAsyncKeyState,VK_SHIFT, Lib=user32.dll  ; Returns bit 15 of RAX set when Shift was pressed.
     XOR ECX,ECX
     SAL AX,1      ; Shift MSbit to CF.
     RCL ECX,1     ; Virtual key handlers receive RCX=1 when Shift was pressed, otherwise RCX=0.
     RET
    ENDP .GetShift2ECX:
.ScrollVer: PROC   ; Scroll vertically until TopLine=ESI.
     TEST ESI      ; Saturate proposed TopLine=ESI to the acceptable range 1..Lines.
     JS .v1:
     CMP ESI,1
     JAE .v2:
 .v1:MOV ESI,1
 .v2:CMP ESI,[Lines]
     JB .v5:
     MOV ESI,[Lines]
 .v5:MOV [TopLine],ESI
     WinABI SetScrollPos,[hWindowMain],SB_VERT,RSI,1
     WinABI InvalidateRect,[hWindowMain],0,0
     RET
    ENDP .ScrollVer:

    ; Handle messages for the main window:
.WM_PAINT:
     CALL WndPaintMain
     JMP .Ret0:
.WM_SIZE:
     CALL WndResizeMain
     JMP .Def:
.VK_TAB:                     ; Tab pressed.
     CALL .GetShift2ECX
     JRCXZ .WM_LBUTTONUP:
.WM_RBUTTONUP:               ; Increase level.
     MOV EAX,[Level]
     CMP EAX,4
     JAE .Ret0:
     INC EAX
     JMPS .LB:
.WM_LBUTTONUP:               ; Decrease level.
     MOV EAX,[Level]
     TEST EAX
     JZ .Ret0:
     DEC EAX
 .LB:MOV [Level],EAX
     CALL WndTitle:
     WinABI InvalidateRect,[hWindowMain],0,0
     JMP .Ret0:
.WM_MOUSEWHEEL:              ; Rolled.
     SAR ESI,16              ; RSI is now +40 or -40 on mouse-wheel roll.
     ADD [WheelCnt],ESI      ; Accumulate scroll requests.
     MOV EDI,[WheelCnt]
 .RollUp:
     CMP EDI,WheelPerLine
     JL  .RollDown:
     SUB EDI,WheelPerLine
     MOV [WheelCnt],EDI
     WinABI SendMessage,RBX,WM_VSCROLL,SB_LINEUP,0
     JMP .RollUp:
 .RollDown:
     CMP EDI,0
     JGE .Ret0:
     ADD EDI,WheelPerLine
     MOV [WheelCnt],EDI
     WinABI SendMessage,RBX,WM_VSCROLL,SB_LINEDOWN,0
     JMP .RollDown:
.WM_VSCROLL:                 ; User scrolled the window vertically.
     CALL .GetCtrl2ECX
     MOV EAX,0x0000_FFFF
     AND EAX,ESI             ; EAX is now scroll box action (clicked on the scrollbox).
     SHR ESI,16              ; ESI is now scroll box position.
     Dispatch EAX,SB_LINEUP,SB_LINEDOWN,SB_PAGEUP,SB_PAGEDOWN,SB_THUMBTRACK
     JMP .Def:
.WM_KEYDOWN:                 ; Non-character hot key ESI=R8D=wParam was pressed.
     CALL .GetCtrl2ECX       ; Test if [Ctrl] was pressed. Set RCX=0 when not pressed.
     Dispatch ESI,VK_UP,VK_DOWN,VK_PRIOR,VK_NEXT,VK_HOME,VK_END,VK_TAB, \
              VK_NUMPAD0,VK_ADD,VK_SUBTRACT,'O',VK_ESCAPE
     CMP ESI,VK_F1
     JB .Def:
     CMP ESI,VK_F12
     JNA .VK_F1:
     JMP .Def:               ; Pass unhandled keys to WinABI DefWindowProc.
.SB_LINEDOWN:                ; Vertical scrollbox line down.
.VK_DOWN:                    ; Down arrow.
     MOV ESI,[TopLine]
     INC ESI
     JRCXZ .SB_THUMBTRACK:   ; If Ctrl is not pressed.
     ADD ESI,CtrlStep
     JMP .SB_THUMBTRACK:
.SB_LINEUP:                  ; Vertical scrollbox line up.
.VK_UP:                      ; Up arrow.
     MOV ESI,[TopLine]
     DEC ESI
     JRCXZ .SB_THUMBTRACK:   ; If Ctrl is not pressed.
     SUB ESI,CtrlStep
     JMP .SB_THUMBTRACK:
.SB_THUMBTRACK:              ; User dragged the tumbtrack to the position ESI.
     CALL .ScrollVer:
     JMP .Ret0:
.SB_PAGEUP:                  ; Vertical scrollbox page up.
.VK_PRIOR:
     MOV ESI,[TopLine]
     SUB ESI,[Rows]
     INC ESI,ESI
     JRCXZ .SB_THUMBTRACK:   ; If Ctrl is not pressed.
     SUB ESI,[Rows]
     SUB ESI,[Rows]
     SUB ESI,[Rows]
     JMP .SB_THUMBTRACK:
.VK_HOME:
     MOV ESI,1
     JMP .SB_THUMBTRACK:
.SB_PAGEDOWN:                ; Vertical scrollbox page down.
.VK_NEXT:
     MOV ESI,[TopLine]
     ADD ESI,[Rows]
     DEC ESI,ESI
     JRCXZ .SB_THUMBTRACK:   ; If Ctrl is not pressed.
     ADD ESI,[Rows]
     ADD ESI,[Rows]
     ADD ESI,[Rows]
     JMP .SB_THUMBTRACK:
.VK_END:
     MOV ESI,[Lines]
     JMP .SB_THUMBTRACK:
.VK_NUMPAD0:                 ; Ctrl 0 restore font size.
     MOV EDI,FontSizeDef
.SetFontEDI:
     MOV [FontSize],EDI
     CALL WndFont            ; Get new [cxChar],[cyChar].
     CALL WndResizeMain      ; Recalculate Rows, Cols.
     JMP .Ret0:
.VK_ADD:                     ; Ctrl + increase font size.
     MOV EDI,[FontSize]
     INC EDI
     CMP EDI,FontSizeMax
     JG .Ret0:
     JMP .SetFontEDI:
.VK_SUBTRACT:                ; Ctrl - decrease font size.
     MOV EDI,[FontSize]
     DEC EDI
     CMP EDI,FontSizeMin
     JL .Ret0:
     JMP .SetFontEDI:
.O:  MOV RDI,[InpFileDlg.lpstrFile]
     MOVW [RDI],0
     WinABI GetOpenFileNameW, InpFileDlg  ; Open another input file.
     TEST RAX
     JZ .Ret0:               ; If cancelled in the common dialogue or other error.
     LEA RSI,[NameUTF16]     ; InputFile selected from the common dialogue.
     GetLength$ RSI, Unicode=yes
     TEST ECX
     JZ .Ret0:               ; If nothing selected.
     MOVD [ArgFileFormat::],0 ; Start with Autodetect file format.
     LEA RDI,[ArgInputFile::]
     WinABI WideCharToMultiByte,65001,0,RSI,RCX,RDI,SIZE#NameUTF8/2,0,0 ; Convert to UTF-8 in ArgInputFile.
     CALL ViewPrologue:      ; Read the input file, prepare output files.
     JC .Ret0:               ; If error, InputFile not found etc.
     CALL ViewCreate::       ; Generate FileIndex and write FileOutput.
     CALL ViewEpilogue:
     CALL WndTitle:
     WinABI InvalidateRect,[hWindowMain],0,0
     JMP .Ret0:

.VK_F1:                                ; Show help window.
     WinABI IsWindowVisible,[hWindowHelp]
     TEST RAX
     JNZ .Ret0:                        ; Ignore F1 when it is visible.
     WinABI ShowWindow, [hWindowHelp], SW_SHOW
     JMP .Ret0:
.VK_ESCAPE:                  ; Terminate window or program.
     WinABI IsWindowVisible,[hWindowHelp]
     TEST RAX
     JZ .WM_DESTROY:
     WinABI ShowWindow, [hWindowHelp], SW_HIDE
     JMP .Ret0:
.WM_DESTROY:                 ; Program terminates.
     WinABI DeleteObject,[hFont]
     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 WndProcMain
WndResizeMain
Dimensions of the MainWindow changed.
Output
[cxChar, cyChar, Rows, Cols
Called from
WndProcMain.WM_SIZE.
WndResizeMain: PROC
    LEA RBX,[RectMainWindow]
    WinABI GetWindowRect,[hWindowMain],RBX
    MOV ESI,[RBX+RECT.left]
    MOV ECX,[RBX+RECT.right]
    SUB ECX,ESI
    CMP ECX,MinimalWidth
    JA .10:
    MOV ECX,MinimalWidth
.10:MOV [WindowWidth],ECX
    MOV EDI,[RBX+RECT.top]
    MOV EDX,[RBX+RECT.bottom]
    SUB EDX,EDI
    CMP EDX,MinimalHeight
    JA .20:
    MOV EDX,MinimalHeight
.20:MOV [WindowHeight],EDX
    WinABI MoveWindow,[hWindowMain],RSI,RDI,RCX,RDX,-1
    MOV EAX,[WindowWidth]
    XOR EDX,EDX
    MOV ECX,[cxChar]
    TEST ECX
    JZ .90:
    DIV RCX
    MOV [Cols],EAX                     ; Number of columns visible in window.
    MOV EAX,[WindowHeight]
    XOR EDX,EDX
    MOV ECX,[cyChar]
    JRCXZ .90:
    DIV RCX
    MOV [Rows],EAX                     ; Number of rows visible in window.
    WinABI SetScrollInfo,[hWindowMain],SB_VERT,ScrollInfo,1
    WinABI InvalidateRect,[hWindowMain],0,1
.90:RET
ENDP WndResizeMain
WndPaintMain
Display lines of the listing file mapped between [OutputPtr]..[OutputEnd].
Indexes (LST_INDEX) are in LevelXBuffers.
View of lines on the monitor are manipulated with cursor keys by changing the variable TopLine.
|#### line 1 |## line 2 | line 3 Level = 0 ┌──────────────┐ │| line 4 │row 1 TopLine = 4 │| line 5 │row 2 │|## line 6 │row 3 │| line 7 │row 4 │| line 8 │row 5 Rows on screen = 5 └──────────────┘ | line 9 | line 10 Lines of listing = 10
[TopLine]
is saturated to the range 1..Lines-Rows+1.
Called from
WndProcMain.WM_PAINT.
WndPaintMain: PROC
    XOR EAX,EAX
    MOV [cxWindow],RAX
    MOV [cyWindow],RAX
    WinABI BeginPaint, [hWindowMain], PaintStruct
    MOV [hDC],RAX
    WinABI SelectObject, RAX, [hFont]
.10:MOV R12,[OutputPtr::]
    TEST R12
    JZ .90:
    MOV EAX,[Level]                    ; 0..4
    MOV EDX,[LevelPrevious]
    CMP EAX,EDX
    MOV [LevelPrevious],EAX
    JE .50:
    JB .35:
    ; Level is increasing from EDX to EAX. Calculate the new value of TopLine.
    ADD R12,RAX
    BufferRetrieve [Level0Buffer::+8*RDX] ; RSI,RCX are old LST_INDEX records.
    XOR EDX,EDX
    MOV EDI,[TopLine]
.15:DEC EDI
    JZ .20:
    LODSD
    CMPB [R12+RAX],'#'                 ; Is the line in new level?
    LODSD
    JNE .15:
    INC EDX
    JMP .15:
.20:TEST EDX
    JNZ .25:
    INC EDX
.25:CMP EDX,[TopLine]
    JB  .30:
    INC EDX
.30:MOV [TopLine],EDX
    JMP .10:
.35:; Level is decreasing from EDX to EAX. Calculate the new value of TopLine.
    ADD R12,RDX
    BufferRetrieve [Level0Buffer::+8*RAX] ; RSI,RCX are new LST_INDEX records.
    SHR ECX,3
    JZ .90:
    XOR EDI,EDI                        ; Line counter in new buffer.
    MOV EDX,[TopLine]
.40:INC EDI
    LODSD
    CMPB [R12+RAX],'#'
    LODSD
    JNE .40:
    DEC EDX
    JNZ .40:
    MOV [TopLine],EDI
    JMP .10:
.50:; Level EAX is unchanged.
    BufferRetrieve [Level0Buffer::+8*RAX] ; RSI,RCX are LST_INDEX records.
    SHR ECX,3                          ; SIZE# LST_INDEX = 8
    MOV [Lines],ECX
    MOV EDI,[TopLine]
    CMP EDI,[Lines]
    JBE .55:
    MOV EDI,[Lines]
.55:MOV [TopLine],EDI
    WinABI SetScrollInfo,[hWindowMain],SB_VERT,ScrollInfo,-1
    SUB RSI,SIZE# LST_INDEX
    XOR EDX,EDX
.60:INC EDX                            ; Line number 1,2,3,,,Lines.
    ADD RSI,SIZE# LST_INDEX
    CMP EDX,EDI                        ; Reached TopLine?
    JB .60:
    MOV R14D,[Rows]                    ; Number of rows on screen.
    CMP EDX,[Lines]                    ; Reached the end of lines?
    JA .80:
    MOV R15D,[AddressDigits::]
    ADD R15D,38                        ; R15 is the number of gray characters in dump, including address and |.
.65:; Display lines indexed by RSI until EDX>[Lines] (out of lines) or until R14=0 (all rows displayed).
    LODSD                              ; LST_INDEX.FA
    LEA RBX,[R12+RAX]                  ; RBX is pointer to the line in mapped listing.
    LODSD                              ; LST_INDEX.Size
    MOV ECX,EAX
    MOV EDX,[cxChar]
    MUL RDX
    MOV R13,RAX                        ; R13=cxWindow at the start of spaces.
    MOV EDI,[Cols]                     ; Columns in the window.
    SUB EDI,ECX                        ; EDI is the number of spaces after the listing line.
    MOV EAX,Color4
    CMPD [RBX+1],'####'
    JE .70:
    MOV EAX,Color3
    CMPB [RBX+3],'#'
    JE .70
    MOV EAX,Color2
    CMPW [RBX+1],'##'
    JE .70:
    MOV EAX,Color1
    CMPB [RBX+1],'#'
    JE .70:
    ; Current line is dump line Level0 , 38+AddressDigits chars wide, plus Remark.
    PUSH RCX                           ; Number of characters in this listing line.
     WinABI SetBkColor,[hDC],ColorDump ; Level0
     WinABI TextOutA,[hDC],[cxWindow],[cyWindow],RBX,R15
     WinABI SetBkColor,[hDC],ColorRem
     ADD RBX,R15                       ; Add the width of the dump column.
     MOV EAX,[cxChar]                  ; Width of one character.
     MUL R15                           ; Let RAX=width of already displayed characters.
    POP RCX
    SUB RCX,R15                        ; Subtract the number of already displayed characters.
    JNA .75:
    WinABI TextOutA,[hDC],RAX,[cyWindow],RBX,RCX ; Print the remark.
    JMP .75:
.70:WinABI SetBkColor,[hDC],RAX        ; LevelX.
    WinABI TextOutA,[hDC],[cxWindow],[cyWindow],RBX,RCX
.75:WinABI TextOutA,[hDC],R13,[cyWindow],Spaces,RDI   ; Display EDI spaces on the same line.
    MOV EAX,[cyChar]
    ADD [cyWindow],EAX
    DEC R14
    JNZ .65:
.80:TEST R14,R14
    JZ .90:
    DEC R14
    WinABI TextOutA,[hDC],[cxWindow],[cyWindow],Spaces,[Cols]  ; Display spaces on the entire line.
    MOV EAX,[cyChar]
    ADD [cyWindow],EAX
    JMP .80:
.90:WinABI EndPaint, [hWindowMain], PaintStruct
    RET
   ENDP WndPaintMain:
WndFont
Release current font [hFont] (if exists) and create a new unproportional ANSI font with [FontSize].
Input
[FontSize] is required line height in pixels.
Output
[hFont],[cxChar],[cyChar]
Called by
WndCreateMain
WndFont: PROC
    MOV RCX,[hFont]
    JRCXZ .10:
    WinABI DeleteObject,RCX,Lib=gdi32.dll
.10:WinABI CreateFontW, [FontSize], 0, 0, 0, FW_DONTCARE, 0, 0, 0, ANSI_CHARSET, \
           OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DRAFT_QUALITY,              \
           FIXED_PITCH | FF_SWISS, 0
    MOV [hFont],RAX
    MOV RBX,[hWindowMain]
    WinABI GetDC,RBX
    MOV RDI,RAX              ; Device context,
    WinABI SelectObject,RDI,[hFont]
    WinABI GetTextMetrics,RDI,TextMetric
    WinABI ReleaseDC,RBX,RDI
    MOV EAX,[TextMetric.tmHeight]
    MOV ECX,[TextMetric.tmAveCharWidth]
    ADD EAX,[TextMetric.tmExternalLeading]
    MOV [cxChar],ECX
    MOV [cyChar],EAX
    RET
  ENDP WndFont:
WndTitle
This procedure will update title of the main window in UTF16 to NameUTF16.
Title is updated when input file, format or level changes.
The new title is constructed in NameUTF8.
Input
FormatNamePtr::, Level, FileInput.Name
Output
NameUTF16
WndTitle PROC
    LEA RDI,[NameUTF8]
    LEA RSI,[EuroView::]
    MOV ECX,8
    REP MOVSB
    MOV AX,' "'
    STOSW
    LEA RSI,[ArgInputFile::]
    TEST RSI
    JZ .40:
.30:LODSB
    CMP AL,0
    JE .40:
    STOSB
    JMP .30:
.40:MOV AL,'"'
    STOSB
    MOV EAX,' as '
    STOSD
    MOV RSI,[FormatNamePtr::]
    TEST RSI
    JZ .60:
.50:LODSB
    CMP AL,0
    JE .60:
    STOSB
    JMP .50:
.60:LEA RSI,[=B' level ']
    MOV CL,7
    REP MOVSB
    MOV AX,'0'
    OR AL,[Level]
    STOSW
    MOV RCX,RDI
    LEA RSI,[NameUTF8]
    SUB RCX,RSI
    LEA RDI,[NameUTF16]
    WinABI MultiByteToWideChar,65001,0,RSI,RCX,RDI,SIZE# NameUTF16 /2
    WinABI SetWindowTextW,[hWindowMain],RDI
    RET
  ENDP WndTitle
SaveViewIndex
Global Window procedure SaveViewIndex is called from analyzing and formating procedures in the OS-independet module viewmain.htm.
It will store the external variable ViewIndex:: to FileIndex, keep its .Size, add .Size to .FA, clear .Level and .Rem in this vairable.
Input
RBX=pointer to VIEW_INDEX variable, usually to ViewIndex::.
FileIndex is a created file.
Output
RAX=0.
RBX= is kept as a pointer to VIEW_INDEX variable.
[RBX+VIEW_INDEX.FA] is incremented by the previous [RBX+VIEW_INDEX.Size] when .Level=0.
[RBX+VIEW_INDEX.Size] is kept, but .Level bits are cleared.
[RBX+VIEW_INDEX.Rem] is cleared.
Clobbers
RAX
SaveViewIndex:: PROC
    PUSH RCX
     FileWrite FileIndex, RBX, SIZE# VIEW_INDEX
     MOV EAX,[RBX+VIEW_INDEX.Size]
     MOV ECX,EAX
     AND EAX,0x0FFF_FFFF
     MOV [RBX+VIEW_INDEX.Size],EAX      ; Keep .Size unchanged for the next element.
     SHR ECX,28                         ; Isolate level.
     JNZ .50:
     ADD [RBX+VIEW_INDEX.FA],EAX        ; Add previous .Size to this .FA, but keep .FA unchanged when .Level >0.
.50: XOR EAX,EAX
     MOV [RBX+VIEW_INDEX.Rem],RAX       ; Always clear .Rem field.
    POP RCX
    RET
   ENDP SaveViewIndex::
ReadFileIni
Procedure ReadFileIni reads lines from FileIni in UTF-8 and parses its each line into configuration variables Arg*** in UTF-8, too.
The FileIni.Name is in UTF-16. Procedure writes information about the file name and whether it was found on standard output.
Called by
Main.
Input
FileIni is assigned with the name.
Clobbers
RAX,RCX,RDX,RSI,RDI
ReadFileIni:: PROC
    SetSt [Status::],ArgFromFile       ; Tell ArgParse that arguments may not begin with / or -.
    StdOutput =U'Configuration "',FileIni.Name,Console=yes,Unicode=yes
.10:FileStreamOpen FileIni,BufSize=4K
    JNC .20:
    StdOutput =U'" was not found.',Eol=yes,Console=yes,Unicode=yes
    JMP .90:
.20:FileStreamReadLn FileIni
    JBE .80:
    MOV ECX,EAX
    ; The first line may begin with BOM.
    MOV AX,[RSI]
    CMPW AX,0xBBEF   ; UTF-8 BOM?
    JNE .50:
    ADD RSI,3        ; Skip the BOM.
    SUB ECX,3
    JB .80:
    JMP .50:
.30:FileStreamReadLn FileIni
    JBE .80:
    MOV ECX,EAX
.50:CALL ArgParse::
    JNC .30:
    StdOutput Help:,Unicode=no
    TerminateProgram 8
.80:FileClose FileIni
    StdOutput =U'" was accepted.',Eol=yes,Console=yes,Unicode=yes
.90:RstSt [Status::],ArgFromFile
    RET
  ENDP ReadFileIni
CreateLstIndex
This procedure will clear BUFFERs for each level (0..4) and then it will index the listing file (OutputPtr..OutputEnd) into those buffers.
Buffers contain records in the form of LST_INDEX.
Input
OutputPtr..OutputEnd is the listing mapped in memory.
Output
CF=0, LstIndex is an empty variable of LST_INDEX structure which was saved to buffers.
ListingLines is filled with the total number of lines in the listing.
Error
CF=1 allocation error.
CreateLstIndex: PROC
    BufferClear [Level0Buffer::],[Level1Buffer::],[Level2Buffer::],[Level3Buffer::],[Level4Buffer::]
    MOV RBX,[OutputPtr::]              ; Start of the listing in memory.
    XOR ECX,ECX
    MOV AL,10
    DEC RCX
    MOV RDX,RBX
.10:MOV RDI,RDX
    CMP RDI,[OutputEnd::]
    JNB .80:
    MOV RSI,RDI
    REPNE SCASB                        ; Find the end of line.
    MOV RDX,RDI
    SUB RDI,RSI                        ; Size.
    SUB RSI,RBX                        ; FA.
    SUB EDI,2                          ; Omit CR+LF.
    MOV [LstIndex.FA],ESI
    MOV [LstIndex.Size],EDI
    BufferStore [Level0Buffer::],LstIndex,SIZE# LstIndex
    JC ErrorAlloc::
    CMPB [RBX+RSI+1],'#'               ; Is the line in Level1?
    JNE .10:
    BufferStore [Level1Buffer::],LstIndex,SIZE# LstIndex
    JC ErrorAlloc::
    CMPW [RBX+RSI+1],'##'              ; Is the line in Level2?
    JNE .10:
    BufferStore [Level2Buffer::],LstIndex,SIZE# LstIndex
    CMPB [RBX+RSI+3],'#'               ; Is the line in Level3?
    JNE .10:
    BufferStore [Level3Buffer::],LstIndex,SIZE# LstIndex
    CMPD [RBX+RSI+1],'####'            ; Is the line in Level4?
    JNE .10:
    BufferStore [Level4Buffer::],LstIndex,SIZE# LstIndex
    JMP .10:
.80:BufferRetrieve [Level0Buffer::]
    SHR ECX,3                          ; SIZE# LstIndex = 8
    MOV [ListingLines::],ECX
    CLC
    RET
   ENDP CreateLstIndex
  ENDPROGRAM viewwing

▲Back to the top▲