EuroAssembler Index Manual Download Source Macros


Sitemap Links Forum Tests Projects

lstview4.htm
Header
LstCreate
LstDestroy
LstIndex
LstSelect
WinMain
WndCreate
WndFont
WndModify
WndPaint
WndProc
WndSize
WndTitle
WndTitleLoc
WndTitleUpdate

Listing Viewer is a sample program for Windows which uses Graphic User Interface (GUI).

It displays the listing file produced by EuroAssembler and enhances its divisions (dump, source, messages) with different background colours.

The viewed file name may be provided by several methods:

Listing viewer can be assembled in ANSI and WIDE version by changing the option EUROASM Unicode= specified in header . No other intervention is necessary and both version work the same way. This should demonstrate EuroAssembler's ability to select ANSI|WIDE variant of string macros, string definitions and WinABI invocations depending on UNICODE= option.
Nevertheless, the viewed listing file is always assumed in UTF-8 encoding only.


Format
PE 64bit FLAT GUI
Platform
MS Windows 64bit.
See also
lstview.htm for the 32bit variant.
Import-library build
If you don't have the import library ..\objlib\winapi.lib yet,
compile in prowin32 subdirectory with command euroasm dll2lib.htm.
Build
euroasm lstview4.htm
Run
lstview4.exe "Source.htm.lst" or associate the program with *.lst files and doubleclick on the listing file in Explorer.
         EUROASM CPU=X64, SIMD=SSE1, AMD=Yes, Unicode=Yes
lstview4 PROGRAM Format=PE, Subsystem=GUI, Width=64, Entry=WinMain, IconFile="easm.ico"
          LINK winapi.lib   ; MS Windows import library.
          INCLUDE winabi.htm, wins.htm, winsgui.htm, winscon.htm,      \
                  winsfile.htm, winsdlg.htm, winsreg.htm, winssec.htm, \
                  fastcall.htm, cpuext.htm, cpuext64.htm, string64.htm
WinMain

This is the main program entry procedure.
Command line argument specifies a listing file to view.
Listing is expected in UTF-8 encoding.
When no valid file was provided, the viewer will show HelpText instead, which is also expected in UTF-8 | plain ASCII.

User can also use standard OpenFile dialog [Ctrl~O] or drag the file icon to the viewer window.

Input
-
Output
-
Invoked by
MS Windows loader
[.data]
HelpTitle DB "LstView keys:",0
HelpText  DB " ",10,10,           \ Top padding lines.
"   LstView4 - EuroAssembler listing viewer ",10,10, \
"Help - this overview          [Ctrl~H] or [F1]",10, \
"Open a listing file           [Ctrl~O] or [F3]",10, \
"Associate *.lst with this viewer          [F4]",10, \
"Modify optimal window size    [Ctrl~M] or [F5]",10, \
"Restore default font size     [Ctrl~0] or [F6]",10, \
"Decrease font size            [Ctrl~-] or [F7]",10, \
"Increase font size            [Ctrl~+] or [F8]",10, \
"Skip to the previous message [Shift~Tab] [F11]",10, \
"Skip to the next message           [Tab] [F12]",10, \
"Move in row | columns steps           [arrows]",10, \
"Move in page steps        [PgUp|PgDn|Home|End]",10, \
"Accelerate the movement                 [Ctrl]",10, \
"Quit the viewer              [Ctrl~Q] or [Esc]",10, \
                          10, 0 ; Bottom padding lines.
NotFoundText DB "Error reading the specified file.",0
ErrorText    D  "Memory allocation error.",0
[.bss]
Msg         D MSG                     ; Window message.
LstFileName D MAX_PATH_SIZE * UNICHAR ; Name of the selected listing file.
[.text]
WinMain PROC
     Clear SEGMENT# [.bss], Size=SIZE# [.bss] ; Make sure to start with zeroed memory.
     CALL WndCreate     ; Initialize the program window.
     GetArg 1           ; Return the filename argument in RSI,RCX, if provided.
     StripQuotes RSI,RCX; Remove double quotes from filename.
     AND ECX,0x000001FF ; Limit filename size to 255 characters.
     MOV EDI,LstFileName
     REP MOVSB
     CALL LstCreate     ; Load and index the listing file specified on command line.
     CALL WndModify     ; Shrink|expand window to the optimal size.
     WinABI RedrawWindow,[hWindow],0,0,RDW_FRAME | RDW_INTERNALPAINT | RDW_INVALIDATE
.MsgLoop:
     WinABI GetMessage, Msg,0,0,0
     TEST EAX
     JZ .MsgQuit:       ; Message WM_QUIT - terminate program.
     WinABI TranslateMessage, Msg ; Remap character keys from national keyboards.
     WinABI DispatchMessage,  Msg ; Let Windows call our WndProc.
     JMP .MsgLoop:      ; Wait for another message.
.MsgQuit:
     CALL LstDestroy    ; Release allocated dynamic memory.
     TerminateProgram Errorlevel=[Msg.wParam]
  ENDPROC WinMain
WndProc, hWnd, uMsg, wParam, lParam

This is a FastCall convention procedure invoked as callback from WinABI DispatchMessage. It receives and handles messages for the program window.
Involved messages are dispatched to their handlers.
Ignored messages are processed by WinABI DefWindowProc.

Functionality of some message handlers is encapsulated with a call to procedures Wnd***, others are unrolled inline here in WndProc.

Handler Input
RAX=uMsg, RBX=hWnd, RSI=wParam, RDI=lParam.
Handler Output
RAX=0 if the message was completely processed by the handler. Otherwise the message is processed by WinABI DefWindowProc and RAX outputs its return value.
RBX,RCX,RDX,RSI,RDI may be destroyed in the handlers.
Invoked by
WinABI DispatchMessage.
SB_VERT_THUMBTRACK EQU SB_THUMBTRACK
SB_HORZ_THUMBTRACK EQU SB_THUMBTRACK
CtrlStep      EQU 5  ; Cursor keys move the screen by 1, or by CtrlStep characters when Ctrl is pressed.
FontSizeMin   EQU 10 ; Acceptable character-box height in pixels.
FontSizeMax   EQU 48
FontSizeDef   EQU 16 ; Standard font height to begin with.
WheelPerLine  EQU 40 ; wParamHigh = 120 or -120 to scroll 3 rows up or down.
[.bss]
WheelCnt      D D ; Accumulated WheelPerLine value when mouse wheel is rolled.
PseudoCapture D D ; Nonzero while the left mouse button is down.
OldPos        D D ; lParam with mouse client coordinates on left button pressed.
xClientCnt    D D ; Accumulated x-difference in pixels on mouse drag.
yClientCnt    D D ; Accumulated y-difference in pixels on mouse drag.
cxChar        D D ; Glyph box dimensions of one unproportional character in pixels.
cyChar        D D
FontSize      D D ; Height of character glyph box in pixels.
hFont         D Q ; Handle of the used font.
[.text]
WndProc Procedure hWnd, uMsg, wParam, lParam
     Uses RBX,RSI,RDI
     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:
     Dispatch EAX, WM_VSCROLL, WM_HSCROLL,                         \ Scroll events.
        WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_LBUTTONDOWN, WM_LBUTTONUP, \ Mouse events.
        WM_KEYDOWN, WM_CHAR,                                       \ Keyboard events.
        WM_PAINT, WM_DROPFILES, WM_SIZE, WM_CREATE, WM_DESTROY     ; Miscellaneous events.
