EuroAssembler Index Manual Download Source Macros


Sitemap Links Forum Tests Projects

viewling.htm
Data
Data
Procedures
CreateLstIndex
FileIndexReopen
FileWriteOutput
FindEditor
FindWindowPaint
Main
ReadFile_ini
SaveViewIndex
Search
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, debug.htm
[.rodata]          ; Constant data.
Help:
 DB " EuroView is one of the EuroTool from https://euroassembler.eu/eurotool/",10
 DB "  which can be use to inspect binary, object, library or executable ""InputFile"":",10
 DB "      ./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/",10
 DB 9,"-FileFormat=      ",9,9,"Default is autodetect.",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,"F",9,9,9,9,"find a text string.",10
 DB 9,"N",9,9,9,9,"find the next occurence",10
 DB 9,"P",9,9,9,9,"find the previous occurence",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,"close window, terminate program.",10
 DB 0
FormatNames:
FF %FOR %FileFormats
     DB "%FF",0
   %ENDFOR FF
EndFormatNames:
Spaces            DB NAME_MAX * 2 * BYTE ' '
[.data]           ; Variable data.
TimeSpec1         DS TIMESPEC, .tv_sec=1, .tv_nsec=200_000_000
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 ; Terminal width in columns.
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.
FoundCnt          DD DWORD ; How many times was the string Find$ found in output file.
FindCursor        DD DWORD ; Offset of cursor from the beginning of edit field 0,1,2....
Find$Size         DD DWORD ; Size of the string to find in bytes.
FindEditLen       DD DWORD ; Size of find-edit field in characters.
FindEditWidth     DD DWORD ; Maximal size of visible editor field.
                  ALIGN 16
