This is a GUI module of EuroTool program EuroView for Linux.
EUROASM CPU=X64, Unicode=No, DumpWidth=36
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,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:: 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: PROC
LEA RBX,[FileIndex]
FileClose RBX
FileMapCreate RBX ; Reopen and sort FileIndex. Returns the contents in RDI,RAX.
JC ErrorFileIndex:
RET
ENDP FileIndexReopen:
FileWriteOutput: PROC
FileWrite FileOutput,RSI,RCX
JC ErrorFileOutput:
RET
ENDP FileWriteOutput:
.Size, add .Size to .FA, clear .Level and
.Rem in this vairable.
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 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
File_iniin UTF-8 and parses its each line into configuration variables Arg*** in UTF-8, too.
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
ArgOutputFile(if not empty) or
/tmp/ArgInputFileName.lst,
/tmp/ArgInputFileName.lst.index(if ArgOutputFile= is empty).
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:: 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
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.
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
EuroView FF L "file".
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
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'Error in file "',RSI,=U'"',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: 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