.Def:WinABI DefWindowProc,[%hWnd],[%uMsg],[%wParam],[%lParam]      ; Other events are ignored.
     JMP .Ret:  ; EndProcedure WndProc with value RAX returned from DefWindowProc.
     ; Message handlers terminate with a jump to .Def: or .Ret0:.
     ; They have Window handle in RBX, wParam and lParam in RSI and RDI.
.WM_CREATE: ; Window is being created by WndCreate.
     WinABI DragAcceptFiles,RBX,1
     JMP .Ret0:
.WM_SIZE:  ; User changed window dimensions.
     CALL WndSize
     JMP .Ret0:
.WM_PAINT: ; Window needs repaint.
     CALL WndPaint
     JMP .Ret0:
.WM_DESTROY: ; Program terminates.
     WinABI DragAcceptFiles,RBX,0 ; Stop accepting dragged files.
     WinABI DeleteObject,[hFont]  ; Free the allocated font memory.
     WinABI PostQuitMessage,0     ; Tell Windows to quit with errorlevel 0.
     JMP .Ret0:
.WM_DROPFILES: ; User dropped a file icon to our window.
     WinABI DragQueryFile,RSI,0,LstFileName,MAX_PATH_SIZE ; Retrieve new LstFileName.
     CALL LstDestroy ; Deallocate previous file.
     CALL LstCreate
     JMP .Ret0:
     ; Mouse event handlers.
.WM_MOUSEWHEEL:  ; Rolled.
     SAR ESI,16  ; RSI is now +120 or -120 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_LBUTTONDOWN:      ; Left mouse button pressed. Window contents will be dragged.
     MOV [PseudoCapture],1
     MOV [OldPos],EDI ; Mouse capture begins.
     CALL WndTitleLoc ; Calculate and show character-coordinates on title bar.
     JMP .Ret0:
.WM_MOUSEMOVE:
     CMP [PseudoCapture],0
     JE .Ret0:
     TEST ESI,MK_LBUTTON
     JNZ .Drag:            ; If mouse button is still pressed, continue drag.
.WM_LBUTTONUP:             ; Window contents was dragged from [OldPos] to the position in lParam=EDI.
     MOV [PseudoCapture],0 ; End of mouse capture.
     CALL WndTitle         ; Stop displaying character-coordinates in window title strip.
 .Drag:
     MOV EAX,0x0000_FFFF   ; Accumulate the difference between [OldPos] and current position EDI.
     MOV ECX,EAX
     AND EAX,EDI
     AND ECX,[OldPos]
     SUB EAX,ECX
     ADD [xClientCnt],EAX
     MOV EAX,EDI
     MOV ECX,[OldPos]
     SHR EAX,16
     SHR ECX,16
     SUB EAX,ECX
     ADD [yClientCnt],EAX
     MOV [OldPos],EDI
     SUB ESI,ESI
 .DragDown:
     CMP [yClientCnt],ESI
     JGE .DragUp:
     MOV EAX,[cyChar]
     ADD [yClientCnt],EAX
     WinABI SendMessage,RBX,WM_VSCROLL,SB_LINEDOWN,0
     JMP .DragDown:
 .DragUp:
     CMP [yClientCnt],ESI
     JLE .DragRight:
     MOV EAX,[cyChar]
     SUB [yClientCnt],EAX
     WinABI SendMessage,RBX,WM_VSCROLL,SB_LINEUP,0
     JMP .DragUp:
 .DragRight:
     CMP [xClientCnt],ESI
     JGE .DragLeft:
     MOV EAX,[cxChar]
     ADD [xClientCnt],EAX
     WinABI SendMessage,RBX,WM_HSCROLL,SB_LINERIGHT,0
     JMP .DragRight:
 .DragLeft:
     CMP [xClientCnt],ESI
     JLE .Ret0:
     MOV EAX,[cxChar]
     SUB [xClientCnt],EAX
     WinABI SendMessage,RBX,WM_HSCROLL,SB_LINELEFT,0
     JMP .DragLeft:
     ; Helper subprocedures for keyboard and scrollbox event handlers.
.GetCtrl2ECX PROC ; Returns RCX=1 when Ctrl is pressed, otherwise RCX=0. RAX,RDX undefined.
     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 undefined.
     WinABI GetAsyncKeyState,VK_SHIFT  ; 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 TopRow=ESI.
     ; Saturate proposed signed TopRow=ESI to the acceptable range 0..MaxRowNr-NrRowsCl.
     TEST ESI
     JNS .v1:
     SUB ESI,ESI
 .v1:MOV EDX,[MaxRowNr]
     SUB EDX,[NrRowsCl]
     JAE .v3:
     SUB EDX,EDX
 .v3:CMP ESI,EDX
     JLE .v5:
     XCHG ESI,EDX
 .v5:MOV [TopRow],ESI
     WinABI SetScrollPos,[hWindow],SB_VERT,RSI,1
     WinABI InvalidateRect,[hWindow],0,0
     RET
    ENDP .ScrollVer:
.ScrollHor: PROC ; Scroll horizontally until LeftCol=ESI.
     ; Saturate proposed signed LeftCol=ESI to the acceptable range 0..MaxLineLen-NrColsCl.
     TEST ESI
     JNS .h1:
     SUB ESI,ESI
 .h1:MOV EDX,[MaxLineLen]
     SUB EDX,[NrColsCl]
     JGE .h3:
     SUB EDX,EDX
 .h3:CMP ESI,EDX
     JLE .h5:
     XCHG ESI,EDX
 .h5:MOV [LeftCol],ESI
     WinABI SetScrollPos,[hWindow],SB_HORZ,RSI,1
     WinABI InvalidateRect,[hWindow],0,0
     RET
    ENDP .ScrollHor:
     ; Scrollbox event handlers.
.WM_VSCROLL: ; User scrolled the window vertically.
     CALL .GetCtrl2ECX
     MOV EAX,0x0000_FFFF
     AND EAX,ESI  ; EAX is now scroll box action.
     SHR ESI,16   ; ESI is now scroll box position.
     Dispatch EAX,SB_LINEUP,SB_LINEDOWN,SB_PAGEUP,SB_PAGEDOWN,SB_VERT_THUMBTRACK
     JMP .Def:
.WM_HSCROLL: ; User scrolled the window horizontally.
     CALL .GetCtrl2ECX
     MOV EAX,0x0000_FFFF
     AND EAX,ESI  ; EAX is now scroll box action.
     SHR ESI,16   ; ESI is now scroll box position.
     Dispatch EAX,SB_LINELEFT,SB_LINERIGHT,SB_PAGELEFT,SB_PAGERIGHT,SB_HORZ_THUMBTRACK
     JMP .Def:
     ; Keyboard event handlers.
.WM_CHAR: ; Character key mapped by WinABI TranslateMessage to wParam=RSI was pressed.
     ADD ESI,0x0000_0040 ; Convert Ctrl~X to 'X'.
     Dispatch ESI,'H','O','M','Q' ; Jump to labels .H:, .O:, .M:, .Q: (Help, OpenFile, ModifySize, Quit).
     JMP .Def:                    ; Pass other character keys.