FindEdit          DB 256* BYTE ; Searched string being edited.
Find$             DB 256* BYTE ; Searched string final version, approved by Enter in Find dialogue.
KeyBuffer         DB 32 * BYTE ; Buffer for one character read from keyboard.
[.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.
    BufferCreate Size=64
    JC ErrorAlloc:
    MOV [ExportBuffer::],RAX
    ; Create five 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 its dimensions changed or when it is too small.
Callled by
Main, WindowProc
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
Linux 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 (a class="EXT" href="viewmain.htm#Data">VIEW_INDEX ) of listing lines to LevelnBuffers in memory.
Input
OutputPtr..OutputEnd
listing lines as plain text mapped to memory.
Output
CF=0LevelnBuffer (n=0..4) was written in memory.
Error
CF=1
Calls
CreateLstIndex
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
Procedure WindowPaint will paint the entire terminal Linux 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.
Contents of the first line in terminal (title row) is fixed, it shows the program name, file name, file format, nesting level (0..4) and how many times was a serched string found, for instance
EuroView "file.o" as ELF32 level 0. Found 0× "".
Vertical position of the displayed section 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; Black foreground.
    MOV R12,[OutputPtr::]    ; Where is the text mapped in memory.
    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.
.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        ; Number of lines in output.
    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 .55:
    MOV ESI,[RBX+LST_INDEX.FA]
    MOV ECX,[RBX+LST_INDEX.Size]
    AND ECX,NoFlags
    ADD RSI,[OutputPtr::]
    CMP RCX,R13
    JBE .55:
    MOV RCX,R13              ; Line is long, its size will be limited to RCX=TermWidth.  Number of following spaces will be R13=0
    SUB R13,R13
    JMP .60:
.55: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 in R13.
    ADD RBX,SIZE# LST_INDEX  ; Line is painted. Go to paint the next line.
    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 single row. Cursor was put at first column of the desired row.
; 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 following spaces. RBX=^LST_INDEX
    TEST RCX
    JZ .8:
    MOV R9,RSI
    LEA RDI,[RSI+1]          ; Characters at the beginning of line specify its level (color).
    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 an ordinary Level0 row with a dump. Paint it gray. 
    MOV AL,'|'
    MOV R8,RCX
    REPNE SCASB              ; Find the second pipe '|' which terminates the dump.
    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; Continue in yellowish 
    JMP .7:
.3: LEA RDI,[AnsiClrBgD0D0FF];   blue 
    CMP [RSI+4],AL
    JE .5:
    LEA RDI,[AnsiClrBgFFD0D0];   red 
    CMP [RSI+3],AL
    JE .5:
    LEA RDI,[AnsiClrBgFFFF30];   yellow 
    CMP [RSI+2],AL
    JE .5:
    LEA RDI,[AnsiClrBgD0FFD0];   green 
.5  StdOutput RDI            ; Color1..4.
.7: StdOutput RSI,Size=RCX   ; Paint the colorfull level row.
.8: StdOutput Spaces,Size=R13; Complete with spaces.
    StdOutput AnsiClrBgC0C0C0;   gray 
.9: LEA RDI,[KeyBuffer]
    MOV AX,0x5B1B            ; Esc [
    STOSW
    MOV EAX,[RBX+LST_INDEX.Size]
    SHR EAX,24               ; RCX=FA of found string related to start of line. 0 if no string was found at the line RBX.
    JZ .99:
    MOV RSI,R9
    LEA RSI,[RSI+RAX-1]
    StoD RDI
    MOV AX,0x0047            ; G
    STOSW
    StdOutput KeyBuffer      ; Put the cursor at column.
    MOV ECX,[Find$Size]
    JRCXZ .99:
    StdOutput AnsiClrBgFFFFFF,AnsiClrFgFF00FF
    StdOutput RSI,Size=RCX
    StdOutput AnsiClrBgC0C0C0,AnsiClrFg000000
.99:RET
  ENDP .RowPaint
 ENDP WindowPaint
WindowTitle
Construct terminal window one line title which contains EuroView "input.bin" as BIN level 0. Found 0× "".
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 AL,'0'
    OR AL,[Level]
    STOSB
    LEA RSI,[=B'. Found ']
    MOV CL,8
    REP MOVSB
    MOV EAX,[FoundCnt]
    StoD RDI
    MOV EAX,0x222097C3       ; × "
    STOSD
    LEA RSI,[Find$]
    GetLength$ RSI
    MOV [Find$Size],ECX
.45:LODSB
    CMP AL,0
    JE .48:
    STOSB
    JMP .45:
.48:MOV AX,'"'
    STOSW
.50:MOVD [AnsiAtRowCol+2],'1;1H'
    MOVB [AnsiAtRowCol+6],0
    StdOutput AnsiClrBgFFFFFF,AnsiClrFg800000,AnsiAtRowCol
    MOV EDX,[TermWidth]
    StdOutput Spaces,Size=RDX
    StdOutput AnsiAtRowCol,WorkMemory
.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:

.NoMore:
    ; Paint double frame around NoMore box:
    StdOutput AnsiClrBgFFFFFF,AnsiClrFgFF00FF,AnsiRow4,AnsiCol4,AnsiBox2DR
    MOV ECX,36
.M2:StdOutput AnsiBox2H
    LOOP .M2:
    StdOutput AnsiBox2DL,AnsiRow5,AnsiCol4,AnsiBox2V
    StdOutput =B' Next|Previous occurence not found. '       ; NoMore text.
    StdOutput AnsiBox2V,AnsiRow6,AnsiCol4,AnsiBox2UR
    MOV ECX,36
.M3:StdOutput AnsiBox2H
    LOOP .M3:
    StdOutput AnsiBox2UL
    LinABI nanosleep, TimeSpec1,0
.Resized:
    CALL WindowResize
.Paint:
    CALL WindowPaint
    MOV EBX,[ListPos]
    JMP .Saturate:

.AnsiKeyCtrlF:
.f:
.F: ; Find a text string in the output file. Position at the 1st occurence, if found.
    CALL FindWindowPaint
    CALL FindEditor                    ; Get string Find$.
    JC .Paint:                         ; CF=cancel. Repaint screen; do not search.
    PUSH RBX
     CALL Search                       ; Mark LST_INDEX.Size with FAFound bits.
    POP RBX
    CALL WindowTitle
    MOV EDX,[Level]                    ; 0..4.
    BufferRetrieve [8*RDX+Level0Buffer::]  ; RSI,RCX is an array of LST_INDEX.
    LEA RDX,[RSI+RCX]                  ; End of the array.
    MOV EBX,-1                         ; ListPos.
    SUB RSI,SIZE# LST_INDEX
.FF:INC EBX
    ADD RSI,SIZE# LST_INDEX
    CMP RSI,RDX
    JNB .NoMore:                       ; No more found.
    MOV ECX,[RSI+LST_INDEX.Size]
    SHR ECX,24
    JZ .FF:
    INC EBX
    JMP .Saturate:

.AnsiKeyCtrlN:
.n:
.N: ; Find the next occurence.
    MOV EDX,[Level]                    ; 0..4.
    BufferRetrieve [8*RDX+Level0Buffer::]  ; RSI,RCX is an array of LST_INDEX.
    LEA RDX,[RSI+RCX]                  ; End of the array.
    MOV EBX,[ListPos]
    LEA RSI,[RSI+8*RBX]
.NF:INC EBX
    ADD RSI,SIZE#LST_INDEX
    CMP RSI,RDX
    JNB .NoMore:                       ; No more found.
    MOV ECX,[RSI+LST_INDEX.Size]
    SHR ECX,24
    JZ .NF:
    INC EBX
    JMP .Saturate:

.AnsiKeyCtrlP:
.p:
.P: ; Find the previous occurence.
    MOV EDX,[Level]
    BufferRetrieve [8*RDX+Level0Buffer::]  ; RSI,RCX is an array of LST_INDEX.
    MOV RDX,RSI                        ; Begining of the array.
    MOV EBX,[ListPos]
    DEC EBX
    LEA RSI,[RSI+8*RBX]
.PF:DEC EBX
    JZ .NoMore:
    SUB RSI,SIZE#LST_INDEX
    CMP RSI,RDX
    JB .NoMore:
    MOV ECX,[RSI+LST_INDEX.Size]
    SHR ECX,24
    JZ .PF:
    INC EBX
    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]
    MOV DL,[RSI]
    Dispatch DL,'f','F','n','N','p','P'

key %FOR AnsiKeyCtrlHome,AnsiKeyCtrlEnd,AnsiKeyPgUp,AnsiKeyPgDn,AnsiKeyUp,AnsiKeyDn, \  Read the keyboard.
         AnsiKeyHome,AnsiKeyEnd,AnsiKeyShiftTab,AnsiKeyTab,AnsiKeyCtrlF,AnsiKeyCtrlP,AnsiKeyCtrlN,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             ; Saturate: Keep EBX in the range 0..ListMax-1.
    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                          ; EOL character.
    DEC RCX
    MOV RDX,RBX
.10:MOV RDI,RDX                        ; Start of physical line.
    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            ; Line size (it is never above 0x0FFF_FFFF).
    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
FindWindowPaint
Procedure FindWindowPaint will draw a small window in the terminal to set or edit the string to find (Find$).
It paints a double-framed rectangle at fixed coordinates 4, 4, 8, TermWidth-4 with the string FindEdit initialized from Find$.
Called by
WindowProc
FindWindowPaint PROC
    MOV EAX,[TermWidth]  ; 0x7F
    SUB EAX,12
    MOV [FindEditWidth],EAX  ; 0x67
    LEA RSI,[Find$]      ; Copy Find$ to FindEdit.
    LEA RDI,[FindEdit]
.05:LODSB
    STOSB
    CMP AL,0
    JNE .05:
    ; Paint double frame around Find box:
    StdOutput AnsiClrBgFFFFFF,AnsiClrFg000000,AnsiRow4, AnsiCol4,AnsiBox2DR
    MOV ECX,[TermWidth]
    MOVB [FindEdit+RCX-3],0
    SUB ECX,9
    MOV EDX,ECX
.10:StdOutput AnsiBox2H
    LOOP .10:
    StdOutput AnsiBox2DL,AnsiRow5,AnsiCol4,AnsiBox2V
    StdOutput Spaces,Size=RDX
    StdOutput AnsiBox2V,AnsiRow6,AnsiCol4,AnsiBox2V
    StdOutput Spaces,Size=RDX
    StdOutput AnsiBox2V,AnsiRow7,AnsiCol4,AnsiBox2UR
    MOV ECX,EDX
.20:StdOutput AnsiBox2H
    LOOP .20:
    StdOutput AnsiBox2UL,AnsiRow5,AnsiCol6,AnsiClrFg808080,=B'Enter the text string to find.  Then use keys N|P to find next|previous occurence'
    StdOutput AnsiRow6,AnsiCol6,AnsiClrFgFF00FF,FindEdit
    RET
   ENDP FindWindowPaint
FindEditor
Procedure FindEditor reads ANSI characters from keyboard which edit the string FindEdit being edited in a rectangle painted by FindWindowPaint.
String is edited at row 6, col 6. Initial cursor position is in FindCursor (at the end of string).
Input
Find$ is the initial string to search.
Output
CF=0 Editor terminated with Enter, FindEdit string is copied to Find$.
CF=1 Editor was cancelled with Esc key; nothing is copied to Find$.
Called by
WindowProc
FindEditor PROC
    GetLengthUTF8 FindEdit
    MOV [FindEditLen],ECX
    MOV [FindCursor],ECX

.Read:
    StdOutput AnsiRow6,AnsiCol6,FindEdit
    CALL .ShowCursor:
    XOR EDI,EDI                         ; Read the keyboard in the edit window.
    LEA RSI,[KeyBuffer]
    MOV R8,RSI
    MOV [RSI],RDI
    MOV EDX,SIZE# KeyBuffer
    LinABI read,RDI,RSI,RDX
    TEST EAX
    JNA .Read:
    XOR ECX,ECX               ; Key is at RSI=R8, its size=RAX.
  key %FOR AnsiKeyEnter,AnsiKeyLineFeed,AnsiKeyEscape,AnsiKeyLeft,AnsiKeyRight,AnsiKeyBackspace, \
           AnsiKeyDelete,AnsiKeyDelete2,AnsiKeyHome,AnsiKeyEnd,AnsiKeyCtrlDelete
       LEA RDI,[%key]
       MOV CL,SIZE# %key
       MOV RSI,R8
       REPE CMPSB
       JE .%key:
      %ENDFOR key
    MOV RSI,R8                       ; Special keys were dispatched.
    CMPB [RSI],27
    JE .Read:                        ; Ignore other characters which start with Esc.
    ; RSI points to a pressed ordinary key (letter). RAX is its UTF-8 size 1..4.
    ; Make room for RAX bytes at [FindCursor] by right-shift the text between [FindCursor]..[FindCursorSize+RAX].
    PUSH RAX,RSI
      LEA RDX,[FindEdit]
      MOV RSI,RDX
      GetLength$ RDX                 ; Return RCX=size of text in FindEdit up to NUL in bytes.
      ADD RSI,RCX
      LEA RDI,[RSI+RAX]
      CALL .Cursor2Pos:            ;  Return RCX=position in bytes in FindEdit corresponding with [FindCursor].
      ADD RDX,RCX
      LEA RCX,[RSI+1]
      SUB RCX,RDX
      STD
      REP MOVSB
      CLD
    POP RSI,RAX
    CALL .Cursor2Pos:    ; Return RCX=FindEditSize in bytes corresponding to FindEditLen.
    LEA RDI,[FindEdit+RCX]
    MOV RCX,RAX
    REP MOVSB
    INC [FindCursor]
    JMP .Read:

.AnsiKeyCtrlDelete:                    ; Erase all FileEdit field.
     MOVB [FindEdit],0
     StdOutput AnsiRow6,AnsiCol6
     MOV ECX,TermWidth
     SUB EDX,6+6
     StdOutput Spaces,Size=RDX
     MOV [FindCursor],0
     CALL .ShowCursor
     JMP .Read:
.AnsiKeyHome:
     MOV [FindCursor],0
     JMP .Read:
.AnsiKeyEnd:
     GetLengthUTF8 FindEdit
     MOV [FindCursor],ECX
     JMP .Read:
.AnsiKeyLeft:
    MOV EAX,[FindCursor]
    DEC EAX
    JS .Read:
    MOV [FindCursor],EAX
    CALL .ShowCursor:
    JMP .Read:
.AnsiKeyRight:
    CALL .Cursor2Pos:
    LEA RSI,[FindEdit+RCX]
    LODSB
    CMP AL,0
    JNE .R1:
    MOVB [RSI-1],' '
.R1:MOV EAX,[FindCursor]
    INC EAX
    CMP EAX,[FindEditWidth]
    JA .Read:
    MOV [FindCursor],EAX
    CALL .ShowCursor:
    JMP .Read:

.AnsiKeyDelete:
    INC [FindCursor]
    CALL .Cursor2Pos:   ;  Return RCX=position in bytes in FindEdit corresponding with [FindCursor].
    LEA RSI,[FindEdit+RCX]
    DEC [FindCursor]
    CALL .Cursor2Pos:  ;  Return RCX=position in bytes in FindEdit corresponding with [FindCursor].
    LEA RDI,[FindEdit+RCX]
    LEA RCX,[FindEdit+SIZE#FindEdit+1]
    SUB RCX,RSI
    REP MOVSB
    CALL .ShowField:
    JMP .Read:

.AnsiKeyDelete2:
.AnsiKeyBackspace:
    CALL .Cursor2Pos:   ;  Return RCX=position in bytes in FindEdit corresponding with [FindCursor].
    LEA RSI,[FindEdit+RCX]
    MOV EAX,[FindCursor]
    DEC EAX
    JS .Read:
    MOV [FindCursor],EAX
    CALL .Cursor2Pos:   ;  Return RCX=position in bytes in FindEdit corresponding with [FindCursor].
    LEA RDI,[FindEdit+RCX]
    LEA RCX,[FindEdit+SIZE#FindEdit+1]
    SUB RCX,RSI
    REP MOVSB
    CALL .ShowField:
    JMP .Read:

.AnsiKeyLineFeed:
.AnsiKeyEnter:               ; Save changes to Find$.
    LEA RSI,[FindEdit]
    LEA RDI,[Find$]
.E1:LODSB
    STOSB
    CMP AL,0
    JNE .E1:
.90:GetLength$ Find$
    MOV [Find$Size],ECX
    RET                      ; Return CF=0.

.AnsiKeyEscape:              ; Ignore changes.
    STC
    RET                      ; Return CF=1.

.ShowField: PROC             ; Display FindEdit up to NUL and then spaces.
    MOV EDX,[TermWidth]
    SUB EDX,6+6
    LEA RDI,[FindEdit]
    StdOutput AnsiRow6,AnsiCol6,RDI
    GetLength$ RDI
    SUB EDX,ECX
    JNA .9:
    StdOutput Spaces,Size=RDX
.9: RET
   ENDP .ShowField:

.Cursor2Pos: PROC          ;  Return RCX=position in bytes in FindEdit corresponding with [FindCursor].
    PUSH RAX,RSI
    LEA RSI,[FindEdit]
    MOV ECX,[FindCursor]   ; Length in characters 0..
    JRCXZ .9:
.0: LODSB                  ; Load UTF-8 character.
    OR  AL,0000_0111b
    CMP AL,1111_0111b
    JE .4                  ; Three more bytes follow.
    OR  AL,0000_1111b
    CMP AL,1110_1111b
    JE .3:                 ; Two more bytes follow.
    OR  AL,0001_1111b
    CMP AL,1101_1111b
    JE .2:                 ; One more byte follows.
    JMP .1:                ; Otherwise no extra byte follows.
.4: INC RSI
.3: INC RSI
.2: INC RSI
.1: LOOP .0:
.9: LEA RCX,[FindEdit]
    XCHG RCX,RSI
    SUB RCX,RSI
    POP RSI,RAX
    RET
   ENDP .Cursor2Pos:

.ShowCursor: PROC ; Display cursor at [FindCursor]. Clobbers RAX,RDI.
    LEA RDI,[KeyBuffer]
    MOV AX,0x5B1B            ; Esc [
    STOSW
    MOV EAX,[FindCursor]     ; 0..
    ADD EAX,6                ; Offset of 0-th character from left screen edge.
    StoD RDI
    MOV AX,0x0047            ; G
    STOSW
    StdOutput KeyBuffer
    RET
   ENDP .ShowCursor:

  ENDP FindEditor
Search  PROC
    XOR EAX,EAX
    MOV [FoundCnt],EAX
    CMPB [Find$],AL
    JE .90:
lvl %FOR 0..4                          ; The string Find$ is not empty. Search all five buffers.
      MOV RBX,[Level%lvl{}Buffer]
      CALL .SearchBuffer:
    %ENDFOR
.90: RET

.SearchBuffer: PROC
    BufferRetrieve RBX                 ; RSI,RCX is array of LST_INDEX records.
    MOV R15,RSI                        ; Beginning of buffer contents.
    LEA R14,[RSI+RCX]                  ; End of buffer contents.
    MOV R13,[OutputPtr::]              ; Start of output file contents mapped to memory.
    LEA RSI,[Find$]                    ; The needle to search for.
    MOV ECX,[Find$Size]
    TEST ECX
    JZ .90:
    LODSB                              ; AL is 1st letter of the needle.
    MOV R12,RSI                        ; Pointer to needle plus one.
    LEA R11,[RCX-1]                    ; Size of needle minus one.
.10:CMP R15,R14
    JNB .90:                           ; When at end of buffer.
    MOV EDI,[R15+LST_INDEX.FA]
    MOV ECX,[R15+LST_INDEX.Size]
    MOV R10,RDI                        ; FA of start of the line.
    ADD RDI,R13
    AND ECX,NoFlags
    MOV [R15+LST_INDEX.Size],ECX       ; Clear FAFound.
.30:REPNE SCASB                        ; Find the 1st letter of needle=Find$ in RDI,RCX.
    JNE .70:
    PUSH RDI,RCX                       ; 1st letter was found. Compare the rest of needle.
      MOV RCX,R11
      MOV RSI,R12
      REPE CMPSB
    POP RCX,RDI
    JNE .30:
    SUB RDI,R13                        ; Find$ was found.
    SUB RDI,R10
    OR [R15+LST_INDEX.Size+3],DIL      ; Mark its offset in LST_INDEX record.
    CMP RBX,[Level0Buffer]
    JNE .70:
    INC [FoundCnt]
.70:ADD R15,SIZE# LST_INDEX            ; Index of the next output line.
    JMP .10:
.90:RET
  ENDP .SearchBuffer:
 ENDP Search
%IF %^DEBUG
 INCLUDE1 linabi.htm
DebugOutput PROC
  StdOutput RSI,Size=RCX
  RET
 ENDP DebugOutput
%ENDIF

  ENDPROGRAM viewling

▲Back to the top▲