This is a GUI module of EuroTool program EuroConv for Linux.
EUROASM CPU=X64,Unicode=No
convling PROGRAM Format=coff,Width=64
%DROPMACRO *
INCLUDEHEAD argument.htm
INCLUDE1 linabi.htm, cpuext.htm, cpuext64.htm, lins.htm
INCLUDE1 string64.htm, time.htm, status32.htm
; Constants.
MinRows EQU 30 ; Minimal terminal dimensions.
MinCols EQU 56
NAME_MAX EQU 256
EDIT STRUC ; A structure for passing parameters for procedures EditField and EditButton.
.Address D QWORD ; Address of the field in memory. The field is in UTF-8, NUL-terminated.
.MaxSize D WORD ; Maximal possible size of the field in memory (bytes).
.ScreenSize D WORD ; Size of the visible field on the screen.
.ScreenRow D WORD ; Row of the edit field in the terminal window (1, 2, 3,,30).
.ScreenCol D WORD ; Left column of the edit field in the terminal window (1, 2, 3,,).
ENDSTRUC EDIT
[.rodata] ; Constant data.
; Zero-terminated ANSII strings:
BoxV DB BYTE '│',0 ; BOX DRAWINGS LIGHT VERTICAL 2502
BoxDR DB BYTE '┌',0 ; BOX DRAWINGS LIGHT DOWN AND RIGHT 250C
BoxDL DB BYTE '┐',0 ; BOX DRAWINGS LIGHT DOWN AND LEFT 2510
BoxUR DB BYTE '└',0 ; BOX DRAWINGS LIGHT UP AND RIGHT 2514
BoxUL DB BYTE '┘',0 ; BOX DRAWINGS LIGHT UP AND LEFT 2518
Box2V DB BYTE '║',0 ; BOX DRAWINGS DOUBLE VERTICAL 2551
Boxes DB NAME_MAX*2*BYTE '─' ; BOX DRAWINGS LIGHT HORIZONTAL 2500
Checked DB '■',0 ; BLACK SQUARE 25A0
Unchecked DB '□',0 ; WHITE SQUARE 25A1
Space4 DB 4 * BYTE ' ',0
Space1 EQU Space4+3
Spaces DB NAME_MAX * 2 * BYTE ' ',0
Box16U DB '┌────────────────┐',0
Box16M DB '│ │',0
Box16D DB '└────────────────┘',0
Box12U DB '┌──────────┐',0
Box12M DB '│ │',0
Box12D DB '└──────────┘',0
Box11U DB '╔═════════╗',0
Box11D DB '╚═════════╝',0
EscRight DB 27,'[C'
EscLeft DB 27,'[D'
EscHome DB 27,'[H'
EscEnd DB 27,'[F'
EscShiftTab DB 27,'[Z'
EscDelete DB 27,'[3~'
EscBaseColor:: DB 27,'[30;47m',0 ; Zero-terminated sequences for writing to terminal.
EscDefColor:: DB 27,'[39;49m',0
EscEnhColor:: DB 27,'[38;5;160m',0
EscDimColor DB 27,'[38;5;243m',0
EscEditColor DB 27,'[30;107m',0
EscErase:: DB 27,'[2J',0
EscEscape DB 27,0
EscEnableMouse DB 27,'[?1000;1006;1015h',0
EscDisableMouse:: DB 27,'[?1000;1006;1015l',0
EscHideCursor DB 27,'[?25l',0
EscShowCursor:: DB 27,'[?25h',0
EscTab DB 9
[.data] ; Variable data.
TabSelected DD -5 ; 0,5,10,,5*(TabSize-1) index of jump on Tab/ShiftTab
EscResize DB 27,'[8;'
ValResize DB 'xxxxxxxxx' ; Replaced by '30;150t',0
EscGotoInputFile DB 27,'[4;2H',0 ; Position of InputFile on screen.
EscGotoOutputFile DB 27,'[19;2H',0 ; Position of OutputFile on screen.
EscGotoHeaderSize DB 27,'[9;xxxH',0 ; Position of header size on screen. Updated by PaintWindow.
EscGotoHeaderLength DB 27,'[9;xxxH',0 ; Position of header length on screen.
EscGotoFooterSize DB 27,'[9;xxxH',0 ; Position of footer size on screen.
EscGotoFooterLength DB 27,'[9;xxxH',0 ; Position of footer length on screen.
EscGotoInputEncoding DB 27,'[14;2H',0 ; Position of input encoding on screen.
EscGotoOutputEncoding DB 27,'[24;2H',0 ; Position of output encoding on screen.
EscGotoHEI DB 27,'[13;21H',0 ; Position of radiobuttons on screen.
EscGotoHEN DB 27,'[14;21H',0
EscGotoHEC DB 27,'[15;21H',0
EscGotoICT DB 27,'[23;21H',0
EscGotoICC DB 27,'[24;21H',0
EscGotoICQ DB 27,'[25;21H',0
EscGotoICO DB 27,'[23;47H',0
EscGotoBOM DB 27,'[25;47H',0
EscGoto DB 27,'[' ; Ad hoc position on screen.
EscGotoRowColH DB 'row;colH',0
line %FOR 1..30 ; Define goto EscLine1, EscLine2 etc.
EscLine%line DB 27,'[%line{}H',0
%ENDFOR line
GuiHeaderSize DB (10+1)*BYTE 0 ; Arguments adjusted for GUI screen.
GuiHeaderLength DB (10+1)*BYTE 0
GuiFooterSize DB (10+1)*BYTE 0
GuiFooterLength DB (10+1)*BYTE 0
IE:: DB '-IE=' ; Used by ArgParse.
GuiInputEncoding DB 16*BYTE 0,0
OE:: DB '-OE='
GuiOutputEncoding DB 16*BYTE 0,0
TxtExit DB " Exit ",0 ; Text on button.
TxtConvert DB " Convert ",0 ; Text on button.
[.bss] ; Working data.
Edit DS EDIT
TtySize DS TTYSIZE
TermIO:: DS TERMIO
MainWidth D DWORD ; Width of the main window in characters.
MainHeight D DWORD ; Number of lines in the main window.
GapFH D DWORD ; Spaces between Header/Footer fields.
OffsetHeaderSize D DWORD
OffsetHeaderLength D DWORD
OffsetFooterSize D DWORD
OffsetFooterLength D DWORD
KeyBuffer D 32*BYTE ; Buffer for reading the keyboard.
[.text]
MainGui:: PROC
CALL PaintWindow
CALL Arg2Gui ; Convert numeric arguments to decimal form and show current arguments on screen.
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 EscEnableMouse
.10: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 .10:
XOR ECX,ECX
key %FOR EscShiftTab,EscTab,EscEscape
LEA RDI,[%key]
MOV CL,SIZE# %key
MOV RSI,R8 ; KeyBuffer.
REPE CMPSB
JE .%key:
%ENDFOR key
MOV RSI,R8 ; Read the mouse. RSI is KeyBuffer.
LODSW
CMP AX,0x5B1B ; Esc [
JNE .10:
LODSB
CMP AL,0x3C ; Less-than?
JNE .10:
LodD ; Mouse button.
JC .10:
CMP AL,0 ; Left button?
JNE .10:
LODSB
CMP AL,';'
JNE .10:
LodD
JC .10:
MOV EBX,EAX ; X-coordinate of mouse cursor.
SHL EBX,16
LODSB
CMP AL,';'
JNE .10:
LodD
JC .10:
MOV BX,AX ; Y-coordinate of mouse cursor.
LODSB
CMP AL,'m'
JNE .10:
CMP BX,3 ; Mouse cursor coordinates are in EBX. Row number is in BX.
JB .10:
CMP BX,5
JA .20:
.TabIF: ; Input file clicked.
LEA RSI,[ArgInputFile::]
MOV [Edit.Address],RSI
MOV [Edit.MaxSize],NAME_MAX
MOV EAX,[MainWidth]
SUB EAX,2
MOV [Edit.ScreenSize],AX
MOV [Edit.ScreenRow],4
MOV [Edit.ScreenCol],2
CALL EditField
CALL Arg2Gui
JMP .10:
.20:CMP BX,7
JB .10:
CMP BX,10
JA .40:
SHR EBX,16 ; EBX=Column. Header/Footer at row 9 clicked. EBX is the column on screen.
MOV EAX,[OffsetHeaderSize]
CMP EBX,EAX
JB .10:
LEA ECX,[EAX+10]
CMP EBX,ECX
JA .30:
.TabHS:
MOV EAX,[OffsetHeaderSize]
MOV [Edit.ScreenCol],AX
LEA RSI,[GuiHeaderSize]
MOV [Edit.Address],RSI
.28:MOV [Edit.MaxSize],10
MOV [Edit.ScreenSize],10
MOV [Edit.ScreenRow],9
CALL EditField
CALL Gui2Arg
CALL Arg2Gui
JMP .10:
.30:MOV EAX,[OffsetHeaderLength]
CMP EBX,EAX
JB .10:
LEA ECX,[EAX+10]
CMP EBX,ECX
JA .33:
.TabHL:
MOV EAX,[OffsetHeaderLength]
MOV [Edit.ScreenCol],AX
LEA RSI,[GuiHeaderLength]
MOV [Edit.Address],RSI
JMP .28:
.33:MOV EAX,[OffsetFooterSize]
CMP EBX,EAX
JB .10:
LEA ECX,[EAX+10]
CMP EBX,ECX
JA .38:
.TabFS:
MOV EAX,[OffsetFooterSize]
MOV [Edit.ScreenCol],AX
LEA RSI,[GuiFooterSize]
MOV [Edit.Address],RSI
JMP .28:
.38:MOV EAX,[OffsetFooterLength]
CMP EBX,EAX
JB .10:
LEA ECX,[EAX+10]
CMP EBX,ECX
JA .10:
.TabFL:
MOV EAX,[OffsetFooterLength]
MOV [Edit.ScreenCol],AX
LEA RSI,[GuiFooterLength]
MOV [Edit.Address],RSI
JMP .28:
.40:CMP BX,13
JB .10:
CMP BX,15
JA .50:
MOV ECX,EBX
SHR ECX,16
CMP ECX,19
JA .43:
.TabIE: ; Clicked at input encoding field.
LEA RSI,[GuiInputEncoding]
MOV [Edit.Address],RSI
MOV [Edit.ScreenRow],14
MOV [Edit.ScreenCol],2
MOV [Edit.ScreenSize],15
MOV [Edit.MaxSize],165
CALL EditField
CALL Gui2Arg
CALL Arg2Gui
JMP .10:
.43:Dispatch BX,0n13,0n14,0n15 ; Clicked at radiobutton HEC|HEN|HEI
.0n13:
.TabHEI:
LEA RSI,[Space1]
MOV [Edit.Address],RSI
MOV [Edit.ScreenRow],13
MOV [Edit.ScreenCol],22
MOV [Edit.MaxSize],1
MOV [Edit.ScreenSize],1
CALL EditButton
JNC .10:
LEA RSI,[=B'Ignore']
.48:LEA RDI,[ArgHtmlEntities::]
MOV ECX,10
REP MOVSB
CALL Arg2Gui
JMP .10:
.0n14:
.TabHEN:
LEA RSI,[Space1]
MOV [Edit.Address],RSI
MOV [Edit.ScreenRow],14
MOV [Edit.ScreenCol],22
MOV [Edit.MaxSize],1
MOV [Edit.ScreenSize],1
CALL EditButton
JNC .10:
LEA RSI,[=B'Non-ASCII']
JMP .48
.0n15:
.TabHEC:
LEA RSI,[Space1]
MOV [Edit.Address],RSI
MOV [Edit.ScreenRow],15
MOV [Edit.ScreenCol],22
MOV [Edit.MaxSize],1
MOV [Edit.ScreenSize],1
CALL EditButton
JNC .10:
LEA RSI,[=B'Convert']
JMP .48:
.50:CMP BX,18
JB .10:
CMP BX,20
JA .53:
.TabOF: ; Output file clicked.
LEA RSI,[ArgOutputFile::]
MOV [Edit.Address],RSI
MOV [Edit.MaxSize],NAME_MAX
MOV EAX,[MainWidth]
SUB EAX,2
MOV [Edit.ScreenSize],AX
MOV [Edit.ScreenRow],19
MOV [Edit.ScreenCol],2
CALL EditField
CALL Arg2Gui
JMP .10:
.53:CMP BX,23
JB .10:
CMP BX,25
JA .75:
MOV ECX,EBX ; Clicked at row 24: OE|ICT|ICO|ICC|ICQ|BOM.
SHR ECX,16
CMP CX,19
JA .58:
.TabOE: ; Clicked at output encoding field.
LEA RSI,[GuiOutputEncoding]
MOV [Edit.Address],RSI
MOV [Edit.ScreenRow],24
MOV [Edit.ScreenCol],2
MOV [Edit.ScreenSize],15
MOV [Edit.MaxSize],15
CALL EditField
CALL Gui2Arg
CALL Arg2Gui
JMP .10:
.58:CMP CX,45
JA .65:
Dispatch BX,0n23,0n24,0n25 ; Clicked at radiobutton ICT|ICC|ICQ
.0n23:
.TabICT:
LEA RSI,[Space1]
MOV [Edit.Address],RSI
MOV [Edit.ScreenRow],23
MOV [Edit.ScreenCol],22
MOV [Edit.MaxSize],1
MOV [Edit.ScreenSize],1
CALL EditButton
JNC .10:
LEA RSI,[=B'Transliterate']
.60:LEA RDI,[ArgInvalidCharacter::]
MOV ECX,18
REP MOVSB
CALL Arg2Gui
JMP .10:
.0n24:
.TabICC:
LEA RSI,[Space1]
MOV [Edit.Address],RSI
MOV [Edit.ScreenRow],24
MOV [Edit.ScreenCol],22
MOV [Edit.MaxSize],1
MOV [Edit.ScreenSize],1
CALL EditButton
JNC .10:
LEA RSI,[=B'Convert to entity']
JMP .60:
.0n25:
.TabICQ:
LEA RSI,[Space1]
MOV [Edit.Address],RSI
MOV [Edit.ScreenRow],25
MOV [Edit.ScreenCol],22
MOV [Edit.MaxSize],1
MOV [Edit.ScreenSize],1
CALL EditButton
JNC .10:
LEA RSI,[=B'Question mark']
JMP .60:
.65:CMP BX,23
JNE .70:
.TabICO:
LEA RSI,[Space1]
MOV [Edit.Address],RSI
MOV [Edit.ScreenRow],23
MOV [Edit.ScreenCol],48
MOV [Edit.MaxSize],1
MOV [Edit.ScreenSize],1
CALL EditButton
JNC .10:
LEA RSI,[=B'Omit from output']
JMP .60:
.70:CMP BX,25
JNE .10:
.TabBOM:
LEA RSI,[Space1]
MOV [Edit.Address],RSI
MOV [Edit.ScreenRow],25
MOV [Edit.ScreenCol],48
MOV [Edit.MaxSize],1
MOV [Edit.ScreenSize],1
CALL EditButton
JNC .10:
InvSt [Status::],ArgBOM
CALL Arg2Gui
JMP .10:
.75:CMP BX,27
JB .10:
CMP BX,29
JA .10:
SHR EBX,16 ; Clicked at [Exit] or [Convert].
CMP EBX,12
JB .TabExit:
MOV EAX,[MainWidth]
SUB EAX,10
CMP EBX,EAX
JB .10:
.TabConvert:
MOV EAX,[MainWidth]
SUB EAX,10
INC EAX
MOV [Edit.ScreenCol],AX
MOV [Edit.Address],TxtConvert
MOV [Edit.MaxSize],9
MOV [Edit.ScreenSize],9
MOV [Edit.ScreenRow],28
CALL EditButton
JNC .10:
RstSt [Status::],ArgCancel
JMP .EscEscape
.TabExit:
MOV [Edit.ScreenCol],2
MOV [Edit.Address],TxtExit
MOV [Edit.MaxSize],9
MOV [Edit.ScreenSize],9
MOV [Edit.ScreenRow],28
CALL EditButton
JNC .10:
SetSt [Status::],ArgCancel
JMP .EscEscape:
TabSelTable: ; Each jump is encoded to a 5 bytes long instruction.
JMP .TabIF:, DIST=NEAR
JMP .TabHS:, DIST=NEAR
JMP .TabHL:, DIST=NEAR
JMP .TabFS:, DIST=NEAR
JMP .TabFL:, DIST=NEAR
JMP .TabIE:, DIST=NEAR
JMP .TabHEI:,DIST=NEAR
JMP .TabHEN:,DIST=NEAR
JMP .TabHEC:,DIST=NEAR
JMP .TabOF:, DIST=NEAR
JMP .TabOE:, DIST=NEAR
JMP .TabICT:,DIST=NEAR
JMP .TabICC:,DIST=NEAR
JMP .TabICQ:,DIST=NEAR
JMP .TabICO:,DIST=NEAR
JMP .TabBOM:,DIST=NEAR
JMP .TabExit:, DIST=NEAR
JMP .TabConvert:, DIST=NEAR
TabSize EQU ($-TabSelTable)/5
.EscShiftTab: ; Shift-Tab pressed in the main window.
MOV EAX,[TabSelected] ; RAX=0,5,10,,,5*(TabSize-1)
SUB EAX,5
JNB .80:
MOV EAX,5*(TabSize-1)
JMP .80:
.EscTab: ; Tab pressed in the main window.
MOV EAX,[TabSelected]
ADD EAX,5
CMP EAX,5*TabSize
JB .80:
SUB EAX,EAX
.80:MOV [TabSelected],EAX ; RAX=0,5,10,,,5*(TabSize-1)
LEA RCX,[TabSelTable+RAX]
JMP RCX
.EscEscape: ; Status::ArgCancel distinguishes [Exit] from [Convert].
StdOutput EscDisableMouse,EscBaseColor,EscErase
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 MainGui
PaintWindow PROC
LinABI ioctl,0,TIOCGWINSZ,TtySize
MOVZXW EDX,[TtySize.ts_lines]
MOVZXW ECX,[TtySize.ts_cols]
MOV EAX,MinRows ; Minimal acceptable lines.
CMP EDX,EAX
JB .10:
MOV EAX,EDX
.10:LEA RDI,[ValResize]
StoD RDI
MOV AL,';'
STOSB
MOV EAX,MinCols ; Minimal acceptable columns.
CMP ECX,EAX
JB .20:
MOV EAX,ECX
.20:StoD RDI
MOV AX,'t'
STOSW
StdOutput EscResize
LinABI ioctl,0,TIOCGWINSZ,TtySize
MOVZXW EDX,[TtySize.ts_lines]
DEC EDX ; Reserve one low line for status.
MOV [MainHeight],EDX
MOVZXW ECX,[TtySize.ts_cols]
MOV [MainWidth],ECX
; Start painting.
StdOutput EscLine1,EscBaseColor,=B' ',EscEnhColor,EuroConv::,EscDimColor,Version::,Spaces
StdOutput EscLine2,EscBaseColor ; Row 2
StdOutput Spaces,Size=10
StdOutput =B'Input file',Spaces
StdOutput EscLine3,BoxDR, ; Row 3
MOV EBX,[MainWidth]
SUB EBX,2
LEA EDX,[2*EBX+EBX]
StdOutput Boxes,Size=RDX
StdOutput BoxDL,EscLine4,BoxV, ; Row 4
StdOutput Spaces,Size=RBX
StdOutput BoxV,EscLine5,BoxUR
StdOutput Boxes,Size=RDX
StdOutput BoxUL,EscLine6 ; Row 6
MOV EAX,[MainWidth]
SUB EAX,2+4*12
XOR EDX,EDX
MOV ECX,5
DIV ECX
MOV EBX,EAX
SUB EAX,2
MOV [GapFH],EAX
ADD EBX,4
StdOutput Spaces,Size=RBX
ADD EBX,2
StdOutput =B"Header"
StdOutput Spaces,Size=RBX
StdOutput =B"Header"
StdOutput Spaces,Size=RBX
StdOutput =B"Footer"
StdOutput Spaces,Size=RBX
StdOutput =B"Footer"
StdOutput Spaces
StdOutput EscLine7
SUB EBX,2
StdOutput Spaces,Size=RBX
ADD EBX,2
StdOutput =B" size "
StdOutput Spaces,Size=RBX
StdOutput =B"length"
StdOutput Spaces,Size=RBX
StdOutput =B" size "
StdOutput Spaces,Size=RBX
StdOutput =B"length"
StdOutput Spaces
SUB EBX,6
StdOutput EscLine8,Space1 ; Row 8
StdOutput Spaces,Size=RBX
StdOutput Box12U
StdOutput Spaces,Size=RBX
StdOutput Box12U
StdOutput Spaces,Size=RBX
StdOutput Box12U
StdOutput Spaces,Size=RBX
StdOutput Box12U
StdOutput Spaces
StdOutput EscLine9,Space1 ; Row 9
StdOutput Spaces,Size=RBX
LEA EAX,[EBX+3]
MOV [OffsetHeaderSize],EAX
LEA RDI,[EscGotoHeaderSize+4]
StoD RDI
MOVW [RDI],'H'
StdOutput Box12M
StdOutput Spaces,Size=RBX
LEA EAX,[EAX+EBX+12]
MOV [OffsetHeaderLength],EAX
LEA RDI,[EscGotoHeaderLength+4]
StoD
MOVW [RDI],'H'
StdOutput Box12M
StdOutput Spaces,Size=RBX
LEA EAX,[EAX+EBX+12]
MOV [OffsetFooterSize],EAX
LEA RDI,[EscGotoFooterSize+4]
StoD
MOVW [RDI],'H'
StdOutput Box12M
StdOutput Spaces,Size=RBX
LEA EAX,[EAX+EBX+12]
MOV [OffsetFooterLength],EAX
LEA RDI,[EscGotoFooterLength+4]
StoD
MOVW [RDI],'H'
StdOutput Box12M
StdOutput Spaces
StdOutput EscLine10,Space1
StdOutput Spaces,Size=RBX
StdOutput Box12D
StdOutput Spaces,Size=RBX
StdOutput Box12D
StdOutput Spaces,Size=RBX
StdOutput Box12D
StdOutput Spaces,Size=RBX
StdOutput Box12D,Spaces
StdOutput EscLine11,Spaces
StdOutput EscLine12 ; Row 12
StdOutput Spaces,Size=2
StdOutput =B"Input encoding Input HTML entities",Spaces
StdOutput EscLine13,Box16U,Space4,=B"Ignore (do not mind)",Spaces
StdOutput EscLine14,Box16M,Space4,=B"Non-ASCII HTML entities",Spaces
StdOutput EscLine15,Box16D,Space4,=B"Convert all entities",Spaces
StdOutput EscLine16,Spaces
StdOutput EscLine17,Spaces,Size=10
StdOutput =B"Output file",Spaces,
StdOutput EscLine18,BoxDR
MOV ECX,[MainWidth]
SUB ECX,2
LEA EDX,[2*ECX+ECX]
StdOutput Boxes,Size=RDX
StdOutput BoxDL,EscLine19,BoxV,
StdOutput Spaces,Size=RCX
StdOutput BoxV,EscLine20,BoxUR
StdOutput Boxes,Size=RDX
StdOutput BoxUL,EscLine21,Spaces
StdOutput EscLine22,=B" Output encoding Invalid output characters"
StdOutput Spaces
StdOutput EscLine23,Box16U,Space4,=B"Transliterate Omit",Spaces
StdOutput EscLine24,Box16M,Space4,=B"Convert to entity",Spaces
StdOutput EscLine25,Box16D,Space4,=B"Question mark replace BOM",Spaces
StdOutput EscLine26,Spaces
MOV ECX,[MainWidth]
SUB ECX,2*11
StdOutput EscLine27,Box11U,
StdOutput Spaces,Size=RCX
StdOutput Box11U,EscLine28,Box2V,TxtExit,Box2V
StdOutput Spaces,Size=RCX
StdOutput Box2V,TxtConvert,Box2V,EscLine29,Box11D
StdOutput Spaces,Size=RCX
StdOutput Box11D, ;
StdOutput EscLine30
RET
ENDP PaintWindow
Arg2Gui PROC
arg %FOR InputFile, OutputFile
MOV EDX,[MainWidth]
SUB EDX,2
LEA RSI,[Arg%arg::]
GetLengthUTF8 RSI
SUB EDX,ECX
JAE .1%.:
ADD EDX,ECX
MOV ECX,EDX
XOR EDX,EDX
.1%.:StdOutput EscGoto%arg, RSI
StdOutput Spaces,Size=RDX
%ENDFOR arg
arg %FOR HeaderSize,HeaderLength,FooterSize,FooterLength
MOV EAX,[Arg%arg::]
LEA RDI,[Gui%arg]
MOV RSI,RDI
StoD RDI,Signed=no,Align=left,Size=10
LEA RCX,[Gui%arg+10]
SUB RCX,RDI
XOR EAX,EAX
PUSH RCX
REP STOSB
StdOutput EscGoto%arg,EscBaseColor,RSI
POP RCX
StdOutput Spaces,Size=RCX
%ENDFOR arg
arg %FOR HEI,HEN,HEC
StdOutput EscGoto%arg,Unchecked
%ENDFOR arg
MOV CL,[ArgHtmlEntities::]
Dispatch CL,'I','N'
StdOutput EscGotoHEC,Checked
JMP .30:
.I: StdOutput EscGotoHEI,Checked
JMP .30:
.N: StdOutput EscGotoHEN,Checked
.30:
arg %FOR ICT,ICC,ICQ,ICO,BOM
StdOutput EscGoto%arg,Unchecked
%ENDFOR arg
MOV CL,[ArgInvalidCharacter::]
Dispatch CL,'T','Q','O'
StdOutput EscGotoICC,Checked
JMP .40:
.T: StdOutput EscGotoICT,Checked
JMP .40:
.Q: StdOutput EscGotoICQ,Checked
JMP .40:
.O: StdOutput EscGotoICO,Checked
.40: JNSt [Status::],ArgBOM,.50:
StdOutput EscGotoBOM,Checked
.50: LEA RDI,[=B" Autodetect "]
MOV EAX,[ArgInputEncoding::]
TEST EAX
JZ .70
LEA RDI,[CPid::]
LEA RSI,[RDI+2]
MOV ECX,[CodePagesLength::]
REPNE SCASW
SUB RDI,RSI
MOV ESI,EDI ; 0,2,4,6,,
LEA RDI,[Names::]
LEA RCX,[Tables::]
SUB RCX,RDI
XOR EAX,EAX
.60: TEST ESI
JZ .70:
REPNE SCASB
REPNE SCASB
SUB ESI,2
JMP .60:
.70: GetLength$ RDI ; RDI points to the codepage name.
StdOutput EscGotoInputEncoding,Space1
StdOutput RDI,Size=RCX
SUB RCX,15
NEG RCX
StdOutput Spaces,Size=RCX
LEA RDI,[=B" UTF-8 "]
MOV EAX,[ArgOutputEncoding::]
TEST EAX
JZ .90
LEA RDI,[CPid::]
LEA RSI,[RDI+2]
MOV ECX,[CodePagesLength::]
REPNE SCASW
SUB RDI,RSI
MOV ESI,EDI ; 0,2,4,6,,
LEA RDI,[Names::]
LEA RCX,[Tables::]
SUB RCX,RDI
XOR EAX,EAX
.80: TEST ESI
JZ .90:
REPNE SCASB
REPNE SCASB
SUB ESI,2
JMP .80:
.90: GetLength$ RDI ; RDI points to the codepage name.
StdOutput EscGotoOutputEncoding,Space1
StdOutput RDI,Size=RCX
SUB RCX,15
NEG RCX
StdOutput Spaces,Size=RCX
RET
ENDP Arg2Gui
Gui2Arg PROC
arg %FOR HeaderSize,HeaderLength,FooterSize,FooterLength
LEA RSI,[Gui%arg]
LodD RSI
MOV [Arg%arg::],EAX
%ENDFOR arg
arg %FOR InputEncoding, OutputEncoding
LEA RSI,[Gui%arg -4]
MOV ECX,4+16
CALL ArgParse:: ; When found, put the encoding number to Arg%arg.
SUB EAX,EAX
LEA RDI,[Gui%arg]
STOSQ
STOSQ
%ENDFOR arg
RET
ENDP Gui2Arg
EditField PROC
LEA RBX,[Edit]
MOVZX EAX,[RBX+EDIT.ScreenRow]
LEA RDI,[EscGotoRowColH]
StoD RDI
MOV AL,';'
STOSB
MOVZX EAX,[RBX+EDIT.ScreenCol]
StoD RDI
MOV AX,'H'
STOSW
StdOutput EscGoto,EscEditColor
MOVZX ECX,[RBX+EDIT.ScreenSize]
LEA EDX,[ECX-1]
StdOutput Spaces,Size=RCX
MOV RSI,[RBX+EDIT.Address]
GetLengthUTF8 RSI
CMP ECX,EDX
JB .05:
MOV ECX,EDX
.05: MOV R11,RCX
.10: PUSH R11 ; R11 is cursor position withing the visible field in characters (0,1,2,,.ScreenSize-1).
XOR R11,R11
CALL .CursorAtR11:
MOV RSI,[RBX+EDIT.Address]
MOV R9,RSI ; R9 points at the beginning of the edit field in memory.
MOVZX EAX,[RBX+EDIT.ScreenSize]
GetLengthUTF8 RSI
SUB EAX,ECX
JA .20:
MOVZX ECX,[RBX+EDIT.ScreenSize]
XOR EAX,EAX
.20: ADD R11,RCX
StdOutput EscShowCursor,EscEditColor,RSI
StdOutput Spaces,Size=RAX
POP R11
.30: CALL .CursorAtR11: ; Display (perhaps new) cursor position.
.40: XOR EDI,EDI ; Read the keyboard.
LEA RSI,[KeyBuffer]
MOV [RSI],RDI ; Clear the buffer.
MOV R8,RSI ; R8 points at the beginning of the keyboard buffer.
MOV EDX,SIZE# KeyBuffer
LinABI read,RDI,RSI,RDX
TEST EAX
JNA .40:
XOR ECX,ECX
MOV RDX,RAX ; Number of read bytes.
MOV EAX,[RSI]
AND EAX,0x00FFFFFF
CMP EAX,0x3C5B1B ; Mouse ANSI sequence
JE .0x0A: ; treat as an escape from edit window.
Dispatch AL,0x7F,0x09,0x08,0x0A,0x0D ; First try the control characters DEL, TAB, BS, Enter.
key %FOR EscDelete,EscLeft,EscRight,EscHome,EscEnd,EscShiftTab,EscEscape ; Then try kursor keys.
LEA RDI,[%key]
MOV CL,SIZE# %key
MOV RSI,R8
REPE CMPSB
JE .%key:
%ENDFOR key
CMP AL,27 ; Other special key in ANSI sequence?
JE .40: ; Ignore other ANSI sequences.
; Otherwise ordinary key was pressed, perhaps multibyte (UTF-8). Its size is in RDX (1..4).
CMP R11W,[EBX+EDIT.ScreenSize]
JNB .40: ; Ignore at the end of field.
CALL .Cursor2Physical
GetLength$ R9 ; Insert RDX bytes at R8 to the current physical position represented by R12.
LEA RSI,[R9+RCX-1]
LEA RDI,[RSI+RDX]
SUB RCX,R12
STD
REP MOVSB
CLD
LEA RDI,[R9+R12]
MOV RSI,R8
MOV ECX,EDX
REP MOVSB
INC R11 ; Finally, increment cursor position.
JMP .10:
.EscHome:
XOR R11,R11
JMP .30:
.EscEnd:
GetLengthUTF8 R9
MOV R11,RCX
JMP .30:
.EscLeft:
TEST R11
JZ .30:
DEC R11
JMP .30:
.EscRight:
GetLengthUTF8 R9
CMP R11,RCX
JAE .30:
INC R11
JMP .30:
.0x08:
.0x7F: ; Move the cursor left and then perform .EscDelete.
TEST R11
JZ .30:
DEC R11
.EscDelete: ; Erase the character at cursor position R11. Move chars on the left by one position.
CALL .Cursor2Physical
MOV EDX,1 ; Size of the erased character.
MOVZXB EAX,[R9+R12] ; UTF-8 encoded character.
CMP AL,0x80
JB .60:
NEG AL ; Scan bits 7..0 of the inverted first byte.
BSR EAX,EAX ; Returns EAX= 5, 4, 3 for 2, 3, 4 bytes long UTF-8 character.
NEG RAX ; RAX=-5,-4,-3 for 2, 3, 4 bytes long UTF-8 character.
LEA RDX,[RDX+RAX+6]
.60: LEA RDI,[R9+R12]
LEA RSI,[RDI+RDX]
GetLength$ R9
INC ECX
SUB RCX,R12
REP MOVSB
JMP .10:
.0x0D:
.0x0A:
.0x09:
.EscShiftTab:
.EscEscape:
.80: StdOutput EscBaseColor,EscHideCursor
RET
.Cursor2Physical PROC ; Convert the cursor position R11 (0,1,2,,GetLengthUTF8)
XOR R12,R12 ; to physical position R12 (0,1,2,,GetLength$). Clobbers RAX,RCX.
XOR ECX,ECX ; Cursor position.
.1: CMP RCX,R11
JAE .8:
MOVZXB EAX,[R9+R12]
INC RCX
INC R12
CMP AL,0x80
JB .1:
NEG AL ; Scan bits 7..0 of the inverted first byte.
BSR EAX,EAX ; Returns EAX= 5, 4, 3 for 2, 3, 4 bytes long UTF-8 character.
NEG RAX ; RAX=-5,-4,-3 for 2, 3, 4 bytes long UTF-8 character.
LEA R12,[R12+RAX+6]
JMP .1:
.8: RET ; R12 is physical offset (0,1,2,,GetLength$) corresponding with cursor offset in R11.
ENDP .Cursor2Physical
.CursorAtR11 PROC ; Place the cursor in the edit field at column R11 (0,1,2,,GetLengthUTF8).
; R11 represents the visible position, not the position in strings bytes. It clobbers RAX,RDI.
LEA RDI,[EscGotoRowColH]
MOVZX EAX,[RBX+EDIT.ScreenRow]
StoD RDI
MOV AL,';'
STOSB
MOVZX EAX,[RBX+EDIT.ScreenCol]
ADD RAX,R11
StoD RDI
MOV AX,'H'
STOSW
StdOutput EscGoto
RET
ENDP .CursorAtR11
ENDP EditField
EditButton PROC
LEA RBX,[Edit]
MOVZX EAX,[RBX+EDIT.ScreenRow]
LEA RDI,[EscGotoRowColH]
StoD RDI
MOV AL,';'
STOSB
MOVZX EAX,[RBX+EDIT.ScreenCol]
StoD RDI
MOV AX,'H'
STOSW
MOV RSI,[RBX+EDIT.Address]
StdOutput EscGoto,EscEditColor,RSI
MOVZX ECX,[RBX+EDIT.ScreenSize]
.40: XOR EDI,EDI ; Read the keyboard.
LEA RSI,[KeyBuffer]
MOV [RSI],RDI ; Clear the buffer.
MOV R8,RSI ; R8 points at the beginning of the keyboard buffer.
MOV EDX,SIZE# KeyBuffer
LinABI read,RDI,RSI,RDX
TEST EAX
JNA .40:
XOR ECX,ECX
MOV RDX,RAX ; Number of read bytes.
MOV EAX,[RSI]
AND EAX,0x00FFFFFF
CMP EAX,0x3C5B1B ; Mouse ANSI sequence
JE .0x0A: ; treat as an escape from edit window.
Dispatch AL,0x09,0x20,0x0A,0x0D ; First try the control characters TAB, SPACE, Enter.
key %FOR EscShiftTab,EscEscape ; Then try other keys.
LEA RDI,[%key]
MOV CL,SIZE# %key
MOV RSI,R8
REPE CMPSB
JE .%key:
%ENDFOR key
JMP .40: ; Ignore all other keys and sequences.
.0x20:
.0x0D:
.0x0A: ; Enter or Space pressed.
STC
JMP .80:
.0x09:
.EscShiftTab: ; Tab or ShiftTab or Esc pressed.
.EscEscape:
CLC
.80: PUSHF
MOV RSI,[RBX+EDIT.Address]
StdOutput EscBaseColor,EscHideCursor,EscGoto,RSI
POPF
RET
ENDP EditButton
ENDPROGRAM convling