.WM_KEYDOWN: ; Non-character key RSI=wParam was pressed. Set RCX=0 if [Ctrl] is not pressed.
     CALL .GetCtrl2ECX ; Test if [Ctrl] was pressed.
     Dispatch ESI, VK_UP, VK_DOWN, VK_PRIOR, VK_NEXT, \
                   VK_LEFT, VK_RIGHT, VK_HOME, VK_END,\
                   VK_ADD, VK_SUBTRACT, VK_NUMPAD0,   \
                   VK_ESCAPE, VK_TAB,                 \
                   VK_F1, VK_F3, VK_F4, VK_F5, VK_F6, \
                   VK_F7, VK_F8, VK_F11, VK_F12
     JMP .Def:  ; Pass unhandled keys to WinABI DefWindowProc.
.SB_LINEDOWN: ; Vertical scrollbox line down.
.VK_DOWN:     ; Down arrow.
     MOV ESI,[TopRow]
     INC ESI
     JRCXZ .SB_VERT_THUMBTRACK: ; If Ctrl not pressed.
     ADD ESI,CtrlStep
.SB_VERT_THUMBTRACK: ; User dragged the tumbtrack to the position ESI.
     CALL .ScrollVer:
     JMP .Ret0:
.SB_LINEUP: ; Vertical scrollbox line up.
.VK_UP:     ; Up arrow.
     MOV ESI,[TopRow]
     DEC ESI
     JRCXZ .SB_VERT_THUMBTRACK: ; If Ctrl not pressed.
     SUB ESI,CtrlStep
     JMP .SB_VERT_THUMBTRACK:
.SB_PAGEDOWN: ; Vertical scrollbox page down.
.VK_NEXT:     ; PageDown
     MOV ESI,[TopRow]
     DEC ESI,ESI
     ADD ESI,[NrRowsCl]
     JRCXZ .SB_VERT_THUMBTRACK: ; If Ctrl not pressed.
     MOV ESI,[MaxRowNr] ; Set ESI to maximum on Ctrl-PgDown.
     JMP .SB_VERT_THUMBTRACK:
.SB_PAGEUP: ; Vertical scrollbox page up.
.VK_PRIOR:  ; PageUp
     MOV ESI,[TopRow]
     INC ESI,ESI
     SUB ESI,[NrRowsCl]
     JRCXZ .SB_VERT_THUMBTRACK: ; If Ctrl not pressed.
     SUB ESI,ESI ; Set ESI to minimum on Ctrl-PgUp.
     JMP .SB_VERT_THUMBTRACK:
.SB_LINERIGHT: ; Horizontal scrollbox column right.
.VK_RIGHT:     ; Right arrow.
     MOV ESI,[LeftCol]
     INC ESI
     JRCXZ .SB_HORZ_THUMBTRACK:
     ADD ESI,CtrlStep
.SB_HORZ_THUMBTRACK:
     CALL .ScrollHor:
     JMP .Ret0:
.SB_LINELEFT: ; Horzintal scrollbox column left.
.VK_LEFT:     ; Up arrow.
     MOV ESI,[LeftCol]
     DEC ESI
     JRCXZ .SB_HORZ_THUMBTRACK:
     SUB ESI,CtrlStep
     JMP .SB_HORZ_THUMBTRACK:
.SB_PAGERIGHT: ; Horizontal scrollbox page right.
.VK_END:       ; End
     MOV ESI,[LeftCol]
     DEC ESI,ESI
     ADD ESI,[NrColsCl]
     JRCXZ .SB_HORZ_THUMBTRACK:
     MOV ESI,[MaxLineLen] ; Set ESI to maximum on Ctrl-End.
     JMP .SB_HORZ_THUMBTRACK:
.SB_PAGELEFT: ; Horizontal scrollbox page left.
.VK_HOME:     ; Home
     MOV ESI,[LeftCol]
     INC ESI,ESI
     SUB ESI,[NrColsCl]
     JRCXZ .SB_HORZ_THUMBTRACK:
     SUB ESI,ESI ; Set ESI to minimum on Ctrl-Home.
     JMP .SB_HORZ_THUMBTRACK:
.Q:         ; Ctrl-Q Quit the program.
.VK_ESCAPE: ; Esc
     WinABI SendMessage,RBX,WM_DESTROY,0,0
     JMP .Ret0:
.H:     ; Ctrl-H Display ANSI HelpText.
.VK_F1: ; F1
     WinABI MessageBoxA,RBX,HelpText,HelpTitle,MB_OK|MB_ICONINFORMATION
     JMP .Ret0:
.VK_F4: ; F4 Register association.
     CALL Register
     JMP .Ret0:
.O:     ; Ctrl-O Open dialog for selection of another file.
.VK_F3: ; F3
     CALL LstSelect
     JZ .Ret0: ; If the OpenFile dialog was cancelled with Esc.
.M:     ; Ctrl-M Modify window size.
.VK_F5: ; F5
     CALL LstDestroy ; Deallocate previous file.
     CALL LstCreate  ; Load and index the new listing file.
     JMP .Ret0:
.VK_NUMPAD0: ; Ctrl-0 ; Restore default font size.
.VK_F6:      ; F6
    MOV EDI,FontSizeDef
.SetFontEDI:
    MOV [FontSize],EDI
    CALL WndFont
    WinABI GetClientRect,RBX,ClientRect
    MOV EAX,[ClientRect.bottom]
    SUB EAX,[ClientRect.top]
    MOV EDI,[ClientRect.right]
    SUB EDI,[ClientRect.left]
    SHL EAX,16
    OR EDI,EAX
    CALL WndSize ; Consequence of changed cxChar,cyChar will be recalculation of NrColsCl,NrRowsCl.
    WinABI InvalidateRect,[hWindow],0,0 ; Redraw client area with the new font.
    JMP .Ret0:
.VK_SUBTRACT: ; Ctrl - Decrease font size.
.VK_F7:       ; F7.
    MOV EDI,[FontSize]
    DEC EDI
    CMP EDI,FontSizeMin
    JL .Ret0:
    JMP .SetFontEDI:
.VK_ADD: ; Ctrl + Increase font size
.VK_F8:  ; F6
    MOV EDI,[FontSize]
    INC EDI
    CMP EDI,FontSizeMax
    JG .Ret0:
    JMP .SetFontEDI:
.VK_F11:  ; F11 Previous message.
    MOV ECX,1
    JMP .SkipMsg:
.VK_F12:  ; F12 Next message.
    XOR ECX,ECX
    JMP .SkipMsg:
.VK_TAB:
    CALL .GetShift2ECX
.SkipMsg: ; Scroll window to the next or previous listing message, identified by INDEX.Color.
          ; RCX= 0 or 1 to scroll down or up.
    MOV EAX,[NrRowsCl]
    MOV ESI,[TopRow]
    SHR EAX,1
    ADD EAX,ESI ; RAX is now "cursor" line number (in vertical center of client).
    MOV EDX,SIZE# INDEX
    MUL RDX
    MOV RDI,[IndexBeg]
    ADD RDI,RAX ; EDI now points to the index of "cursor" line.
    MOV EAX,SIZE# INDEX
    SHL ECX,1 ; ECX is now  0 or  2.
    NOT RCX   ; RCX is now -1 or -3.
    ADD RCX,2 ; RCX is now +1 or -1.
    IMUL RCX  ; RAX is now +SIZE#INDEX or -SIZE#INDEX.
.SkipLine:
    ADD RDI,RAX ; The next line (forward or backward).
    ADD RSI,RCX ; The next TopRow (INC or DEC).
    CMP RDI,[IndexBeg]
    JB .ColorInfo:     ; Stop at the top of listing.
    CMP RDI,[IndexEnd]
    JNB .ColorInfo:    ; Stop at the bottom of listing.
    MOV EDX,[RDI+INDEX.Color] ; The €ASM message is identified by its background color.
    Dispatch EDX,ColorErr,ColorWarn,ColorInfo
    JMP .SkipLine:     ; Continue searching when the line is not a message.
 .ColorErr:
 .ColorWarn:
 .ColorInfo: ; Move up or down to the new "cursor" line indexed by ESI.
    CALL .ScrollVer: ; Scroll to the TopRow=ESI.
.Ret0:XOR EAX,EAX
.Ret:EndProcedure WndProc
WndCreate
Program lstview4.exe uses one and only graphical window. Procedure WndCreate creates the window class and window object.
Input
-
Output
-
Called by
WinMain
[.data]
WndClassName D "LSTVIEW",0
[.bss]
WndClassEx   DS WNDCLASSEX ; Definition of the window class structure.
hWindow      D QWORD       ; Handle of the window object.
hPen         D QWORD       ; Handle of the pen.
PaintStruct  DS PAINTSTRUCT
VScrollInfo  DS SCROLLINFO
HScrollInfo  DS SCROLLINFO
cxScreen     D D ; Width (cx*) and height (cy*) of screen objects.
cyScreen     D D ; Screen resolution.
cxClient     D D ; Inner area of the window.
cyClient     D D
cxScroll     D D ; Thicknes of the scrollbar.
cyScroll     D D
cxBorder     D D ; Thicknes of the window border.
cyBorder     D D
cyCaption    D D ; Height of window title bar.
NrRowsCl     EQU VScrollInfo.nPage ; How many characters are visible in the window row.
MaxRowNr     EQU VScrollInfo.nMax  ; How many physical lines are in the listing file.
NrColsCl     EQU HScrollInfo.nPage ; How many rows are visible in the window.
MaxLineLen   EQU HScrollInfo.nMax  ; How many characters are in the longest listing line.
[.text]
WndCreate PROC
    ; Register class LSTVIEW for the main window.
    MOV [WndClassEx.cbSize],SIZE# WNDCLASSEX
    MOV [WndClassEx.lpszClassName],WndClassName
    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 LoadCursor,0,IDC_HAND
    MOV [WndClassEx.hCursor],RAX
    WinABI GetStockObject,WHITE_BRUSH ; Default window background colour.
    MOV [WndClassEx.hbrBackground],RAX
    WinABI GetStockObject,NULL_PEN
    MOV [hPen],RAX
    WinABI RegisterClassEx,WndClassEx
    ; Inquire system metrics.
    WinABI GetSystemMetrics,SM_CXSCREEN
    MOV [cxScreen],EAX
    WinABI GetSystemMetrics,SM_CYSCREEN
    MOV [cyScreen],EAX
    WinABI GetSystemMetrics,SM_CXVSCROLL
    MOV [cxScroll],EAX
    WinABI GetSystemMetrics,SM_CYHSCROLL
    MOV [cyScroll],EAX
    WinABI GetSystemMetrics,SM_CXBORDER
    MOV [cxBorder],EAX
    WinABI GetSystemMetrics,SM_CYBORDER
    MOV [cyBorder],EAX
    WinABI GetSystemMetrics,SM_CYCAPTION
    MOV [cyCaption],EAX
    ; Create the main window.
    WinABI CreateWindowEx, WS_EX_ACCEPTFILES|WS_EX_CLIENTEDGE,      \
           WndClassName, DefTitle, WS_OVERLAPPEDWINDOW,             \
           CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT, \
           0, 0, [WndClassEx.hInstance], 0
    MOV [hWindow],RAX
    MOV RBX,RAX
    MOV [VScrollInfo.cbSize], SIZE# SCROLLINFO
    MOV [VScrollInfo.fMask], SIF_RANGE | SIF_PAGE
    WinABI SetScrollInfo, RBX, SB_VERT,  VScrollInfo, 1
    MOV [HScrollInfo.cbSize], SIZE# SCROLLINFO
    MOV [HScrollInfo.fMask], SIF_RANGE | SIF_PAGE
    WinABI SetScrollInfo, RBX, SB_HORZ, HScrollInfo, 1
    WinABI ShowWindow, RBX, SW_SHOWNORMAL
    WinABI UpdateWindow, RBX
    MOV [FontSize], FontSizeDef
    CALL WndFont
    CALL WndTitle
    RET
   ENDP WndCreate
WndPaint

This is a procedure which repaints the client area with listing contents.

Indexed listing is virtually formated to a character text-rectangle MaxLineLen × MaxRowNr (in LstCreate ), this includes white top&bottom margin rows and left&right margin columns.
Visible part of text-client rectangle NrRowsCl × NrColsCl is manipulated by user interactions which are transformed to changes of LeftCol & TopRow values (in WndProc) and then it is repainted here..

Each listing line consists of five spans 0..4 described by its index:

SpanBackgroundPointerLength in charsRemark
0ColorMrgStuffPtr1Left margin.
1INDEX.ColorINDEX.PtrINDEX.Len1Dump column.
2ColorSrcINDEX.Ptr+2*INDEX.Len1INDEX.Len2 Source column, color changed only when INDEX.length2>0.
3unchangedStuffPtrMaxLineLen-INDEX.Len1-INDEX.Len2 Extends the line to MaxLineLen.
4ColorMrgStuffPtr1Right margin.

Margin spans 0 and 4 are one character (space) wide.
Dump and source span length in characters is specified by INDEX.Len1 and INDEX.Len2.
Stuff length is calculated on the fly and it fills each line with spaces up to the MaxLineLen-1, which was learnt in LstCreate.
Only rows and spans potentionally visible in the client window are being painted.

┌─────────────────────────┐ ┐ ┐ │░░░░░░░░░margin░░░░░░░░░░│ │ │ │░ ░│ ├ │ TopRow │░ virtual text ░│ │ │ │░ ┌───────────────┐ ░│ ┘┐│ │░ │ │ ░│ ││ │░ │ client area │ ░│ ││ │░ │ │ ░│ ├│NrRowsCl │░ │ │ ░│ │├MaxRowNr │░ │ │ ░│ ││ │░ └───────────────┘ ░│ ┘│ │░ ░│ │ │0 1 2 3 4│ │ │░|dump | source stuff ░│ │ │░ ░│ │ │░░░░░░░░░░░░░░░░░░░░░░░░░│ │ └─────────────────────────┘ ┘ └──┬──┘ │ └─────┬─────────┘ └─────────────┬───────────┘ │ │ └MaxLineLen │ └NrColsCl └LeftCol
Input
hWindow, IndexBuffer
Output
hDC
Called by
WndProc.WM_PAINT
[.bss]
hDC       D Q ; Device context handle.
xClient   D D ; Client pixel position of TextOut. 0..[cxClient].
ColClient D D ; Number of characters already painted in client.
TopRow    D D ; Number of listing lines hidden above the top edge of client area (topmost lineNr).
LeftCol   D D ; Number of characters hidden on the left side of client area (leftmost colNr).
[.text]
WndPaint:: PROC
     MOV RSI,[IndexBeg]
     MOV EAX,SIZE# INDEX
     TEST RSI ; If index is not created yet.
     JZ .90:
     MOV EDX,[TopRow]
     MUL RDX     ; MUL by the number of line which is displayed in the 1st client row.
     ADD RSI,RAX ; Index of topmost row.
     CMP RSI,[IndexBeg]
     JB .90:
     WinABI BeginPaint, [hWindow], PaintStruct
     MOV [hDC],RAX
     WinABI SelectObject, RAX, [hFont]
     WinABI SelectObject, [hDC], [hPen]
     SUB EDI,EDI ; Begin to paint rows on client y-coordinate EDI=0.
     MOV ECX,[NrRowsCl]
 .10:CMP RSI,[IndexEnd]
     JNB .50:
     PUSH RCX
       CALL .RowPaint:
     POP RCX
     ADD EDI, [cyChar]    ; Height of character box.
     ADD RSI, SIZE# INDEX ; Index of the next row.
     DEC ECX
     JNZ .10:
 .50:CMP EDI,[cyClient]
     JAE .60:
     WinABI Rectangle,[hDC],0,RDI,[cxClient],[cyClient] ; Erase garbage on the bottom.
 .60:MOV EAX,[xClient]
     CMP EAX,[cxClient]
     JAE .80:
     WinABI Rectangle,[hDC],RAX,0,[cxClient],[cyClient] ; Erase garbage on the right.
 .80:WinABI EndPaint, [hWindow], PaintStruct
 .90:RET
.RowPaint PROC ; Paint one line described by INDEX record RSI at yClient=EDI. RSI,RDI are preserved.
    SUB EBX,EBX
    MOV [xClient],EBX
    MOV [ColClient],EBX
    CMP EBX,[LeftCol]
    JNE .10:
    ; Paint span0 margin.
    WinABI SetBkColor, [hDC], ColorMrg
    INC EBX
    WinABI TextOutW, [hDC], 0, RDI, [StuffPtr], RBX
    MOV EAX,[cxChar]
    ADD [xClient],EAX
.10:MOV [ColClient],EBX ; 0 or 1.
    ; Paint span1 dump.
    WinABI SetBkColor, [hDC], [RSI+INDEX.Color]
    MOV RDX,[RSI+INDEX.Ptr]
    MOV ECX,[RSI+INDEX.Len1]
    MOV EAX,[LeftCol]
    LEA EAX,[RAX+RBX-1]
    SUB ECX,EAX
    JB .15:
    SAL EAX,1
    ADD RDX,RAX
    ADD [ColClient],ECX
    WinABI TextOutW, [hDC], [xClient], RDI, RDX, RCX ; Paint dump span of ECX characters.
    MOV EAX,[cxChar]
    MUL [ColClient]
    MOV [xClient],EAX
    CMP EAX,[cxClient]
    JAE .80:
.15:MOV ECX,[RSI+INDEX.Len2]
    JRCXZ .30:
    ; Paint span2 source.
    WinABI SetBkColor,[hDC],ColorSrc
    MOV EDX,[RSI+INDEX.Len1]
    LEA EBX,[RDX+RDX]
    ADD RBX,[RSI+INDEX.Ptr]
    MOV EAX,[LeftCol]
    INC EDX
    MOV ECX,[RSI+INDEX.Len2]
    SUB RAX,RDX
    JB .20:
    SUB RCX,RAX
    SAL RAX,1
    ADD RBX,RAX
.20:ADD [ColClient],ECX
    WinABI TextOutW, [hDC], [xClient], RDI, RBX, RCX ; Paint source span of ECX characters.
    MOV EAX,[cxChar]
    MUL [ColClient]
    MOV [xClient],EAX
    CMP EAX,[cxClient]
    JAE .80:
.30:; Paint span3 stuff.
    MOV ECX,[MaxLineLen]
    SUB ECX,[RSI+INDEX.Len1]
    SUB ECX,[RSI+INDEX.Len2]
    SUB ECX,2
    JBE .40:
    ADD [ColClient],ECX
    WinABI TextOutW, [hDC], [xClient], RDI, [StuffPtr], RCX ; Paint stuff span of ECX characters.
    MOV EAX,[cxChar]
    MOV EDX,[ColClient]
    MUL RDX
    MOV [xClient],EAX
    CMP EAX,[cxClient]
    JAE .80:
.40: ; Paint span4 margin.
    WinABI SetBkColor, [hDC], ColorMrg
    WinABI TextOutW, [hDC], [xClient], RDI, [StuffPtr], 1   ; Paint right margin space.
.80:RET
    ENDP .RowPaint:
   ENDP WndPaint
WndSize
Resize window and recalculate scroll bars and client dimensions.
Input
EDI=lParam with window-client dimensions.
Output
[cxChar], [cyChar], [cxClient], [cyClient], [NrColsCl], [NrRowsCl]
Called by
WndProc.WM_SIZE
[.text]
WndSize:: PROC
    MOV EAX,0x0000FFFF ; Width is in lower WORD of lParam.
    AND EAX,EDI
    MOV ECX,[cxChar]
    JRCXZ .End:        ; If font is not loaded yet.
    MOV [cxClient],EAX
    CDQ
    DIV ECX
    INC EAX
    MOV [NrColsCl],EAX ; How many characters fits in client width.
    WinABI SetScrollInfo,[hWindow], SB_HORZ, HScrollInfo, 1
    MOV EAX,EDI        ; Client height is in higher WORD of lParam.
    SHR EAX,16
    MOV ECX,[cyChar]
    MOV [cyClient],EAX
    JRCXZ .End:
    CDQ
    DIV ECX
    INC EAX
    MOV [NrRowsCl],EAX ; How many rows fits in client height.
    WinABI SetScrollInfo,[hWindow],SB_VERT, VScrollInfo,1
.End:RET
   ENDP WndSize::
WndModify
Procedure will change window dimension so it will display the whole listing, if possible, but no more than necessary. This is better than going fullscreen.
Input
[MaxLineLen], [MaxRowNr], [cxChar], [cyChar]
Output
Window dimensions are modified.
Called by
WndProc.WM_SIZE, LstCreate.
MarginHor   EQU 64  ; Screen margins of max-modified window in pixels.
MarginVert  EQU 64
[.text]
WndModify PROC
    MOV EAX,[MaxLineLen] ; Calculate maximal useful window width.
    MOV EDX,[cxChar]
    MUL RDX
    ADD EAX,[cxScroll]
    XCHG RBX,RAX ; RBX is now required client width to display whole lines.
    MOV EAX,[cxScreen]
    SUB EAX,2*MarginHor
    CMP RAX,RBX
    JG .xOK:
    XCHG RAX,RBX ; Screen is not wide enough.
.xOK: ; RBX is now the new client width.
    MOV EAX,[MaxRowNr]
    MOV EDX,[cyChar]
    MUL RDX ; RDI is now required client height to display whole listing.
    ADD EAX,[cyScroll]
    XCHG RDI,RAX
    MOV EAX,[cyScreen]
    SUB EAX,2*MarginVert
    CMP RAX,RDI
    JG .yOK:
    XCHG RAX,RDI ; Screen is not high enough.
.yOK: ; RDI is now the new client height.
    MOV [cxClient],EBX
    MOV [cyClient],EDI
    MOV EAX,[cxBorder]
    ADD EBX,EAX
    ADD EBX,EAX
    ADD EDI,[cyBorder]
    ADD EDI,[cyCaption]
    WinABI MoveWindow, [hWindow], MarginHor, MarginVert, RBX, RDI, 1
    RET
   ENDP WndModify
WndTitleLoc
Prepare character-coordinates of mouse cursor and show them in window caption.
Title contains "LstFileName"{rowNr}[colNr].
When LstFileName is empty, title contains LstView - €ASM listing viewer.
Input
RDI=lParam with yClient&xClient coordinates in high&low words.
[hWindow], LstFileName
Output
Window title is updated. Register are not saved.
Called by
WndProc.WM_LBUTTONDOWN
Calls
WndTitle
[.bss]
LocA D 16*B ; ANSI format.
  %IF %^UNICODE
LocW D 16*U ; WIDE format.
  %ENDIF
[.text]
WndTitleLoc PROC
    MOV EBX,0x0000_FFFF
    MOV ECX,EDI
    AND EBX,EDI   ; xClient.
    MOV RDI,LocA
    MOV AL,'{'
    STOSB
    XCHG ECX,EAX
    SHR EAX,16 ; yClient.
    CDQ
    DIV [cyChar]
    ADD EAX,[TopRow]
    StoD RDI
    MOV AX,'}['
    STOSW
    MOV EAX,EBX
    CDQ
    DIV [cxChar]
    ADD EAX,[LeftCol]
    StoD RDI
    MOV AX,']'
    STOSW
    %IF %^UNICODE  ; Convert ANSI string produced by StoD to WIDE string.
      MOV RSI,LocA
      MOV RDI,LocW
      SUB EAX,EAX
  .50:LODSB
      STOSW
      TEST EAX
      JNZ .50:
    %ENDIF
   CALL WndTitleUpdate
   RET
  ENDP WndTitleLoc
WndTitle
Show window title without character-coordinates.
Title contains "LstFileName".
When LstFileName is empty, title contains LstView - €ASM listing viewer.
Input
hWindow, LstFileName
Output
Window title is updated. Registers are not saved.
Called by
WndProc.WM_LBUTTONUP
Calls
WndTitle
[.text]
WndTitle PROC
    %IF %^UNICODE
      MOVW [LocW],0
    %ELSE
      MOVB [LocA],0
    %ENDIF
    CALL WndTitleUpdate
    RET
   ENDP WndTitle
WndTitleUpdate
Update and show window title caption with LstFileName and optional character coordinates.
Title contains file name "LstFileName"{rowNr}[colNr] or "LstFileName".
When LstFileName is empty, title contains LstView - €ASM listing viewer.
The character defined in ANSI version of string DefTitle is in ANSI codepage and therefore it is misinterpreted in browser.
Input
hWindow, LstFileName, LocA|LocW
Output
Window title is updated. Registers are not saved.
Called by
WndTitleLoc, WndTitle
[.data]
  %IF %^UNICODE ; DefTitle contains non-ASCII character, CODEPAGE is required.
    EUROASM CODEPAGE=UTF-8
    DefTitle DU " LstView - €ASM listing viewer",0
  %ELSE
    EUROASM CODEPAGE=WINDOWS-1252
    DefTitle DB " LstView - €ASM listing viewer",0
  %ENDIF
[.bss]
Title D MAX_PATH_SIZE + 16 * U
[.text]
WndTitleUpdate PROC
    %IF %^UNICODE
      MOV RBX,LocW
    %ELSE
      MOV RBX,LocA
    %ENDIF
    CMPB [LstFileName],0
    JNZ .NoFile:
    Concat$ Title,DefTitle
    JMP .ShowTitle:
.NoFile:
    Concat$ Title,='"', LstFileName, ='"', RBX, DefTitle
.ShowTitle:
    WinABI SetWindowText,[hWindow],Title
    RET
   ENDP WndTitleUpdate
LstSelect

Display standard OpenFileName dialogue for selection of the listing file to view.

Input
-
Output
ZF=0, LstFileName was selected.
Error
ZF=1, LstFileName is empty if the dialogue was cancelled.
Called by
WinMain, WndProc.VK_F3
[.data]
OpenFilter  D "Listing files *.lst",0,"*.lst",0, "All files *.*",0,"*.*",0,0
[.bss]
OpenDialog  DS OPENFILENAME ; Standard Windows open-file dialogue.
[.text]
LstSelect PROC
    MOV [LstFileName],0
    MOV [OpenDialog.lStructSize],SIZE# OPENFILENAME
    MOV [OpenDialog.lpstrFilter],OpenFilter
    MOV [OpenDialog.lpstrFile],LstFileName
    MOV [OpenDialog.nMaxFile],SIZE# LstFileName
    MOV [OpenDialog.Flags],OFN_FILEMUSTEXIST
    WinABI GetOpenFileName,OpenDialog
    TEST RAX
    RET
   ENDP LstSelect
LstCreate

LstCreate maps the file to memory, reserves dynamic heap memory for its Wide copy and its Index and creates Index array.

Listing file specified with LstFileName is open, recoded from UTF-8 to UTF-16 (Wide), each physical line is parsed and creates one index record, stored to Index array.

Input
LstFileName
Output
[IndexBeg]..[IndexEnd], [MaxLineLen], [MaxRowNr].
See also
LstDestroy
Called by
WinMain WndProc.WM_DROPFILES
Invokes
LstIndex
[.bss]
LstVarBeg: ; Memory up to LstVarEnd: is cleared in LstDestroy before a new file is loaded.
hFile       D QWORD ; Handle of listing file.
hMap        D QWORD ; Handle of file mapping.
StuffPtr    D QWORD ; Pointer to one line of WIDE spaces on heap.
TxtBeg      D QWORD ; Pointer to the displayed text.
TxtSize     D QWORD ; Size of displayed text in bytes.
LstBeg      D QWORD ; Pointer to the start of memory-mapped listing file (UTF-8).
LstEnd      D QWORD ; Pointer beyond the end of listing file.
LstSize     D QWORD ; Size of listing file in bytes.
WideBeg     D QWORD ; Pointer to the start of WIDE copy of listing on heap (UTF-16).
WidePtr     D QWORD ; Pointer inside WideBuffer.
WideEnd     D QWORD ; Pointer which limits the end of WideBuffer.
IndexBeg    D QWORD ; Pointer to the start of array with INDEX records on heap.
IndexPtr    D QWORD ; Pointer to the next unused INDEX record.
IndexEnd    D QWORD ; Pointer which limits the end of INDEX array.
LstVarEnd:
[.text]
LstCreate PROC
    CALL WndTitle
    MOV RDI,HelpText
    MOV ECX,SIZE# HelpText
    CMPB [LstFileName],0
    JZ .10: ; If no filename was provided in command line, display HelpText instead.
    ; Load the LstFileName content.
    WinABI CreateFile, LstFileName, GENERIC_READ, FILE_SHARE_READ, 0, \
           OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
    MOV [hFile],RAX
    MOV RDI, NotFoundText
    MOV ECX,SIZE# NotFoundText
    CMP EAX,INVALID_HANDLE_VALUE
    JE .10: ; If file does not exist, display error message instead.
    WinABI GetFileSize, RAX, 0
    MOV [LstSize],RAX
    WinABI CreateFileMapping,[hFile],0,PAGE_READONLY,0,0,0
    MOV [hMap],RAX
    TEST RAX
    JZ .Error:
    WinABI MapViewOfFile,RAX,FILE_MAP_READ,0,0,0
    MOV [LstBeg],RAX
    TEST RAX
    JZ .Error:
    MOV RDI,RAX
    MOV RCX,[LstSize]
