📄 e3.asm
字号:
; side effect: sets 'columne' for RestoreStatusLine function (displays column); variable kurspos: for placing the cursor at new position; register bh counts lines; register bl counts columns visible on screen (w/o left scrolled); register edx counts columns in text lines; register ecx screen line counter and helper for rep stos; register esi text index; register edi screen line buffer index;DispNewScreen:test byte [mode], EM | PI | NE jz NoEmBlock mov ecx,[showblock] ;transfering Emacs's mark/point into.... jecxz NoEmBlock ;....WS's block display system mov ecx,[EmaMark] jecxz NoEmBlock mov eax,edi cmp ecx,eax jb EmBlock xchg eax,ecxEmBlock:mov [blockbegin],ecx mov [blockende ],eax;-------NoEmBlock:call GetEditScreenSize ;check changed tty size xor eax,eax mov byte[isbold],al mov byte[inverse],al mov [zloffst],eax mov [columne],eax mov [fileptr],edi ;for seeking current cursor pos push edi ;&&**## call CountColToLineBeginVis ;i.e. expanding TABs mov ebx,[columns] lea ebx,[ebx-4] ;03 Jun 2001 cmp eax,ebx jb short DispShortLine sub eax,ebx inc eax mov [zloffst],eaxDispShortLine:call LookPgBegin ;go on 1st char upper left on screen mov esi,edi ;esi for reading chars from text mov ecx,[lines] jecxz Kviex cld mov bh,-1 ;first lineDispNewLine:inc bh ;new line mov edi,screenline ;line display buffer xor edx,edx ;reset char counter mov bl,0 ;reset screen column to 0%ifdef LESSWRITEOPS call SetColor2 ;set initial character color per each line%endifDispCharLoop: cmp esi,[fileptr] ;display char @ cursor postion ? jnz DispCharL1 cmp byte[tabcnt],0 jnz DispCharL1 mov [kurspos],ebx mov byte [columne],bl mov eax,[zloffst] ;chars scrolled left hidden add [columne],eax%ifdef CURSORMGNT stc call SetInverseStatus jnc DispEndLine%endifDispCharL1:call SetColor ;set color if neccessary;-------DispEndLine:cmp esi,ebp ja FillLine ;we have passed EOF, so now fill rest of screen cmp byte[tabcnt],0 jz ELZ dec byte[tabcnt] jmp short ELZ2ELZ: cmp esi,ebp jnz ELZ6 inc esi ;set esi>ebp will later trigger "ja FillLine" jmp short ELZ2ELZ6: lodsb cmp al,TABCHAR jnz ELZ3 call SpacesForTab ;ah = space_up_to_next_tab location dec ah ;count out the tab char itself mov byte[tabcnt],ahELZ2: mov al,SPACECHARELZ3: cmp al,NEWLINE jz FillLine%ifdef W32LF cmp al,RETURN jz ELZ5 ;keep 0dh "invisible"%endif cmp al,SPACECHAR jae ELZ9 ;simply ignore chars like carriage_return etc. mov al,'.'ELZ9: %ifndef W32 cmp al,7fh jb ELZ7 cmp al,9Fh ja ELZ7 mov al,'.'ELZ7: %endif cmp bl,byte [columns] ;screen width jae DispEndLine ;continue reading line until end inc edx ;also count hidden chars (left margin) cmp edx,[zloffst] jbe ELZ5 ;load new char (but no display) stosB%ifdef CURSORMGNT clc call SetInverseStatus%endif inc bl ;counts displayed chars onlyELZ5: jmp DispCharLoop;-------FillLine:push ecx ;continue rest of line mov ecx,[columns] ;width sub cl,bl mov al,SPACECHAR ;fill with blanks jecxz FillLine2 cmp byte[inverse],1 ;special cursor attribute? jnz FillLine1 stosB ;only 1st char with special attribute%ifdef CURSORMGNT clc call SetInverseStatus%endif dec ecx ;one char less jz FillLine2FillLine1: rep stosB ;store the rest blanksFillLine2:pop ecx mov byte[edi],0 call ScreenLineShow dec ecx jnz near DispNewLine pop edi ;&&**## ;OLD: mov edi,[fileptr] ;=restore text pointer jmp RestKursPos;----------------------------------------------------------------------; three helper subroutines called by DispNewScreen; dealing ESC sequences for character attributes; %ifdef CURSORMGNTSetInverseStatus: push ecx ;returns zero flag push esi jnc SIS1 cmp byte [insstat],1 stc jnz SIS4 mov byte[inverse],1 mov esi,reversevideoX add esi,[revvoff] ;switch between esc seq for linux or Xterm jmp short SIS2SIS1: cmp byte[inverse],1 jnz SIS3 mov byte[inverse],0;-------continued...%endif;------; next presented in 2 versions: one for Win32, one for Terminals;%ifdef W32 ;------------- this can't be done via ESC seq ----------------SIS6: mov byte[isbold],0SIS5: mov eax,DARKWHITESIS2: mov ecx,edi sub ecx,screenline mov edx,ecx ;current pos in columne shl ecx,1 mov edi,attribline add edi,ecx mov ecx,[columns] sub ecx,edx ;only current pos up to line end rep stoswSIS3: clcSIS4: popa retSetColor: ;expects cy flag:bold / nc:normal pusha call IsShowBlock jnc SCEsc1 cmp byte [isbold],1 ;never set bold if it is already bold jz SIS4 mov byte [isbold],1SCEsc2: mov eax,WHITE jmp short SIS2SCEsc1: cmp byte [isbold],0 ;ditto jz SIS4 jmp short SIS6;-------SetColor2:pusha call IsShowBlock jnc SIS5 jmp short SCEsc2%else ;---------------------- TERMINAL part -----------------------------SIS6: mov byte[isbold],0SIS5: mov esi,bold0SIS2: push byte boldlen pop ecx rep movsbSIS3: clcSIS4: pop esi pop ecx ret;-------SetColor:push ecx ;expects cy flag:bold / nc:normal push esi call IsShowBlock jnc SCEsc1 cmp byte [isbold],1 ;never set bold if it is already bold jz SIS4 mov byte [isbold],1SCEsc2: mov esi,bold1 jmp short SIS2SCEsc1: cmp byte [isbold],0 ;ditto jz SIS4 jmp short SIS6;-------%ifdef LESSWRITEOPSSetColor2: push ecx push esi call IsShowBlock jnc SIS5 jmp short SCEsc2%endif%endif ;----------------- end of double part -----------------------------;;-------; a little helper for SetColor* functions;IsShowBlock:cmp byte [showblock],0 je SBlock cmp dword [blockbegin],0 je SBlock cmp [blockbegin],esi ja SBlock cmp esi,[blockende] jb SB_retSBlock: clcSB_ret: ret;-------; this helper for DispNewScreen checks screen size before writing on screen; FIXME: adjusting edit screen resize works with xterm, but not with SVGATextMode;GetEditScreenSize:%ifdef W32 push dword csbi push dword [hout] call GetConsoleScreenBufferInfo or eax,eax mov eax,[csbi] jnz noerr mov eax,0x00190050 ;i.e. (80<<16)+24 (assume 80x25)noerr: mov byte [columns],al shr eax,16 dec eax mov byte [lines],al ;columns > 255 are ignored... ret%else mov ecx,TERMIOS_WSIZE mov edx,winsize call IOctlTerminal mov eax,[edx] ;each 16 bit lines,columns cmp eax,0x0000FFFF ;some give no columns info..? jb iserr or eax,eax jnz noerriserr: mov eax,0x00500018 ;i.e. (80<<16)+24 (assume 80x24)noerr: dec eax ;without status line ('dec al' are 2 byte!) mov byte [lines],al shr eax,16 mov byte [columns],al ;columns > 255 are ignored... ret%endif;----------------------------------------------------------------------;; LOWER LEVEL screen acces function (main +2 helpers); this function does write the line buffer to screen i.e. terminal;; at first 2 special entry points:WriteTwo:mov [screenline],ecxStatusLineShow:%ifdef W32 push edi mov ecx,[columns] shr ecx,1 mov eax,YELLOW_BLUE_TWICE mov edi,attribline rep stosd pop edi mov edx,[kurspos2] call sys_writeKP ;set cursor pos before reading chars%endif xor ecx,ecx ;0 for bottom line;-------ScreenLineShow:pusha ;expecting in ecx screen line counted from 0%ifdef LESSWRITEOPS%ifdef W32 ;screen attrib caching mov eax,[columns] mul ecx ;setting edx to 0 mov ebx,edx ;flag lea edi,[eax+attribbuffer] cld mov esi,attriblineXsl3: lodsw cmp edi,attribbuffer_end ;never read/write beyond buffer jnb Xsl5 cmp ax,[edi] jz Xsl4 mov [edi],axXsl5: inc ebx ;set flag whether line need redrawingXsl4: inc edi inc edi or al,al jnz Xsl3%else xor ebx,ebx ;flag%endif;------- mov eax,[columns] lea eax,[eax+32] ;estimated max ESC sequences extra bytes (i.e. boldlen*X) (BTW add eax,32 islonger) mul ecx ;setting edx to 0 lea edi,[eax+screenbuffer]%else xor edx,edx ;counter%endif cld mov esi,screenlinesl3: lodsb inc edx ;count message length to write%ifdef LESSWRITEOPS cmp edi,screenbuffer_end ;never read/write beyond buffer jnb sl5 cmp al,[edi] jz sl4 mov [edi],alsl5: inc ebx ;set flag whether line need redrawingsl4: inc edi%endif or al,al jnz sl3 dec edx ;one too much%ifdef LESSWRITEOPS or ebx,ebx ;redraw ? jz NoWrite%endif push edx xor edx,edx mov dh,byte [lines] sub dh,cl%ifdef W32_EXTENDED_IO pop ebx ;len shl edx,8 and edx,00ff0000h ;only line# (column is always 0) push edx ;cursor data;------- push dword w32result push edx ;cursor push ebx ;length push dword screenline push dword [hout] call WriteConsoleOutputCharacterA;------- pop edx push dword w32result push edx ;cursor push ebx ;length push dword attribline push dword [hout] call WriteConsoleOutputAttribute%else ;this works on both Terminal and W32, ... ;...but is suboptimal and slow on W32 call sys_writeKP ;set cursor pos before writing the line pop edx push ecx mov eax,screencolors1 ;set bold yellow on blue call sys_writeSLColors ;special for status line (ecx==0) mov ecx,screenline ;second argument: pointer to message to write call WriteFile0;------- pop ecx mov eax,screencolors0 ;reset to b/w call sys_writeSLColors ;special for status line (ecx==0) mov edx,[kurspos2] call sys_writeKP ;restore old cursor pos%endifNoWrite:popa ret;-------; a helper for ScreenLineShow;sys_writeSLColors:%ifndef W32 jecxz syswSL ;do nothing if not in status line retsyswSL: pusha xchg eax,ecx ;parameter points to ESC-xxx color string push byte scolorslen pop edx call WriteFile0 popa%endif ret;----------------------------------------------------------------------;; getting line INPUT from terminal / UNDER CONSTRUCTION;; expecting pointer to message text in esi;InputStringWithMessage0:mov esi,extextInputStringWithMessage:call WriteMess9MakeLine mov ecx,optbuffer push byte optslen pop edx jmp short InputString;-------InputString00:mov ecx,suchtextInputString0:call WriteMess9MakeLine mov edx,maxfilenamelen; expecting input line buffer in ecx; expecting max count byte in edx; return length in eax, CY for empty string (or user abort);InputString:push ecx push edi push byte 2 pop eax xchg eax, [VICmdMode] push eax ;LONGER: push dword [VICmdMode], mov byte [VICmdMode],2 push dword [kurspos2] mov ebx,[columns] lea ebx,[ebx-stdtxtlen] cmp edx,ebx ;TODO enable some scrolling: jb IS8 ;not yet ready, so truncate at end of line mov edx,ebxIS8: xor ebx,ebx mov edi,ecxIS0: push ebx push edx add bl,stdtxtlen ;offset+column mov bh,byte[lines] ;line# mov [kurspos2],ebx%ifdef LESSWRITEOPS mov byte [screenbuffer],0 ;switching off usage of buffer v0.7%endif call StatusLineShow call GetChar pop edx pop ebx cld;------- call IsViMode jnz NO_VI01 cmp al,0 je ISANO_VI01: call CheckUserAbort jne IS9ISA: xor ebx,ebx ;length 0 triggers CY flag jmp short IS1IS9: cmp al,RETURN je IS1 cmp al,8 ;^H (translated DEL) jne IS2 or ebx,ebx ;@left border? jz IS0 dec ebx dec edi mov al,SPACECHAR mov byte [ebx+screenline+stdtxtlen],al jmp short IS0;-------IS2: cmp al,SPACECHAR jb IS0 stosb mov byte [ebx+screenline+stdtxtlen],al ;ditto inc ebx cmp ebx,edx jb IS0;-------IS1: xor eax,eax stosb ;make asciz string pop dword [kurspos2] pop dword [VICmdMode] ;restore original vi mode pop edi pop ecx xchg eax,ebx cmp al,1 ;set cy flag if empty string (len always <256)ISready:ret ;eax length (but is < 255);----------;; GetChar (main function for kbd input);ReadChar:mov eax,edi xchg eax,[old] ;for ^QP mov [veryold],eaxGetChar:call ReadOneChar ;ah=0xFF for usual keys%ifdef W32 cmp ah,0FEh ;cursor key jnz GC33 shl eax,8 retGC33: cmp ah,0FDh ;ALT key jnz GC34 and al,5fh ;toupper jmp short NOVI7GC34:%endif cmp al,7FH jne short RC_No7F ;special case: remap DEL to Ctrl-H%ifndef FREEBSD mov al,8%else mov al,7%endifRC_No7F:;-------%define DoNo 10;-------;; vi needs special handling of the ESC key; call IsViMode jz short ISVI7 cmp al,27 ;ESC ? jnz ISready call ReadOneChar ;dont care whether '[' or 'O' (should be [ for vt220 family O for vt100 family) jmp short NOVI7;-------ISVI7: cmp byte [VICmdMode],1 jne NoCMDmode cmp al,27 je ESCpressed cmp al,VIsize ja near Other mov ebx,VIcmdTable ;process command mode keys...... jmp RCready_0 ;....and ready;-------ESCpressed:call ReadOneChar cmp al,'[' ;decide: it's a cursor key? je near Other ;yes, contine jmp short NoCursorKey ;no push back char into buffer and exitNoCMDmode:cmp al,27 ;ESC ? jnz ISready call KeyVImode1 ;ESC pressed in EDIT Mode%ifdef BEOS call RestoreStatusLine%else%ifdef SYS_select pusha call Select ;differ between ESC and ESC_cursor_keys popa jz isSingleEscape%endif%endif call ReadOneChar cmp al,'[' ;starting sequence of cursor key found? je IsCursorKey ;pressed ESC, but do _NOT_ switch init cmd modeNoCursorKey:mov byte [VIbufch],al ;push char back into read buffer due it's not a cursor key mov al,DoNo ;do nothing jmp short JmpRCreadyisSingleEscape:mov al,3 ;3 is keyLeft (i.e. entry #3 jumptab1) jmp short JmpRCready ;keyLeft is what a real vi user expects here ;);-------IsCursorKey:call KeyVImode0 ;reset mode to 'no_command' and continue;-------NOVI7: cmp byte [mode],NE ;ALT keys are currently used for nedit mode... jnz NONE7 cmp al,'i' jnz NOi mov al,0x10 jmp short JmpRCreadyNOi: cmp al,'I' jnz NONE7 mov al,0x10 jmp short JmpRCreadyNONE7: call IsEmMode jnz NOEM7 ;ALT keys are currently used for Emacs mode... cmp al,'%' ;...except altH for online Help jne NoAltPer mov al,0x28JmpRCready:jmp short RCready_1NoAltPer:cmp al,'<' jne NoAltLt mov al,0x0e jmp short RCready_1NoAltLt:cmp al,'>' jne NoAltGt mov al,0x0f jmp short RCready_1NoAltGt:and al,0x5F ;to upper case sub al,'B' ;1at in table js Other cmp al,ATsize ja Other mov ebx,EmaAltTable
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -