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

# viewling.htm
Data
Data
Procedures
CreateLstIndex
FileIndexReopen
FileWriteOutput
Main
ReadFile_ini
SaveViewIndex
ViewEpilogue
ViewPrologue
WindowPaint
WindowProc
WindowResize
WindowTitle

This is a GUI module of EuroTool program EuroView for Linux.

             EUROASM CPU=X64, Unicode=No, DumpWidth=36, Debug=no
    viewling PROGRAM Format=COFF, Width=64
               %DROPMACRO *
               INCLUDEHEAD argument.htm, viewmain.htm
               INCLUDE linabi.htm, cpuext64.htm, cpuext.htm, linsfile.htm, linf64.htm, \
                       ansi.htm,string64.htm, memory64.htm, time.htm, status32.htm

    [.rodata]          ; Constant data.
    Help:
     DB "EuroView version %^DATE",10,10
     DB " designed to inspect binary, object, library,",10
     DB "  executable etc ""InputFile"":",9,9,"./euroview.x ""InputFile""",10,10
     DB " It also accepts arguments from the command-line or from /etc/eurotool/euroview.ini:",10
     DB 9,"-InputFile=       ",9,9,"Input file name to be inspected (alternative notation).",10
     DB 9,"-FileFormat=      ",9,9,"Default is Autodetect. /FF=? for the list of accepted formats.",10
     DB 9,"-OutputFile=      ",9,9,"Temporary file; default is ""/tmp/InputFile.lst"".",10
     DB 9,"-LeaveTemporary=no",9,9,"Do not erase OutputFile when EuroView terminates.",10
     DB 9,"-CodeWidth=       ",9,9,"Set to 16|32|64 if not autodetected.",10
     DB 9,"-CodeBegin=       ",9,9,"File address where to begin the disassembly..",10
     DB 9,"-CodeEnd=         ",9,9,"File address where to end the disassembly",10
     DB 9,"-DataBegin=       ",9,9,"File address where to begin the dumping as data.",10
     DB 9,"-DataEnde=        ",9,9,"File address where to end the dumping as data.",10
     DB 10
     DB " Accepted file formats:",10
     %i %SETA 1
     %WHILE "%FileFormats{%i}"
     DB 9,"%FileFormats{%i+0}"
     DB 9,"%FileFormats{%i+1}"
     DB 9,"%FileFormats{%i+2}"
     DB 9,"%FileFormats{%i+3}"
     DB 9,"%FileFormats{%i+4}"
     DB 9,"%FileFormats{%i+5}"
     DB 10
     %i %SETA %i+6
     %ENDWHILE
     DB 10," Keys:",10
     DB 9,"Tab | Left button",9,9,"decrease nesting level (more detailed)",10
     DB 9,"Shift Tab | Right button",9,"increase nesting level (more compact)",10
     DB 9,"Home",9,9,9,9,"beginning of the document",10
     DB 9,"End",9,9,9,9,"end of the document",10
     DB 9,"PgUp | PgDn",9,9,9,"page up | down",10
     DB 9,"Up | Dn | mouse wheel",9,9,"line up | down",10
     DB 9,"Esc",9,9,9,9,"quit the program",10
     DB 0
    FormatNames:
    FF %FOR %FileFormats
         DB "%FF",0
       %ENDFOR FF
    EndFormatNames:
    Spaces            DB NAME_MAX * 2 * BYTE ' '

    [.data]           ; Variable data.
    ValResize         DB 'xxxxxxxxx'  ; Replaced by '24;150t',0
    ScrollSlider      DB 0xE2,0x96,0x88,0xE2,0x96,0x88,0   ; 2 * FULL BLOCK.
    ScrollBar         DB 0xE2,0x96,0x92,0xE2,0x96,0x92,0   ; 2 * MEDIUM SHADE.

    [.bss]       ; Working memory variables.
    File_ini          DS FILE64 ; Configuration FILE64.
    FileInput         DS FILE64 ;  Input FILE64.
    FileOutput        DS FILE64 ; Output FILE64.lst in ASCII.
    FileIndex         DS FILE64 ; Temporary FILE64.lst.index with VIEW_INDEX records.
    TtySize           DS TTYSIZE
    TermIO::          DS TERMIO
    LstIndex:         DS LST_INDEX
    TermWidth         DD DWORD
    TermHeight        DD DWORD ; Number of rows in the terminal window.
    DirHeight         DD DWORD ; Number of rows in the directory window, without borders.
    Level             DD DWORD ; What level of headers to display (0..4).
    LevelPrevious     DD DWORD ; Used to test the change of Level.
    ListPos           DD DWORD ; Ordinal of the listing line displayed in the top row of the window.
    ListMax           DD DWORD ; Number of rows in the listing.
    KeyBuffer         DB 32 * BYTE

    [.text]

Main
  Program entry.

    Main:: PROC
        StdOutput EuroView::, Version::, Eol=yes
       ; Try to load arguments from the configuration file /etc/eurotool/euroview.ini.
        FileAssign File_ini,=B'/etc/eurotool/euroview.ini'
        FileExists? File_ini
        JNC .20:
        CALL ReadFile_ini
    .20:MOV EAX,[ArgNr::]        ; Read arguments from the command-line.
        INC EAX
        MOV [ArgNr::],EAX
        GetArg RAX, Frame=RSP    ; Returns the line in RSI,RCX with one argument, e. g. -IF="~/file.obj"
        JC .40:                  ; If there're no more arguments.
        CALL ArgParse::          ; Use ArgParse to translate it to a public symbol Arg***.
        JNC .20:
        StdOutput ErrorMessage::
        JMP ErrorHelp:
    .40:LEA RSI,[ArgInputFile::]
        CMPB [RSI],0
        JZ ErrorHelp:
        LEA RBX,[FileInput]
        FileAssign RBX,RSI
        FileExists? RBX
        JNC .50:
        LEA RSI,[RBX+FILE64.Name]
        StdOutput =B"File """,RSI,=B""" was not found.",Eol=yes
        TerminateProgram 4
    .50:; Input file was specified.
        ; Create level buffers.
        BufferCreate Size=256K
        JC ErrorAlloc:
        MOV [Level0Buffer::],RAX
    lvl %FOR 1..4
          BufferCreate Size=64K
          JC ErrorAlloc:
          MOV [Level%lvl{}Buffer::],RAX
        %ENDFOR
        LEA RAX,[FileIndexReopen:]
        MOV [FileIndexReopenProc::],RAX
        LEA RAX,[FileWriteOutput:]
        MOV [FileWriteOutputProc::],RAX
        MOVD [Level],0
        MOVD [ListPos],1
        CALL ViewPrologue
        CALL ViewCreate::                  ; External procedure in viewmain.htm.
        CALL ViewEpilogue
        CALL WindowResize
        CALL WindowPaint
        CALL WindowProc
        FileClose FileOutput, FileIndex
        JSt [Status::],ArgLeaveTemporary,.90:
        FileDelete FileOutput, FileIndex
    .90:TerminateProgram
       ENDP Main::

FileIndexReopen
  OS dependent proxy function.

    FileIndexReopen: PROC
        LEA RBX,[FileIndex]
        FileClose RBX
        FileMapCreate RBX                ; Close and reopen FileIndex. Returns the contents in RDI,RAX.
        JC ErrorFileIndex:
        RET
      ENDP FileIndexReopen:

FileWriteOutput
  OS dependent proxy function.

    FileWriteOutput: PROC
        FileWrite FileOutput,RSI,RCX
        JC ErrorFileOutput:
        RET
      ENDP FileWriteOutput:

SaveViewIndex
  Global Linux procedure SaveViewIndex is called from analyzing and formating procedures in the OS-independent module viewmain.htm.
  It will store the external structured variable ViewIndex:: to FileIndex, keep its `.Size`, add `.Size` to .FA, clear `.Level` and `.Rem` in this variable.
Input
  RBX=pointer to VIEW_INDEX variable, usually to ViewIndex::.
  FileIndex is a created file.
Output
  RAX=0.
  RBX= is kept as a pointer to VIEW_INDEX variable.
  [RBX+VIEW_INDEX.FA] is incremented by the previous [RBX+VIEW_INDEX.Size] when .Level=0.
  [RBX+VIEW_INDEX.Size] is kept, but .Level bits are cleared.
  [RBX+VIEW_INDEX.Rem] is cleared.
Clobbers
  RAX

    SaveViewIndex:: PROC
        PUSH RCX
         FileWrite FileIndex, RBX, 16
         MOV EAX,[RBX+VIEW_INDEX.Size]
         MOV ECX,EAX
         AND EAX,0x0FFF_FFFF                ; Get rid of Level bits.
         MOV [RBX+VIEW_INDEX.Size],EAX      ; Keep .Size unchanged for the next element.
         SHR ECX,28                         ; Isolate level.
         JNZ .50:
         ADD [RBX+VIEW_INDEX.FA],EAX        ; Add previous .Size to this .FA, but keep .FA unchanged when .Level >0.
    .50: XOR EAX,EAX
         MOV [RBX+VIEW_INDEX.Rem],RAX       ; Always clear .Rem field.
        POP RCX
        RET
       ENDP SaveViewIndex::

WindowResize
  Procedure WindowResize resizes the terminal window when it is too small and the it paints the entire window.

    WindowResize PROC
        LinABI ioctl,0,TIOCGWINSZ,TtySize
        MOVZXW EDX,[TtySize.ts_lines]
        MOVZXW ECX,[TtySize.ts_cols]
        MOV EAX,20               ; Minimal acceptable lines.
        CMP EDX,EAX
        JB .10:
        MOV EAX,EDX
    .10:LEA RDI,[ValResize]
        StoD RDI
        MOV AL,';'
        STOSB
        MOV EAX,150              ; Minimal acceptable columns.
        CMP ECX,EAX
        JB .13:
        MOV EAX,ECX
    .13:StoD RDI
        MOV AX,'t'
        STOSW
        LinABI ioctl,0,TIOCGWINSZ,TtySize
        MOVZXW EDX,[TtySize.ts_lines]
        MOV [TermHeight],EDX
        MOVZXW ECX,[TtySize.ts_cols]
        MOV [TermWidth],ECX
        RET
     ENDP WindowResize

ReadFile_ini
  Procedure ReadFile_ini reads lines from File_ini in UTF-8 and parses its each line into configuration variables Arg*** in UTF-8, too.
Input
  File_ini is assigned with the name.
Clobbers
  RAX,RCX,RDX,RSI,RDI

    ReadFile_ini:: PROC
        SetSt [Status::],ArgFromFile       ; Tell ArgParse that arguments may not begin with / or -.
        LEA RDI,[WorkMemory::]
        Concat$ RDI, RDI,=B'Configuration "',File_ini.Name,=B'"'
    .10:FileStreamOpen File_ini,BufSize=4K
        JNC .20:
        Concat$ RDI,RDI,=B'" was not found.',=B(10)
        JMP .90:
    .20:FileStreamReadLn File_ini
        JBE .80:
        MOV ECX,EAX
        ; The first line may begin with BOM.
        MOV AX,[RSI]
        CMPW AX,0xBBEF   ; UTF-8 BOM?
        JNE .50:
        ADD RSI,3        ; Skip the BOM.
        SUB ECX,3
        JB .80:
        JMP .50:
    .30:FileStreamReadLn File_ini
        JBE .80:
        MOV ECX,EAX
    .50:CALL ArgParse::
        JNC .30:
        StdOutput ErrorMessage::, Help
        TerminateProgram 8
    .80:FileClose File_ini
        LEA RDI,[WorkMemory::]
        Concat$ RDI,RDI,=B'" was accepted.',=B(10)
    .90:RstSt [Status::],ArgFromFile
        RET
      ENDP ReadFile_ini

ViewPrologue
  Linux function which will read ArgInputFile, memory-map it to InputPtr..InputEnd, then create files FileOutput and FileIndex with filenames ArgOutputFile (if not empty) or /tmp/ArgInputFileName.lst, /tmp/ArgInputFileName.lst.index (if ArgOutputFile= is empty).
Input
  ArgInputFile, ArgOutputFile, ArgFileFormat
Output
  CF=0, ArgOutputFile, ArgFileFormat (detected), FileOutput, FileIndex.
Error
  ErrorFile*

    ViewPrologue: PROC
        LEA RSI,[ArgInputFile::]           ; Memory-map FileInput.
        CMPB [RSI],0
        JZ ErrorFileInput:
        LEA RBX,[FileInput]
        FileAssign RBX,RSI
        FileMapOpen RBX
        JC ErrorFileInput:
        MOV [InputPtr::],RSI
        MOV [InputSize::],RAX
        LEA RDX,[RSI+RAX]
        MOV [InputEnd::],RDX
        BSR ECX,EAX
        MOV EDX,4
        ADD ECX,EDX
        SHR ECX,2
        CMP ECX,EDX                        ; Number of address digits (4..8) in listing.
        JA .10:
        MOV ECX,EDX
    .10:MOV [AddressDigits::],ECX
        MOV EDX,[ArgFileFormat::]          ; Find file format.
        TEST EDX
        JNZ .20:
        CALL AutodetectFileFormat::
        MOV [FormatProcPtr::],RAX          ; FormatELF32, FormatBIN etc.
        MOV [ArgFileFormat::],ECX          ; Ordinal format number.
    .20:XOR EDI,EDI
        MOV EDX,[ArgFileFormat::]          ; Set by AutodetectFormat or by cmd-line argument.
        LEA RDI,[FormatNames:]             ; Find the format uppercase name.
        MOV ECX,EndFormatNames-FormatNames
        XOR EAX,EAX
    .25:DEC EDX
        JZ .28:
        REPNE SCASB
        JMP .25:
    .28:MOV [FormatNamePtr::],RDI
        LEA RBX,[FileOutput]
        LEA RSI,[ArgOutputFile::]
        CMPB [RSI],0
        JZ .30:
        FileAssign RBX,RSI
        JC ErrorFileOutput:
        JMP .40:
    .30:; If ArgOutputFile is not specified (default), use /tmp/ and filename without path for temporary names.
        LEA RSI,[FileInput.Name]
        MOV EAX,[FileInput.NameOffs]
        ADD RSI,RAX
        FileAssign RBX,=B"/tmp/",RSI,=b".lst"
    .40:FileCreate RBX
        JC ErrorFileOutput:
        LEA RSI,[RBX+FILE64.Name]
        FileAssign FileIndex, RSI, =B".index"
        FileCreate FileIndex
        JC ErrorFileIndex
        RET
       ENDP ViewPrologue

ViewEpilogue
  Windows function which will convert indexes written to FileIndex to listing lines and store the lines to FileOutput. Then it will close FileInput and FileIndex, reopen FileOutput, memory-map it to OutputPtr..OutputEnd, sort it, store indexes of listing lines to LevelnBuffer.
Input
  OutputPtr..OutputEnd
Output
  CF=0LevelnBuffer (n=0..4)
Error
  CF=1

    ViewEpilogue:: PROC
         FileClose FileOutput, FileIndex
         FileMapOpen FileOutput
         JC ErrorFileOutput
         MOV [OutputPtr::],RSI
         MOV [OutputSize::],RAX
         ADD RAX,RSI
         MOV [OutputEnd::],RAX
         FileMapOpen FileIndex
         JC ErrorFileIndex
         MOV [IndexPtr::],RSI
         ADD RSI,RAX
         MOV [IndexEnd::],RSI
         SHR EAX,4
         MOV [ListMax],EAX
         CALL CreateLstIndex::   ; Toss the index to five memory buffers for levels 0..4.
         MOVD [Level],0
         MOVD [ListPos],1
         RET
      ENDP ViewEpilogue

WindowPaint
  Linux function WindowPaint will paint the entire terminal window with its title and with the partial contents of `ListMax` rows of the listing file (FileOutput).

  The following example shows the listing with `ListMax=22` rows, viewed by the terminal window with `TermHeight=11` rows.
  First line in terminal (title row) is fixed, it shows the program name, file format, nesting level (0..4) and filename, for instance EuroView ELF32 0 "file.o".
  Vertical position of the displayed part of listing in the terminal window is specified by `ListPos`, which is the ordinal number of this listing row, which is displayed in terminal row 1 (just below the title row).

  Cursor keys and mouse wheel manipulate only with this variable `ListPos`, it is saturated to `0..ListMax`.

  The last column in terminal window is dedicated to scroll box. The height of its slider is `ScrollHeight=(TermHeight-1)*(TermHeight-1)/ListMax=10*10/22=4` saturated to `1..TermHeight-1=1..10`.
  Position of the topmost character of the slider is `ScrollPos=(TermHeight-1)*(ListPos)/(ListMax)+1=10*7/22+1=4`, saturated to `1..TermHeight-1=1..10`.

  Listing contains ASCII characters only, no UTF-8.

  ┌──────────────────────────────┐ │ListRow=1 │ │ListRow=2 │ │ListRow=3 │ │ListRow=4 │ ╔════════════════════════╗ │ ║░EuroView░FF░L░"file"░░░║<title ║ListRow=7 TermRow=1 ▒║ │ ║ListRow=8 TermRow=2 ▒║ │ ║ListRow=9 TermRow=3 █║┐<─3 │ ║ListRow=10 TermRow=4 █║│ │ ║ListRow=11 TermRow=5 █║├──4 │ ║ListRow=12 TermRow=6 █║┘ │ ║ListRow=13 TermRow=7 ▒║ │ ║ListRow=14 TermRow=8 ▒║ │ ║ListRow=15 TermRow=9 ▒║ │ ║ListRow=16 TermRow=10 ▒║ │ ╚════════════════════════╝ │ │ListRow=18 │ │ListRow=19 │ │ListRow=20 │ │ListRow=21 │ │ListRow=22 │ └──────────────────────────────┘ TermHeight=11, ListMax=22, ListPos=7, ScrollPos=3, ScrollHeight=4.
Input
  [ListPos], [ListMax], [Level], [LevelXBuffer], [OutputPtr]..[OutputEnd], [IndexPtr]..[IndexEnd]
Output
  Terminal window is painted.

    WindowPaint PROC
        CALL WindowTitle
        StdOutput AnsiClrFg000000
        MOV R12,[OutputPtr::]
        MOV EAX,[Level]
        MOV EDX,[LevelPrevious]
        CMP EAX,EDX
        MOV [LevelPrevious],EAX
        JE .40:
        JB .30:
        ; Level is increasing from EDX to EAX. Calculate the new value of LinePos.
        ADD R12,RAX              ; Position of '#' in output line.
        BufferRetrieve [8*RDX+Level0Buffer::] ; Let RSI,RCX point to old LST_INDEX records.
        XOR EDX,EDX
        MOV EDI,[ListPos]
        TEST EDI
        JZ .15:
    .10:DEC EDI
        JZ .20:
    .15:LODSD                    ; EAX=LST_INDEX.FA
        CMPB [R12+RAX],'#'       ; Is the line in new level?
        LODSD                    ; Skip LST_INDEX.Size
        JNE .10:
        INC EDX                  ; The next row.
        JMP .10:
    .20:TEST EDX
        JNZ .25:
        INC EDX
    .25:MOV [ListPos],EDX        ; The new position is calculated.
        JMP .40:
    .30:; Level is decreasing form EDX to EAX. Calculate the new value of LinePos.
        ADD R12,RDX
        BufferRetrieve [8*RAX+Level0Buffer::] ; Let RSI,RCX point to new LST_INDEX records.
        SHR ECX,3
        JZ .90:
        XOR EDI,EDI              ; Line counter in new buffer.
        MOV EDX,[ListPos]
    .35:INC EDI
        LODSD                    ; EAX=LST_INDEX.FA
        CMPB [R12+RAX],'#'
        LODSD                    ; Skip LST_INDEX.Size
        JNE .35:
        DEC EDX
        JNZ .35:
        MOV [ListPos],EDI        ; The new position is calculated.
      ;;  JMP .40:
    .40:; Level is unchanged or adjusted.
        MOV EAX,[Level]
        BufferRetrieve [8*RAX+Level0Buffer::] ; Let RSI,RCX point to LST_INDEX records.
        LEA R9,[RSI+RCX]         ; R9=behind the last LST_INDEX record.
        SHR ECX,3                ; SIZE# LST_INDEX = 8.
        MOV [ListMax],ECX
        MOV EDX,[ListPos]
        TEST EDX
        JZ .45:
        DEC EDX
    .45:LEA RBX,[RSI+8*RDX]      ; RBX = pointer to LST_INDEX of ListPos-th record.
        MOV EDX,2                ; RDX=Terminal row (2,3,,,TerminalHeight-1).
    .50:; The loop for terminal lines.
        MOV RAX,RDX              ; Terminal row number.
        LEA RDI,[AnsiAtRowCol+2]
        StoD RDI
        MOV EAX,';1H'
        STOSD                    ; AnsiAtRowCol is prepared to move the cursor to row RDX, col 1.
        StdOutput AnsiAtRowCol   ; Make the position in terminal at column 1 of row RDX.
        SUB ECX,ECX
        MOV R13D,[TermWidth]
        DEC R13                  ; Decrease TermWidth due to ScrolBox.
        CMP RBX,R9               ; At end of LST_INDEX?
        JNB .57:
        MOV ESI,[RBX+LST_INDEX.FA]
        MOV ECX,[RBX+LST_INDEX.Size]
        ADD RSI,[OutputPtr::]
        CMP RCX,R13
        JBE .57:
        MOV RCX,R13              ; Line is long, its size will be RCX=TermWidth.  Number of spaces will be R13=0
        SUB R13,R13
        JMP .60:
    .57:SUB R13,RCX              ; Line is short, its size will be RCX. Number of spaces will be R13.
    .60:CALL .RowPaint           ; RSI,RCX is the contents of the listing row. Size of following spaces is R13.
        ADD RBX,SIZE# LST_INDEX
        INC RDX
        CMP EDX,[TermHeight]
        JB  .50:

        ; Scroll box.
         MOV EDI,[TermHeight]     ; Calculate ScrollHeight.
        DEC EDI
        MOV EAX,EDI
        MUL RAX
        MOV ECX,[ListMax]
        TEST ECX
        JZ .90:
        DIV RCX
        CMP EAX,0                ; Saturate ScrollHeight.
        JA  .63:
        MOV EAX,1
    .63:CMP EAX,EDI
        JNA .67:
        MOV EAX,EDI
    .67:MOV ESI,EAX              ; Let ESI=ScrollHeight.
        MOV EAX,[ListPos]        ; Calculate ScrollPos.
        MUL RDI                  ; RDI=TermHeight-1.
        MOV ECX,[ListMax]
        DIV RCX
        INC EAX
        CMP EAX,EDI              ; Saturate ScrollPos.
        JNA .70:
        MOV EAX,EDI
    .70:MOV EDX,EAX              ; EDX=ScrollPos, ESI=ScrollHeight.
        ADD ESI,EDX              ; ESI=position below the slider.
        MOV EBX,[TermHeight]
        DEC EBX
        XOR ECX,ECX              ; Row counter.
        INC ECX
    .75:INC ECX                  ; Paint the scrollbox at row ECX.
        CMP ECX,EBX
        JA .90:
        LEA RDI,[AnsiAtRowCol+2]
        MOV EAX,ECX
        StoD RDI                 ; Row 2..TermHeight.
        MOV AL,';'
        STOSB
        MOV EAX,[TermWidth]
        DEC EAX
        StoD RDI
        MOV AX,'H'
        STOSW
        StdOutput AnsiAtRowCol   ; Cursor is set at row ECX.
        CMP ECX,EDX
        JAE .85:
    .80:StdOutput AnsiClrBgFEFEFF,ScrollBar
        JMP .75:
    .85:CMP ECX,ESI
        JA .80:
        StdOutput AnsiClrBgFEFEFF,ScrollSlider
        JMP .75:
    .90:RET

    .RowPaint PROC ; Print a row at cursor position in column 1.
    ; The row looks like
    ; "|dump      | Remark in level0           Spaces"  or
    ; "!###   range ##### Name of the level3   Spaces"
    ; Input: RSI,RCX is the listing row (without CR+LF). RCX is never above TermWidth. R13 is the number of spaces.
    ; When the Remark or Name does not fit to TermWidth, it is shortened.
        TEST RCX
        JZ .8:
        LEA RDI,[RSI+1]
        MOV AL,'#'
        CMP [RDI],AL
        JE .3:                   ; Jump when this row represents a colored level row (it starts with pipe+hash).
        StdOutput AnsiClrBgC0C0C0; No, it is and ordinary Level0 row with a dump. Paint in gray.
        MOV AL,'|'
        MOV R8,RCX
        REPNE SCASB              ; Find the second pipe '|' which terminates the dump.
        DEC RDI
        SUB RDI,RSI              ; RDI is the dump size.
        StdOutput RSI,Size=RDI   ; Paint the dump. It is always displayed as unshorten.
        ADD RSI,RDI              ; RSI points to the start of the listing remark.
        MOV RCX,R8               ; Restore RCX.
        SUB RCX,RDI
        JNA .9:
        StdOutput AnsiClrBgFFFFD0 ; Paint in yellowish colour.
        JMP .7:
    .3: LEA RDI,[AnsiClrBgD0D0FF]
        CMP [RSI+4],AL
        JE .5:
        LEA RDI,[AnsiClrBgFFD0D0]
        CMP [RSI+3],AL
        JE .5:
        LEA RDI,[AnsiClrBgFFFF30]
        CMP [RSI+2],AL
        JE .5:
        LEA RDI,[AnsiClrBgD0FFD0]
    .5  StdOutput RDI            ; Color1..4.
    .7: StdOutput RSI,Size=RCX   ; Paint the level row.
    .8: StdOutput Spaces,Size=R13
        StdOutput AnsiClrBgC0C0C0
    .9:RET
      ENDP .RowPaint
     ENDP WindowPaint

WindowTitle
  Construct terminal window one line title which contains `EuroView FF L "file"`.
Input
  [FormatNamePtr::], [Level], ArgInputFile::
Output
  Title line is written to the terminal window.

    WindowTitle PROC
        LEA RDI,[WorkMemory::]     ; Title is constructed in WorkMemory.
        MOV RDX,RDI
        MOV AX,'  '
        STOSW
        LEA RSI,[EuroView::]
        MOV ECX,8
        REP MOVSB
        MOV AX,' "'
        STOSW
        LEA RSI,[ArgInputFile::]
    .10:LODSB
        CMP AL,0
        JE .20:
        STOSB
        JMP .10:
    .20:MOV AL,'"'
        STOSB
        MOV EAX,' as '
        STOSD
        MOV RSI,[FormatNamePtr::]
        TEST RSI
        JZ .50:
    .30:LODSB
        CMP AL,0
        JE .40:
        STOSB
        JMP .30:
    .40:LEA RSI,[=B' level ']
        MOV CL,7
        REP MOVSB
        MOV AX,'0'
        OR AL,[Level]
        STOSW
    .50:MOVD [AnsiAtRowCol+2],'1;1H'
        MOVB [AnsiAtRowCol+6],0
        StdOutput AnsiClrBgFFFFFF,AnsiClrFg800000,AnsiAtRowCol
        GetLengthUTF8 RDX
        MOV ESI,[TermWidth]
        CMP ECX,ESI
        JBE .60:
        StdOutput RDX,Size=RSI
        JMP .90:
    .60:StdOutput RDX,Size=RCX
        SUB ESI,ECX
        StdOutput Spaces,Size=RSI
    .90:RET
      ENDP WindowTitle

WindowProc
  This procedure reads the keyboard and mouse and manipulates with `ListPos`

    WindowProc PROC
        LEA RBX,[TermIO]
        LinABI ioctl,0,TCGETS,RBX          ; Load current local terminal status.
        RstSt [RBX+TERMIO.c_lflag],ICANON+ECHO
        LinABI ioctl,0,TCSETS,RBX          ; Disable terminal echo.
        StdOutput AnsiMouseEnable
        JMP .ReadKeyboard:
    .Resized:
        CALL WindowResize
        CALL WindowPaint
        MOV EBX,[ListPos]
        JMP .Saturate:
    .ReadKeyboard:
        LinABI ioctl,0,TIOCGWINSZ,TtySize  ; Check if terminal dimension changed.
        MOVZXW EDX,[TtySize.ts_lines]
        MOVZXW ECX,[TtySize.ts_cols]
        CMP EDX,[TermHeight]
        JNE .Resized:
        CMP ECX,[TermWidth]
        JNE .Resized:
        XOR EDI,EDI                        ; Read the keyboard in the main window.
        LEA RSI,[KeyBuffer]
        MOV R8,RSI
        MOV [RSI],RDI
        MOV EDX,SIZE# KeyBuffer
        LinABI read,RDI,RSI,RDX
        TEST EAX
        JNA .ReadKeyboard:
        XOR ECX,ECX
        MOV EBX,[ListPos::]
    key %FOR AnsiKeyCtrlHome,AnsiKeyCtrlEnd,AnsiKeyPgUp,AnsiKeyPgDn,AnsiKeyUp,AnsiKeyDn, \  Read the keyboard.
             AnsiKeyHome,AnsiKeyEnd,AnsiKeyShiftTab,AnsiKeyTab,AnsiKeyEscape
           LEA RDI,[%key]
           MOV CL,SIZE# %key
           MOV RSI,R8
           REPE CMPSB
           JE .%key:
        %ENDFOR key
        MOV RSI,R8               ; Read the mouse.
        LODSW
        CMP AX,0x5B1B            ; Esc [
        JNE .ReadKeyboard:
        LODSB
        CMP AL,0x3C              ; Less-than?
        JNE .ReadKeyboard:
        LodD                     ; Mouse button.
        JC  .ReadKeyboard:
        DEC EBX                  ; ListPos.
        CMP AL,64                ; Scroll wheel up?
        JE .Saturate:
        ADD EBX,1+1
        CMP AL,65                ; Scroll wheel down?
        JE .Saturate:
        MOV ECX,EAX              ; Not scrolled. CL=0 for left button; CL=2 for right button.
        LODSB
        CMP AL,';'
        JNE .ReadKeyboard:
        LodD
        JC .ReadKeyboard:
        MOV EBX,EAX              ; X-coordinate of mouse cursor.
        SHL EBX,16
        LODSB
        CMP AL,';'
        JNE .ReadKeyboard:
        LodD
        JC .ReadKeyboard:
        MOV BX,AX                ; Y-coordinate of mouse cursor.
        LODSB
        CMP AL,'m'
        JNE .ReadKeyboard:
        ; Mouse cursor coordinates are in EBX. Row number is in BX, button in CL.
        MOV EDX,EBX
        SHR EDX,16
        MOV EAX,[TermWidth]
        SUB EAX,3
        CMP DX,AX
        JA .Scroll:
        CMP CL,0
        JE .MouseLeftButton:
        CMP CL,2
        JE .MouseRightButton:
        JMP .ReadKeyboard:
    .Scroll:                       ; Clicked at scroll box, row BX. Level is not influenced by mouse buttons.
        MOVZX EAX,BX
        TEST EAX
        JZ .30:
        DEC EAX
    .30:MOV ECX,[ListMax]
        MUL RCX
        MOV ECX,[TermHeight]
        DIV RCX
        MOV [ListPos],EAX
        CALL WindowPaint
        JMP .ReadKeyboard:
    .AnsiKeyUp:
        DEC EBX
    .Saturate:TEST EBX
        JNS .60:
        SUB EBX,EBX
    .60:CMP EBX,[ListMax]
        JB .70:
        MOV EBX,[ListMax]
    .70:TEST EBX
        JNZ .75:
        INC EBX
    .75:MOV [ListPos],EBX
        CALL WindowPaint
        JMP .ReadKeyboard:
    .AnsiKeyDn:
        INC EBX
        JMP .Saturate:
    .AnsiKeyPgUp:
        SUB EBX,[TermHeight]
        ADD EBX,2
        JMP .Saturate:
    .AnsiKeyPgDn:
        ADD EBX,[TermHeight]
        SUB EBX,2
        JMP .Saturate:
    .AnsiKeyCtrlHome:
    .AnsiKeyHome:
        MOV EBX,0
        JMP .Saturate:
    .AnsiKeyCtrlEnd:
    .AnsiKeyEnd:
        MOV EBX,[ListMax::]
        SUB EBX,[DirHeight]
        ADD EBX,2
        JMP .Saturate:

    .MouseRightButton:                     ; Increase level.
    .AnsiKeyShiftTab:                      ; Shift Tab pressed.
        MOV EAX,[Level]
        CMP AL,4
        JAE .ReadKeyboard:
        INC AL
    .80:MOV [Level],EAX
        CALL WindowPaint
        JMP .ReadKeyboard:
    .MouseLeftButton:                      ; Decrease level.
    .AnsiKeyTab:                           ; Tab pressed.
        MOV EAX,[Level]
        CMP EAX,0
        JLE .ReadKeyboard:
        DEC AL
        JMP .80:

    ErrorHelp:
         StdOutput Help:,Eol=yes
         TerminateProgram 8
    ErrorFileOutput:
         LEA RSI,[FileOutput.Name]
         JMP ErrorFile:
    ErrorFileInput:
         LEA RSI,[FileInput.Name]
         JMP ErrorFile:
    ErrorFileIndex:
         LEA RSI,[FileOutput.Name]
    ErrorFile:
         StdOutput =B'File "',RSI,=U'" not found or empty.',Eol=yes
         JMP .AnsiKeyEscape:
    ErrorAlloc::
         StdOutput =B"Error on memory allocation.",Eol=yes
        JMP .AnsiKeyEscape:

    .AnsiKeyEscape:
        FileClose FileInput, FileOutput, FileIndex
        LEA RBX,[TermIO]
        LinABI ioctl,0,TCGETS,RBX          ; Get current terminal echo.
        SetSt [RBX+TERMIO.c_lflag],ICANON+ECHO
        LinABI ioctl,0,TCSETS,RBX          ; Restore terminal echo.
        RET
     ENDP WindowProc

CreateLstIndex
  This procedure will clear BUFFERs for each level (0..4) and then it will index the listing file (OutputPtr..OutputEnd) into those buffers.
  Buffers contain records in the form of LST_INDEX.
Input
  OutputPtr..OutputEnd is the listing mapped in memory.
Output
  CF=0, LstIndex is an empty variable of LST_INDEX structure which was saved to buffers.
  ListingLines is filled with the total number of lines in the listing.
Error
  CF=1 allocation error.

    CreateLstIndex: PROC
        BufferClear [Level0Buffer::],[Level1Buffer::],[Level2Buffer::],[Level3Buffer::],[Level4Buffer::]
        MOV RBX,[OutputPtr::]              ; Start of the listing in memory.
        XOR ECX,ECX
        MOV AL,10
        DEC RCX
        MOV RDX,RBX
    .10:MOV RDI,RDX
        CMP RDI,[OutputEnd::]
        JNB .80:
        MOV RSI,RDI
        REPNE SCASB                        ; Find the end of line.
        MOV RDX,RDI
        SUB RDI,RSI                        ; Size.
        SUB RSI,RBX                        ; FA.
        SUB EDI,2                          ; Omit CR+LF.
        MOV [LstIndex.FA],ESI
        MOV [LstIndex.Size],EDI
        BufferStore [Level0Buffer::],LstIndex,SIZE# LstIndex
        JC ErrorAlloc::
        CMPB [RBX+RSI+1],'#'               ; Is the line in Level1?
        JNE .10:
        BufferStore [Level1Buffer::],LstIndex,SIZE# LstIndex
        JC ErrorAlloc::
        CMPW [RBX+RSI+1],'##'              ; Is the line in Level2?
        JNE .10:
        BufferStore [Level2Buffer::],LstIndex,SIZE# LstIndex
        CMPB [RBX+RSI+3],'#'               ; Is the line in Level3?
        JNE .10:
        BufferStore [Level3Buffer::],LstIndex,SIZE# LstIndex
        CMPD [RBX+RSI+1],'####'            ; Is the line in Level4?
        JNE .10:
        BufferStore [Level4Buffer::],LstIndex,SIZE# LstIndex
        JMP .10:
    .80:BufferRetrieve [Level0Buffer::]
        SHR ECX,3                          ; SIZE# LstIndex = 8
        MOV [ListingLines::],ECX
        CLC
        RET
       ENDP CreateLstIndex

      ENDPROGRAM viewling

▲Back to the top▲