.10:; Decode, index and display the text mapped as RDI,RCX.
    MOV [TxtBeg],RDI
    MOV [TxtSize],RCX
    ; Count lines in file contents RDI,RCX into RBX.
    SUB EBX,EBX
    MOV AL,10
.20:INC EBX
    REPNE SCASB
    JE .20:
    ADD EBX,4 ; Count margins lines, too.
    MOV EAX,SIZE# INDEX
    MUL RBX
    ; Allocate memory for INDEX array, RAX bytes long.
    MOV [IndexEnd],RAX
    WinABI GlobalAlloc, GMEM_FIXED+GMEM_ZEROINIT, RAX
    TEST RAX
    JZ .Error:
    MOV [IndexBeg],RAX
    MOV [IndexPtr],RAX
    ADD [IndexEnd],RAX
    ; Allocate memory for WIDE copy of listing.
    MOV RCX,[TxtSize]
    SAL RCX,2 ; Size of WIDE variant cannot exceed 4 * file size.
    MOV [WideEnd],RCX
    WinABI GlobalAlloc, GMEM_FIXED, RCX
    TEST RAX
    JZ .Error:
    MOV [WideBeg],RAX
    MOV [WidePtr],RAX
    ADD [WideEnd],RAX
    MOV RDI,[TxtBeg]
    MOV RCX,[TxtSize]
    ; Create index of the UTF-8 text RDI,RCX.
    LEA EAX,[RDI+RCX]
    MOV [LstEnd],RAX
    SUB EAX,EAX
    MOV [MaxLineLen],EAX
    MOV [MaxRowNr],EAX
    ; Create index of top margin empty envelope line.
    MOV R11,[IndexPtr]
    MOV [R11+INDEX.Color],ColorMrg
    ADD R11,SIZE# INDEX
    INCD [MaxRowNr]
    MOV [IndexPtr],R11
.50:; Index the physical line at RDI with remaining file size in RCX.
    MOV AL,10  ; LineFeed termination of physical line.
    JRCXZ .70:
    MOV RSI,RDI
    REPNE SCASB
    MOV RBX,RDI
    JNE .60:
    DEC RBX ; Trim LF.
.60:PUSH RCX,RDI
      Invoke LstIndex,RSI,RBX ; Create index of physical listing line RSI..RBX.
    POP RDI,RCX
    JNC .50:
.Error:
    WinABI MessageBox,[hWindow],ErrorText,="Error",MB_ICONERROR
    JMP .90:
.70:; Create index of bottom margin empty envelope line.
    MOV R11,[IndexPtr]
    CMP R11,[IndexEnd]
    JNB .Error:
    MOV [R11+INDEX.Color],ColorMrg
    INCD [MaxRowNr]
    ; Allocate and prepare line of stuff (spaces).
    MOV EBX,[MaxLineLen]
    INC EBX,EBX  ; Add left and right margin columns.
    MOV [MaxLineLen],EBX
    SHL EBX,1    ; Convert Wide character to bytes.
    WinABI GlobalAlloc,GMEM_FIXED,RBX
    MOV [StuffPtr],RAX
    TEST RAX
    JZ .Error:
    MOV RDI,RAX
    MOV ECX,EBX
    SAR ECX,1
    MOV AX,' '
    REP STOSW
    ; Initialize displayed window position.
    SUB EAX,EAX
    MOV [TopRow],EAX
    MOV [LeftCol],EAX
    CALL WndModify     ; Shrink | expand the window to the optimal size.
    WinABI RedrawWindow,[hWindow],0,0,RDW_FRAME | RDW_INTERNALPAINT | RDW_INVALIDATE
.90:RET
   ENDP LstCreate
LstIndex LinePtr, LineEnd

One INDEX record is created for each physical line of listing file and also for the envelope margin lines (the first and the last).

Each physical line is parsed, decoded from UTF-8 to UTF-16LE and this WIDE version stored on heap.

Procedure LstIndex will recognize machine and markup comments and parse one physical line into five spans (0..4) with different background colors, see WndPaint.
Line in virtually extended with spaces to MaxLineLen, so all lines will be displayed with the same width.

Input
LinePtr is pointer to the first UTF-8 byte of the current physical line.
LineEnd is pointer to LF character terminating the current line, i.e. it is the end of line with LF character removed.
Output
CF is set on error (out of memory).
Invoked by
LstCreate
INDEX STRUC   ; Describes one listing line.
.Color D D ; Background color of span 1 (as well of span 1..3 when INDEX.Len2=0).
       D D ; Unused.
.Ptr   D Q ; Pointer to the first unichar of listing line.
.Len1  D D ; Length of span 1 in characters.
.Len2  D D ; Length of span 2 in characters. Len1+Len2 is total line length without LF.
     ENDSTRUC INDEX
; Background color definition for INDEX.Color.
ColorMrg  EQU 0x00FFFFFF ; Margin line.
ColorHtml EQU 0x00FFD0D0 ; Markup comment.
ColorDmp  EQU 0x00D0D0D0 ; Dump column.
ColorSrc  EQU 0x00D0FFFF ; Source column.
ColorInfo EQU 0x00D0FFD0 ; Info message line.
ColorWarn EQU 0x0030FFFF ; Warning message line.
ColorErr  EQU 0x00D0D0FF ; Error message line.
[.text]
LstIndex Procedure LinePtr, LineEnd
    SaveToShadow
    MOV R11,[IndexPtr]
    CMP R11,[IndexEnd]
    CMC
    JC .90:
    MOV [R11+INDEX.Color],ColorSrc ; Assume no dump column.
    MOV RSI,[%LinePtr]
    MOV RDX,[%LineEnd]
    MOV RBX,RSI
    MOV RCX,RDX
    SUB RCX,RSI
.White:          ; Listing line has white space at the beginning.
    CMP RSI,RDX
    JNB .Length:
    LODSB
    CMP AL,' '
    JBE .White:  ; Skip leading white spaces.
    CMP AL,'|'   ; Does dump-column exist?
    JE .Dmp:
    CMP AL,'<'   ; Is it a markup comment line?                                     >
    JE .Html:
    MOV [R11+INDEX.Color],ColorSrc ; It is a source-only line.
    CALL .Decode: ; Convert the whole line RBX,RCX to WIDE encoding.
    MOV [R11+INDEX.Ptr],RAX  ; WIDE encoded text.
    SHR ECX,1                ; Size returned from .Decode is in bytes.
    MOV [R11+INDEX.Len1],ECX
    JMP .Length:
