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

# lstview.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:

- as a command-line parameter, e. g. `lstview mysource.htm.lst` when the program is launched from console,
- with standard OpenFile dialog evocated with `Ctrl~O` or `F3`,
- dragging the file from desktop or explorer window to the program,
- double-clicking on the listing file in desktop or explorer window (when associated),
- writing the listing file name in console (when associated), e.g. `mysource.htm.lst`.

Listing viewer can be assembled in ANSI and WIDE version by changing the boolean 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 WinAPI invocations depending on UNICODE= option.
Nevertheless, the viewed listing file is always assumed in UTF-8 encoding only.

Format
  PE 32-bit FLAT GUI
Platform
  MS-Windows. It works in 32-bit and 64-bit Windows.
See also
  lstview4.htm for the native 64bit Windows 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 lstview.htm`
Run
  `lstview.exe "Source.htm.lst"` or associate the program with *.lst files and doubleclick on the listing file in Explorer.

Header

  The header defines program format, imported and linked libraries, dynamic memory management.

  > GUI programs use lot of dynamically linked functions from graphic libraries comctl32.dll, gdi32.dll and others. Instead of tediously IMPORTing each used function individually, it's more convenient to LINK those DLLs directly from the system where the program is being created, or use their import libraries. €ASM will pick up only those DLL function names, which were actually used in the program.
  > If you don't have the linked import library winapi.lib , you can create it with sample project DLL2LIB.

  Memory variables are allocated statically in the segment `[.bss]` and they are initialized to zero in bulk at the beginning.
  Due to the potentially unlimited size of displayed files this program uses dynamically allocated memory provided by macrolibrary memory32.htm , too. This library requires system macros SysAlloc, SysFree, which are defined here in the header.

            EUROASM Unicode=off
    lstview PROGRAM Format=PE, Subsystem=GUI, Width=32, Entry=WinMain, IconFile="easm.ico"
              LINK winapi.lib
              INCLUDE winapi.htm, wins.htm, winsgui.htm, winscon.htm,     \
                      winsdlg.htm, winsreg.htm, winssec.htm, winf32.htm,  \
                      stdcal32.htm, cpuext32.htm, cpuext.htm, string32.htm, memory32.htm
    ; Definition of three system macros required by library "memory32.htm":
    SysAlloc %MACRO BlockSize
                PUSH ECX,EDX
                 WinAPI VirtualAlloc, 0, EDX, MEM_COMMIT, PAGE_READWRITE
                  TEST EAX
                POP EDX,ECX
             %ENDMACRO SysAlloc ; Returns ZF on error, otherwise EAX=pointer to allocatd block.
    SysFree %MACRO BlockAddress
              PUSH ECX,EDX
                WinAPI VirtualFree, %BlockAddress, 0, MEM_RELEASE
              POP EDX,ECX
            %ENDMACRO SysFree
    SysGetAllocationGranularity %MACRO
            MOV EAX,64K
            %ENDMACRO SysGetAllocationGranularity
    ; Debugging macro for simplified error report.
    AbortIf %MACRO cc,SourceLine
             %IF "%cc" == "FALSE"
               TEST EAX
               JNZ Abort%.:
             %ELSE
               J%!cc,Abort%.:
             %ENDIF
             MOV EBX,%SourceLine ; Error occured at "lstview.htm"{%^SourceLine}.
             JMP Abort@RT:       ; Go to report error and terminate program.
    [.text]
    Abort@RT:PROC1
             SUB ESP,40
             MOV EDI,ESP
             MOV ESI,AbortText
             MOV ECX,34
             REP MOVSB
             WinAPI GetLastError
             LEA EDI,[ESP+6]
             StoH EDI,Size=8
             MOV EAX,EBX
             LEA EDI,[ESP+23]
             StoD EDI,Size=8
             XOR EAX,EAX
             STOSB
             MOV ESI,ESP
             WinAPI MessageBoxA,0,ESI,=B"%^SourceName%^SourceExt",MB_OK|MB_ICONERROR
             TerminateProgram Errorlevel=8
    [.data]
    AbortText   D B "Error XXXXXXXXh at line DDDDDDDD"
                  ;  0....5...10...15...20...24....30
             ENDPROC1 Abort@RT:
    Abort%.:
            %ENDMACRO AbortIf

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.
    "    LstView - 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
    [.bss]
    Msg         D MSG                     ; Window message.
    LstFileName D MAX_PATH_SIZE * UNICHAR ; Name of the selected listing file.
    [.text]
    WinMain Procedure hInstance, hPrevInstance, szCmdLine, iCmdShow
         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 ESI,ECX, if provided.
         StripQuotes ESI,ECX; 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.
         WinAPI RedrawWindow,[hWindow],0,0,RDW_FRAME | RDW_INTERNALPAINT | RDW_INVALIDATE
    .MsgLoop:
         WinAPI GetMessage, Msg,0,0,0
         TEST EAX
         JZ .MsgQuit:       ; Message WM_QUIT - terminate program.
         WinAPI TranslateMessage, Msg ; Remap character keys from national keyboards.
         WinAPI DispatchMessage,  Msg ; Let Windows call our WndProc.
         JMP .MsgLoop:      ; Wait for another message.
    .MsgQuit:
         CALL LstDestroy    ; Release allocated dynamic memory.
         TerminateProgram Errorlevel=[Msg.wParam]
      EndProcedure WinMain

WndProc, hWnd, uMsg, wParam, lParam
  This is a callback procedure which receives and processes messages for the program window.
  Involved messages are dispatched to their handlers.
  Functionality of some message handlers is encapsulated with a call to procedures Wnd***, others are unrolled inline here in WndProc.
Handler Input
  EAX=uMsg, EBX=hWnd, ESI=wParam, EDI=lParam.
Handler Output
  EAX=0 if the message was completely processed by the handler. Otherwise the message is processed by WinAPI DefWindowProc and EAX outputs its return value.
  EBX,ECX,EDX,ESI,EDI may be destroyed in the handlers.
Invoked by
  WinAPI 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 D ; Handle of the used font.
    [.text]
    WndProc Procedure hWnd, uMsg, wParam, lParam
         MOV EBX,[%hWnd]
         MOV EAX,[%uMsg]
         MOV ESI,[%wParam]
         MOV EDI,[%lParam] ; Load msg attributes for handler's convenience.
        ; Fork message uMsg=EAX 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     ; Other events.
    .Def:WinAPI DefWindowProc,[%hWnd],[%uMsg],[%wParam],[%lParam]      ; Ignored events.
         JMP .Ret:  ; EndProcedure WndProc with value EAX returned from DefWindowProc.
         ; Message handlers terminate with a jump to .Def: or .Ret0:.
    .WM_CREATE: ; Window is being created by WndCreate.
         WinAPI DragAcceptFiles,EBX,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.
         WinAPI DragAcceptFiles,EBX,0 ; Stop accepting dragged files.
         WinAPI DeleteObject,[hFont]  ; Free the allocated font memory.
         WinAPI PostQuitMessage,0     ; Tell Windows to quit with errorlevel 0.
         JMP .Ret0:
    .WM_DROPFILES: ; User dropped a file icon to our window.
         WinAPI DragQueryFile,ESI,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  ; ESI 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
         WinAPI SendMessage,EBX,WM_VSCROLL,SB_LINEUP,0
         JMP .RollUp:
     .RollDown:
         CMP EDI,0
         JGE .Ret0:
         ADD EDI,WheelPerLine
         MOV [WheelCnt],EDI
         WinAPI SendMessage,EBX,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
         WinAPI SendMessage,EBX,WM_VSCROLL,SB_LINEDOWN,0
         JMP .DragDown:
     .DragUp:
         CMP [yClientCnt],ESI
         JLE .DragRight:
         MOV EAX,[cyChar]
         SUB [yClientCnt],EAX
         WinAPI SendMessage,EBX,WM_VSCROLL,SB_LINEUP,0
         JMP .DragUp:
     .DragRight:
         CMP [xClientCnt],ESI
         JGE .DragLeft:
         MOV EAX,[cxChar]
         ADD [xClientCnt],EAX
         WinAPI SendMessage,EBX,WM_HSCROLL,SB_LINERIGHT,0
         JMP .DragRight:
     .DragLeft:
         CMP [xClientCnt],ESI
         JLE .Ret0:
         MOV EAX,[cxChar]
         SUB [xClientCnt],EAX
         WinAPI SendMessage,EBX,WM_HSCROLL,SB_LINELEFT,0
         JMP .DragLeft:
         ; Helper subprocedures for keyboard and scrollbox event handlers.
    .GetCtrl2ECX PROC ; Returns ECX=1 when Ctrl is pressed, otherwise ECX=0. EAX,EDX undefined.
         WinAPI GetKeyState,VK_CONTROL
         XOR ECX,ECX
         SAL AX,1
         RCL ECX,1 ; Virtual key handlers receive ECX=1 when Ctrl was pressed, otherwise ECX=0.
         RET
        ENDP .GetCtrl2ECX
    .GetShift2ECX PROC ; Returns ECX=1 when Shift is pressed, otherwise ECX=0. EAX,EDX undefined.
         WinAPI GetAsyncKeyState,VK_SHIFT
         XOR ECX,ECX
         SAL AX,1
         RCL ECX,1 ; Virtual key handlers receive ECX=1 when Shift was pressed, otherwise ECX=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
         WinAPI SetScrollPos,[hWindow],SB_VERT,ESI,1
         WinAPI 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
         WinAPI SetScrollPos,[hWindow],SB_HORZ,ESI,1
         WinAPI 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 WinAPI TranslateMessage to wParam=ESI 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 ESI=wParam was pressed. Set ECX=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 WinAPI DefWindowProc.
    .SB_LINEDOWN: ; Vertical scrollbox line down.
    .VK_DOWN:     ; Down arrow.
         MOV ESI,[TopRow]
         INC ESI
         JECXZ .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
         JECXZ .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]
         JECXZ .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]
         JECXZ .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
         JECXZ .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
         JECXZ .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]
         JECXZ .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]
         JECXZ .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
         WinAPI SendMessage,EBX,WM_DESTROY,0,0
         JMP .Ret0:
    .H:     ; Ctrl-H Display ANSI HelpText.
    .VK_F1: ; F1
         WinAPI MessageBoxA,EBX,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
        WinAPI GetClientRect,EBX,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.
        WinAPI 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.
              ; ECX= 0 or 1 to scroll down or up.
        MOV EAX,[NrRowsCl]
        MOV ESI,[TopRow]
        SHR EAX,1
        ADD EAX,ESI ; EAX is now "cursor" line number (in vertical center of client).
        SHL EAX,4 ; Multiply by SIZE#INDEX=16.
        MOV EDI,[IndexBeg]
        ADD EDI,EAX ; EDI now points to the index of "cursor" line.
        MOV EAX,SIZE# INDEX
        SHL ECX,1 ; ECX is now  0 or  2.
        NOT ECX   ; ECX is now -1 or -3.
        ADD ECX,2 ; ECX is now +1 or -1.
        IMUL ECX  ; EAX is now +SIZE#INDEX or -SIZE#INDEX.
    .SkipLine:
        ADD EDI,EAX ; The next line (forward or backward).
        ADD ESI,ECX ; The next TopRow (INC or DEC).
        CMP EDI,[IndexBeg]
        JB .ColorInfo:     ; Stop at the top of listing.
        CMP EDI,[IndexEnd]
        JNB .ColorInfo:    ; Stop at the bottom of listing.
        MOV EDX,[EDI+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.
       ; JMP .Ret0:
    .Ret0:XOR EAX,EAX
    .Ret: MOV [%ReturnEAX],EAX
        EndProcedure WndProc

WndCreate
  Program lstview.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 D           ; Handle of the window object.
    hPen         D D           ; 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
        WinAPI GetModuleHandle,0
        MOV [WndClassEx.hInstance],EAX
        WinAPI LoadIcon,EAX,1             ; The 1st and only icon from [.rsrc] section.
        MOV [WndClassEx.hIcon],EAX
        WinAPI LoadCursor,0,IDC_HAND
        MOV [WndClassEx.hCursor],EAX
        WinAPI GetStockObject,WHITE_BRUSH ; Default window background colour.
        MOV [WndClassEx.hbrBackground],EAX
        WinAPI GetStockObject,NULL_PEN
        MOV [hPen],EAX
        WinAPI RegisterClassEx,WndClassEx
        ; Inquire system metrics.
        WinAPI GetSystemMetrics,SM_CXSCREEN
        MOV [cxScreen],EAX
        WinAPI GetSystemMetrics,SM_CYSCREEN
        MOV [cyScreen],EAX
        WinAPI GetSystemMetrics,SM_CXVSCROLL
        MOV [cxScroll],EAX
        WinAPI GetSystemMetrics,SM_CYHSCROLL
        MOV [cyScroll],EAX
        WinAPI GetSystemMetrics,SM_CXBORDER
        MOV [cxBorder],EAX
        WinAPI GetSystemMetrics,SM_CYBORDER
        MOV [cyBorder],EAX
        WinAPI GetSystemMetrics,SM_CYCAPTION
        MOV [cyCaption],EAX
        ; Create the main window.
        WinAPI 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],EAX
        MOV EBX,EAX
        MOV [VScrollInfo.cbSize], SIZE# SCROLLINFO
        MOV [VScrollInfo.fMask], SIF_RANGE | SIF_PAGE
        WinAPI SetScrollInfo, EBX, SB_VERT,  VScrollInfo, 1
        MOV [HScrollInfo.cbSize], SIZE# SCROLLINFO
        MOV [HScrollInfo.fMask], SIF_RANGE | SIF_PAGE
        WinAPI SetScrollInfo, EBX, SB_HORZ, HScrollInfo, 1
        WinAPI ShowWindow, EBX, SW_SHOWNORMAL
        WinAPI UpdateWindow, EBX
        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:

  Span | Background | Pointer | Length in chars | Remark
  --- | --- | --- | --- | ---
  0 | ColorMrg | StuffPtr | 1 | Left margin.
  1 | INDEX.Color | INDEX.Ptr | INDEX.Len1 | Dump column.
  2 | ColorSrc | INDEX.Ptr+2*INDEX.Len1 | INDEX.Len2 | Source column, color changed only when INDEX.length2>0.
  3 | unchanged | StuffPtr | MaxLineLen-INDEX.Len1-INDEX.Len2 | Extends the line to MaxLineLen.
  4 | ColorMrg | StuffPtr | 1 | Right 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 D ; 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 ESI,[IndexBeg]
         MOV EAX,SIZE# INDEX
         TEST ESI ; If index is not created yet.
         JZ .90:
         MUL [TopRow] ; MUL by the number of line which is displayed in the 1st client row.
         ADD ESI,EAX ; Index of topmost row.
         CMP ESI,[IndexBeg]
         JB .90:
         WinAPI BeginPaint, [hWindow], PaintStruct
         MOV [hDC],EAX
         WinAPI SelectObject, EAX, [hFont]
         WinAPI SelectObject, [hDC], [hPen]
         SUB EDI,EDI ; Begin to paint rows on client y-coordinate EDI=0.
         MOV ECX,[NrRowsCl]
     .10:CMP ESI,[IndexEnd]
         JNB .50:
         PUSH ECX
           CALL .RowPaint:
         POP ECX
         ADD EDI, [cyChar]    ; Height of character box.
         ADD ESI, SIZE# INDEX ; Index of the next row.
         DEC ECX
         JNZ .10:
     .50:CMP EDI,[cyClient]
         JAE .60:
         WinAPI Rectangle,[hDC],0,EDI,[cxClient],[cyClient] ; Erase garbage on the bottom.
     .60:MOV EAX,[xClient]
         CMP EAX,[cxClient]
         JAE .80:
         WinAPI Rectangle,[hDC],EAX,0,[cxClient],[cyClient] ; Erase garbage on the right.
     .80:WinAPI EndPaint, [hWindow], PaintStruct
     .90:RET
    .RowPaint PROC ; Paint one line described by INDEX record ESI at yClient=EDI. ESI,EDI are preserved.
        SUB EBX,EBX
        MOV [xClient],EBX
        MOV [ColClient],EBX
        CMP EBX,[LeftCol]
        JNE .10:
        ; Paint span0 margin.
        WinAPI SetBkColor, [hDC], ColorMrg
        INC EBX
        WinAPI TextOutW, [hDC], 0, EDI, [StuffPtr], EBX
        MOV EAX,[cxChar]
        ADD [xClient],EAX
    .10:MOV [ColClient],EBX ; 0 or 1.
        ; Paint span1 dump.
        WinAPI SetBkColor, [hDC], [ESI+INDEX.Color]
        MOV EDX,[ESI+INDEX.Ptr]
        MOV ECX,[ESI+INDEX.Len1]
        MOV EAX,[LeftCol]
        LEA EAX,[EAX+EBX-1]
        SUB ECX,EAX
        JB .15:
        SAL EAX,1
        ADD EDX,EAX
        ADD [ColClient],ECX
        WinAPI TextOutW, [hDC], [xClient], EDI, EDX, ECX ; Paint dump span of ECX characters.
        MOV EAX,[cxChar]
        MUL [ColClient]
        MOV [xClient],EAX
        CMP EAX,[cxClient]
        JAE .80:
    .15:MOV ECX,[ESI+INDEX.Len2]
        JECXZ .30:
        ; Paint span2 source.
        WinAPI SetBkColor,[hDC],ColorSrc
        MOV EDX,[ESI+INDEX.Len1]
        LEA EBX,[EDX+EDX]
        ADD EBX,[ESI+INDEX.Ptr]
        MOV EAX,[LeftCol]
        INC EDX
        MOV ECX,[ESI+INDEX.Len2]
        SUB EAX,EDX
        JB .20:
        SUB ECX,EAX
        SAL EAX,1
        ADD EBX,EAX
    .20:ADD [ColClient],ECX
        WinAPI TextOutW, [hDC], [xClient], EDI, EBX, ECX ; 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,[ESI+INDEX.Len1]
        SUB ECX,[ESI+INDEX.Len2]
        SUB ECX,2
        JBE .40:
        ADD [ColClient],ECX
        WinAPI TextOutW, [hDC], [xClient], EDI, [StuffPtr], ECX ; Paint stuff span of ECX characters.
        MOV EAX,[cxChar]
        MUL [ColClient]
        MOV [xClient],EAX
        CMP EAX,[cxClient]
        JAE .80:
    .40: ; Paint span4 margin.
        WinAPI SetBkColor, [hDC], ColorMrg
        WinAPI TextOutW, [hDC], [xClient], EDI, [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]
        JECXZ .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.
        WinAPI 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
        JECXZ .End:
        CDQ
        DIV ECX
        INC EAX
        MOV [NrRowsCl],EAX ; How many rows fits in client height.
        WinAPI 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 48  ; Screen margins of max-modified window in pixels.
    MarginVert  EQU 64
    [.text]
    WndModify PROC
        MOV EAX,[MaxLineLen] ; Calculate maximal useful window width.
        MUL [cxChar]
        ADD EAX,[cxScroll]
        ADD EAX,[cxScroll]
        XCHG EBX,EAX ; EBX is now required client width to display whole lines.
        MOV EAX,[cxScreen]
        SUB EAX,2*MarginHor
        CMP EAX,EBX
        JA .xOK:
        XCHG EAX,EBX ; Screen is not wide enough.
    .xOK: ; EBX is now the new client width.
        MOV EAX,[MaxRowNr]
        MUL [cyChar]
        ADD EAX,[cyScroll]
        XCHG EDI,EAX
        MOV EAX,[cyScreen]
        SUB EAX,2*MarginVert
        CMP EAX,EDI
        JA .yOK:
        XCHG EAX,EDI ; Screen is not high enough.
    .yOK: ; EDI 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]
        WinAPI MoveWindow, [hWindow], MarginHor, MarginVert, EBX, EDI, 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
  EDI=lParam with yClient&xClient coordinates in high&low words.
  [hWindow], LstFileName
Output
  Window title is updated.
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
       PUSHAD
        MOV EBX,0x0000_FFFF
        MOV ECX,EDI
        AND EBX,EDI   ; xClient.
        MOV EDI,LocA
        MOV AL,'{'
        STOSB
        XCHG ECX,EAX
        SHR EAX,16 ; yClient.
        CDQ
        DIV [cyChar]
        ADD EAX,[TopRow]
        StoD EDI
        MOV AX,'}['
        STOSW
        MOV EAX,EBX
        CDQ
        DIV [cxChar]
        ADD EAX,[LeftCol]
        StoD EDI
        MOV AX,']'
        STOSW
        %IF %^UNICODE  ; Convert ANSI string produced by StoD to WIDE string.
          MOV ESI,LocA
          MOV EDI,LocW
          SUB EAX,EAX
      .50:LODSB
          STOSW
          TEST EAX
          JNZ .50:
        %ENDIF
       POPAD
       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.
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.
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
        PUSH EBX,EDI
        %IF %^UNICODE
          MOV EBX,LocW
        %ELSE
          MOV EBX,LocA
        %ENDIF
        CMPB [LstFileName],0
        JNZ .NoFile:
        Concat$ Title,DefTitle
        JMP .ShowTitle:
    .NoFile:
        Concat$ Title,='"', LstFileName, ='"', EBX, DefTitle
    .ShowTitle:
        WinAPI SetWindowText,[hWindow],Title
        POP EDI,EBX
        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
        WinAPI GetOpenFileName,OpenDialog
        TEST EAX
        RET
       ENDP LstSelect

LstCreate

  LstCreate reserves dynamic memory for Index and for the conversion of UTF-8 listing file to UTF-16.

  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 IndexBuffer.

Input
  LstFileName
Output
  [IndexBeg]..[IndexEnd], [MaxLineLen], [MaxRowNr].
Depends on
  FileLoad, FileClose.
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.
    Pool        D D      ; Pointer to dynamic memory structure POOL.
    LineBuffer  D D      ; Pointer to BUFFER for temporary Wide listing line.
    IndexBuffer D D      ; Pointer to BUFFER with INDEX record per each listing line.
    IndexBeg    D D      ; Pointer to INDEX record of the first listing line.
    IndexEnd    D D      ; Pointer beyond the INDEX record of the last listing line.
    StuffPtr    D D      ; Pointer to an empty line of MaxLineLen WIDE spaces.
    LstFile     DS FILE  ; FILE object.
    Index       DS INDEX ; Working space for the index.
    LstVarEnd:
    [.text]
    LstCreate PROC
        PoolCreate
        AbortIf C,%^SourceLine
        MOV [Pool],EAX
        BufferCreate EAX,Size=4K   ; Temporary buffer for one Wide listing line span.
        AbortIf C,%^SourceLine
        MOV [LineBuffer],EAX
        BufferCreate [Pool],Size=16K*SIZE#INDEX ; This is enough to store 16K physical lines without reallocation.
        AbortIf C,%^SourceLine
        MOV [IndexBuffer],EAX
        CALL WndTitle
        MOV EDI,HelpText
        MOV ECX,SIZE# HelpText
        CMPB [LstFileName],0
        JZ .20: ; If no filename in command line.
        FileAssign LstFile,LstFileName
        FileLoad LstFile ; Memory at ESI,EAX now contains the listing in UTF-8 (or plain ASCII).
        MOV EDI,NotFoundText
        MOV ECX,SIZE# NotFoundText
        JC .20: ; If the specified file was not found.
        MOV EDI,ESI ; Pointer to the loaded listing (encoded in ASCII or UTF-8).
        MOV ECX,EAX ; Size of the listing file loaded in memory.
    .20:; Create index of the UTF-8 text EDI,ECX.
        SUB EAX,EAX
        MOV [MaxLineLen],EAX
        MOV [MaxRowNr],EAX
        ; Create index of top margin empty envelope line.
        MOV [Index.Color],ColorMrg
        BufferStore [IndexBuffer],Index, SIZE# Index ; Top envelope line.
        INCD [MaxRowNr]
        MOV AL,10  ; LineFeed termination of physical line.
    .30:; Index the physical line at EDI with remaining file size in ECX.
        JECXZ .50:
        MOV ESI,EDI
        REPNE SCASB
        MOV EBX,EDI
        JNE .40:
        DEC EBX ; Trim LF.
    .40:Invoke LstIndex,ESI,EBX ; Create index of physical listing line ESI,EBX.
        JMP .30:
    .50:MOV ECX,[MaxLineLen] ; Prepare line of stuff (spaces).
        INC ECX,ECX
        MOV [MaxLineLen],ECX
        SHL ECX,1
        PoolNew [Pool],ECX,Align=WORD
        AbortIf C,%^SourceLine
        MOV EDI,EAX
        MOV [StuffPtr],EDI
        MOV AX,0x0020
        SHR ECX,1
        REP STOSW
        ; Create index of bottom margin empty envelope line.
        Clear Index
        MOV [Index.Color],ColorMrg
        BufferStore [IndexBuffer],Index, SIZE# Index ; Bottom envelope line.
        BufferRetrieve [IndexBuffer]
        MOV [IndexBeg],ESI
        MOV [IndexEnd],ESI
        ADD [IndexEnd],ECX
        ;DIV ECX,SIZE#INDEX
        SAR ECX,4 ; SIZE# INDEX = 16.
        MOV [MaxRowNr],ECX
        FileClose LstFile  ; File contents is already converted and indexed on Pool.
        SUB EAX,EAX
        MOV [TopRow],EAX
        MOV [LeftCol],EAX
        CALL WndModify     ; Shrink | expand the window to the optimal size.
        WinAPI RedrawWindow,[hWindow],0,0,RDW_FRAME | RDW_INTERNALPAINT | RDW_INVALIDATE
        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 virtually extended with spaces to MaxLineLen, so all lines will be displayed with the same width.

  Procedure LstIndex will parse one physical line into five spans (0..4) with different background colors, see WndPaint.

  Line is parsed, decoded from UTF-8 to UTF-16LE and stored on Pool. The Index record is then saved to IndexBuffer.

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.
Invoked by
  LstCreate

    INDEX STRUC   ; Describes one listing line.
    .Color D D ; Background color of span 1 (as well for span 1..3 when INDEX.Length2=0).
    .Ptr   D D ; Pointer to the first unichar of listing line.
    .Len1  D D ; Length of span 1.
    .Len2  D D ; Length of span 2.
         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
        Clear Index
        MOV [Index.Color],ColorSrc ; Assume no dump column.
        MOV ESI,[%LinePtr]
        MOV EDX,[%LineEnd]
        MOV EBX,ESI
        MOV ECX,EDX
        SUB ECX,ESI
    .White:
        CMP ESI,EDX
        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 [Index.Color],ColorSrc ; It is a source-only line.
        BufferClear [LineBuffer]
        CALL .Decode
        MOV [Index.Ptr],EAX
        SHR ECX,1
        MOV [Index.Len1],ECX
        JMP .Length:
    .Decode:PROC ; Convert the input string from UTF-8 to UTF-16 and store it on [Pool].
        ; Input: EBX,ECX is input string
        ; Output: EAX,ECX is output string (size in ECX is doubled).
        PUSH ESI
         DecodeUTF8 EBX, Size=ECX, .W:  ; Macro from string32.htm.
         .W:PROC1 ; Store decoded Wide character to LineBuffer.
              CMP AX,0x0020
              JAE .WS:
              MOV AX,0x0020  ; Convert white-space to space.
          .WS:BufferStoreWord [LineBuffer],EAX
              RET
            ENDP1 .W:
         BufferRetrieve [LineBuffer] ; Into ESI,ECX.
         PoolStore [Pool],ESI,ECX
        POP ESI
        RET
      ENDP .Decode:
    .Html:
        MOV [Index.Color],ColorHtml
        BufferClear [LineBuffer]
        CALL .Decode
        MOV [Index.Ptr],EAX
        SHR ECX,1
        MOV [Index.Len1],ECX
        JMP .Length:
    .Dmp: ; AL='|',  EBX=LinePtr, ESI=beyond 1st '|', EDX=LineEnd.
        MOV EDI,ESI
        MOV ECX,EDX
        SUB ECX,EDI
        REPNE SCASB ; Search for the 2nd '|'.
        JNE .Msg:
    ; EBX        EDI    EDX
    ;  |          |      |
    ;  |1234:5678| Source
        MOV [Index.Color],ColorDmp
        BufferClear [LineBuffer]
        MOV ECX,EDI
        SUB ECX,EBX
        CALL .Decode
        SHR ECX,1
        MOV [Index.Len1],ECX
        MOV EBX,EDI
        MOV ECX,EDX
        SUB ECX,EBX
        CALL .Decode
        MOV [Index.Ptr],EAX
        SHR ECX,1
        SUB ECX,[Index.Len1]
        MOV [Index.Len2],ECX
        JMP .Length:
    .Msg: ; EBX=LinePtr, ESI=beyond 1st '|', EDX=LineEnd.
    ;  ESI             EDI
    ;EBX|              EDX
    ;  ||               |
    ;  |## W1234 Warning
        MOV AL,'#'
        MOV ECX,ColorDmp
        CMP [ESI+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 [Index.Color],ECX
        BufferClear [LineBuffer]
        MOV ECX,EDX
        SUB ECX,EBX
        CALL .Decode
        MOV [Index.Ptr],EAX
        SHR ECX,1
        MOV [Index.Len1],ECX
    .Length:
        MOV EAX,[Index.Len1]
        ADD EAX,[Index.Len2]
        CMP EAX,[MaxLineLen]
        JNA .Store:
        MOV [MaxLineLen],EAX
    .Store:
        BufferStore [IndexBuffer], Index, SIZE# Index
      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
            PoolDestroy [Pool] ; Free the memory if Pool was already created before.
            Clear LstVarBeg, Size=LstVarEnd-LstVarBeg
            WinAPI 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 ECX,[hFont]
        JECXZ .10:
        WinAPI DeleteObject,ECX
    .10:WinAPI 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
        AbortIf FALSE,%^SourceLine
        MOV [hFont],EAX
        MOV EBX,[hWindow]
        WinAPI GetDC,EBX
        MOV EDI,EAX ; Device context,
        WinAPI SelectObject,EDI,[hFont]
        WinAPI GetTextMetrics,EDI,TextMetric
        WinAPI ReleaseDC,EBX,EDI
        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 "lstview.exe",0 ; Name of file type in registry classes.
    RegHelp D 'Associate "*.lst" files to always open with',10
    Command D MAX_PATH_SIZE + 4 * UNICHAR 0
    [.bss]
    hKey    D D ; Handle of registry key.
    RegName D D ; Pointer to the filename in ExeSelf. Not used.
    ExeSelf D MAX_PATH_SIZE * U ; Full path to "lstview.exe".
    [.text]
    Register PROC
        WinAPI SearchPath, 0, ="lstview.exe", 0, MAX_PATH_SIZE, ExeSelf, RegName
        AbortIf FALSE,%^SourceLine
        Concat$ Command, ='"', ExeSelf, ='" "%%1"'
        WinAPI MessageBox, [hWindow], RegHelp, ="Associate *.lst", \ 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 "lstview.exe".
        WinAPI RegCreateKeyEx, HKEY_CURRENT_USER, ="Software\Classes\.lst", 0, \
               ="", 0, KEY_ALL_ACCESS, 0, hKey, 0
        WinAPI RegSetValueEx, [hKey], 0, 0, REG_SZ, Listing, SIZE#Listing
        WinAPI RegCloseKey, [hKey]
        ; Create key HKCU\Software\Classes\Applications\lstview.exe\shell\open\command.
        WinAPI RegCreateKeyEx, HKEY_CURRENT_USER, ="Software\Classes\Applications\lstview.exe\shell\open\command", 0, \
               ="", 0, KEY_ALL_ACCESS, 0, hKey, 0
        GetLength$ Command
        INC ECX,ECX
        WinAPI RegSetValueEx, [hKey], 0, 0, REG_SZ, Command, ECX
        WinAPI RegCloseKey, [hKey]
        WinAPI SHChangeNotify, SHCNE_ASSOCCHANGED,SHCNF_IDLIST, 0, 0 ; Remind MS Windows.
    .Cancel:
        RET
        ENDP Register

       ENDPROGRAM lstview

▲Back to the top▲