.Decode:PROC ; Convert the input string RBX,RCX from UTF-8 to UTF-16 and store it at [WidePtr].
    ; Input: RBX,RCX is input string.
    ; Output: RAX,RCX alias RAX..RDI is output Wide string (size in RCX is doubled).
     MOV RDI,[WidePtr]
     DecodeUTF8 RBX, Size=RCX, .W: ; Macro from string64.htm.
     .W:PROC1 ; Callback to store decoded Wide character to Wide buffer at RDI.
          CMP AX,0x0020
          JAE .WS:
          MOV AX,0x0020  ; Convert white-space to space.
      .WS:STOSW
          RET
        ENDP1 .W:
     MOV RCX,RDI
     MOV RAX,[WidePtr]   ; Old pointer before .Decode was called.
     SUB RCX,RAX
     MOV [WidePtr],RDI   ; Update pointer for the next Decoding.
     RET
  ENDP .Decode:
.Html: ; Listing line RBX,RCX is markup comment.
    MOV [R11+INDEX.Color],ColorHtml
    CALL .Decode
    MOV [R11+INDEX.Ptr],RAX
    SHR ECX,1
    MOV [R11+INDEX.Len1],ECX
    JMP .Length:
.Dmp: ; Listing line RBX,RCX alias RBX..RDX has machine comment or it is a message line.
    ; AL='|',  RBX=LineBeg, RSI=beyond 1st '|', RDX=LineEnd.
    MOV RDI,RSI
    MOV RCX,RDX
    SUB RCX,RDI
    REPNE SCASB ; Search for the 2nd '|'.
    JNE .Msg:
    ; Listing line RBX..RDX has dump and source span.
; RBX        RDI    RDX
;  |          |      |
;  |1234:5678| Source
    MOV [R11+INDEX.Color],ColorDmp
    MOV R8,RDI
    MOV RCX,RDI
    SUB RCX,RBX
    CALL .Decode: ; Convert dump-span in listing line RBX,RCX to WIDE encoding.
    MOV RDI,R8    ; Restore pointer to source-span in listing line.
    SHR ECX,1     ; Decoded length of dump.
    MOV [R11+INDEX.Len1],ECX
    MOV [R11+INDEX.Ptr],RAX
    MOV RBX,RDI
    MOV RCX,RDX
    SUB RCX,RBX
    CALL .Decode
    SHR ECX,1
    MOV [R11+INDEX.Len2],ECX
    JMP .Length:
.Msg: ; Listing line RBX..RDX is a message.
; AL='|',  RBX=LineBeg, RSI=beyond 1st '|', RDX=LineEnd.
;  RSI
;RBX|              RDX
;  ||               |
;  |## W1234 Warning
    ; Distinguish the color of message by search marker.
    MOV AL,'#'
    MOV ECX,ColorDmp
    CMP [RSI+0],AL
    JNE .SetColor:
    MOV ECX,ColorInfo
    CMP [ESI+1],AL
    JNE .SetColor:
    MOV ECX,ColorWarn
    CMP [ESI+2],AL
    JNE .SetColor:
    MOV ECX,ColorErr
.SetColor:
    MOV [R11+INDEX.Color],ECX
    MOV RCX,RDX
    SUB RCX,RBX
    CALL .Decode: ; Convert message line RBX,RCX to WIDE encoding.
    MOV [R11+INDEX.Ptr],RAX
    SHR ECX,1
    MOV [R11+INDEX.Len1],ECX
.Length:
    MOV EAX,[R11+INDEX.Len1]
    ADD EAX,[R11+INDEX.Len2]
    CMP EAX,[MaxLineLen]
    JNA .Store:
    MOV [MaxLineLen],EAX
.Store:
    CMP R11,[IndexEnd]
    JNB .90:
    INCD [MaxRowNr]
    ADD R11,SIZE# INDEX
    MOV [IndexPtr],R11
.90:EndProcedure LstIndex
LstDestroy
Procedure will release memory allocated in LstCreate and reinitialize variables used for indexing.
Input
-
Output
LstFileName is empty, pool and index buffers destroyed.
Called by
WinMain.
[.text]
LstDestroy PROC
   WinABI GlobalFree,[StuffPtr]
   WinABI GlobalFree,[IndexBeg]
   WinABI GlobalFree,[WideBeg]
   WinABI UnmapViewOfFile,[LstBeg]
   WinABI CloseHandle,[hMap]
   WinABI CloseHandle,[hFile]
   Clear LstVarBeg, Size=LstVarEnd-LstVarBeg
   WinABI UpdateWindow,[hWindow]
   RET
  ENDP LstDestroy
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
WndCreate WndProc.VK_ADD, WndProc.SetFontEDI
[.bss]
        %IF %^UNICODE  ; Properties of the used font.
TextMetric  DS TEXTMETRICW
        %ELSE
TextMetric  DS TEXTMETRICA
        %ENDIF
ClientRect  DS RECT ; Client area of the window.
[.text]
WndFont PROC
    MOV RCX,[hFont]
    JRCXZ .10:
    WinABI DeleteObject,RCX
.10:WinABI CreateFont, [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,[hWindow]
    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
Register
Associate *.lst files with this viewer in MS Windows registry.
Called by
WndProc.VK_F4.
[.data]
Listing D "lstview4.exe",0 ; Name of file type in registry classes.
RegHelp D 'Associate "*.lst" files to always open with',10
Classes D "Software\Classes\.lst",0
Shell   D "Software\Classes\Applications\lstview4.exe\shell\open\command",0
Quote   D '"',0
Default D "",0

Command D MAX_PATH_SIZE + 4 * UNICHAR 0
[.bss]
hKey    D QWORD ; Handle of registry key.
RegName D QWORD ; Pointer to the filename in ExeSelf. Not used.
ExeSelf D MAX_PATH_SIZE * U ; Full path to "lstview4.exe".

[.text]
Register PROC
    WinABI SearchPath, 0, ="%^PROGRAM.exe", 0, MAX_PATH_SIZE, ExeSelf, RegName
    TEST EAX
    JZ .Cancel:
    MOV R8,='" "%%1"'
    Concat$ Command, Quote, ExeSelf, R8
    WinABI MessageBox, [hWindow], RegHelp, RegHelp,      \ Ask for confirmation.
           MB_OKCANCEL | MB_ICONASTERISK | MB_DEFBUTTON1
    CMP EAX,IDOK
    JNE .Cancel:
    ; Create key HKCU\Software\Classes\.lst with value (Default) REG_SZ "lstview4.exe".
    WinABI RegCreateKeyEx, HKEY_CURRENT_USER, Classes, 0, \
           Default, 0, KEY_ALL_ACCESS, 0, hKey, 0
    WinABI RegSetValueEx, [hKey], 0, 0, REG_SZ, Listing, SIZE# Listing
    WinABI RegCloseKey, [hKey]
    ; Create key HKCU\Software\Classes\Applications\lstview4.exe\shell\open\command.
    WinABI RegCreateKeyEx, HKEY_CURRENT_USER, Shell, 0, \
           Default, 0, KEY_ALL_ACCESS, 0, hKey, 0
    GetLength$ Command
    INC ECX,ECX
    WinABI RegSetValueEx, [hKey], 0, 0, REG_SZ, Command, RCX
    WinABI RegCloseKey, [hKey]
    WinABI SHChangeNotify, SHCNE_ASSOCCHANGED,SHCNF_IDLIST, 0, 0 ; Remind MS Windows.
.Cancel:
    RET
    ENDP Register
   ENDPROGRAM lstview4

▲Back to the top▲