📄 e3.asm
字号:
;--------------------------------------------------------------------;; e3.asm v2.41 Copyright (C) 2000-2003 Albrecht Kleine <kleine@ak.sax.de>;; This program is free software; you can redistribute it and/or modify; it under the terms of the GNU General Public License as published by; the Free Software Foundation; either version 2 of the License, or; (at your option) any later version.;; This program is distributed in the hope that it will be useful,; but WITHOUT ANY WARRANTY; without even the implied warranty of; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the; GNU General Public License for more details.;; You should have received a copy of the GNU General Public License; along with this program; if not, write to the Free Software; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.;;----------------------------------------------------------------------;%include "e3.h";section .textbits 32 ORGheaderglobal _start;; start with OUTER editor loop;_start: call SetTermStruc%ifdef SELFTEST mov eax,mode mov byte [eax],WS ;store current editor mode: WS only.. mov esi,pipein ;...because the test file expects WS "syntax"%else%ifdef W32 push byte 0 push dword 8192 ;initial size (to be extended) push byte 0 call HeapCreate mov [heap],eax;------ mov eax,mode mov byte [eax],DEFAULT_MODE ;store default editor mode call GetCommandLineA ;eax points to either D:\PATH\E3.EXE args1 args2 args3... xchg eax,esi ; or "d:\path\e3.exe" ;-- for debug only -- ; or e3.exe "args" ;pusha ;push dword 0 ;single OK button ;push dword esi ;push dword esi ;push dword 0 ;call MessageBoxA ;show cmd line ;popa ;-------------------- cld xor ebx,ebx cmp byte [esi],'"' ;due above mentined 2 different cmd line ways jnz prog dec ebx ;ebx -1 due pending '"'prog: lodsb or al,al jz prog9 cmp al,SPACECHAR ;TODO chk TABs ja prog inc esiprog9: dec esiprog0: push esi lea esi,[esi+ebx-4-5] ;-4 due suffix ".exe" call SetEditMode jz prog1 mov byte [eax],DEFAULT_MODE ;store current editor modeprog1: pop esi xor edx,edx ;no argsprog2: lodsb or al,al jz prog3 cmp al,SPACECHAR jbe prog2 dec esi jmp short prog5prog3: mov esi,edxprog5:%else%ifdef BEOS ;----------------------------------------------------------- pop eax pop ebx ;args counter (1....x) pop esi mov esi,[esi] ;points to our_name0[args]0env..... cldprog: lodsb or al,al jne prog mov edx,esi ;store arg ptr lea esi,[esi-5] call SetEditMode jz prog1 mov byte [eax],DEFAULT_MODE ;store current editor modeprog1: xor esi,esi ;init for 'no args' dec ebx jz noarg mov esi,edxnoarg:%else%ifdef DYN ;------------------------------------------------------------; This is to be called from dynamic linked libc startup code ; just like you would expect: int main(int argc,char**argv); (for experimental purpose only); xor esi,esi ;init to "no args" mov ecx,[esp+4] ;"int argc" cmp ecx,1 je NoArg mov esi,[esp+8] ;"char**argv" mov esi,[esi] cldArgl: lodsb or al,al jne ArglNoArg: mov eax,mode mov byte [eax],DEFAULT_MODE ;store current editor mode (WS only)%undef CURSORMGNT%else ;-------------- i.e. Linux, FreeBSD, QNX, Ath ------------------%ifdef SYS_sigaction call SetSigHandler%endif;-------%ifdef ATHEOS pop edx pop edx pop edx%endif pop edx ;Linux: arguments # pop esi ;Linux: argv[0] cldprog: lodsb or al,al jne prog ;get program name lea esi,[esi-5] call SetEditMode jz prog1 mov byte [eax],DEFAULT_MODE ;store current editor modeprog1:;------- pop esi ;Linux: esi points to first arg (filename)%endif%endif%endif%endif;-------%ifdef CURSORMGNT or esi,esi jz moreenvmorearg:pop ecx ;arguments until NULL or ecx,ecx jnz morearg;-------moreenv:pop ecx jecxz ReStart%ifndef ARMCPU cmp dword[ecx],'TERM' ;a short test for "TERM=linux" jnz moreenv cmp dword[ecx+5],'linu'%else cmp byte[ecx],'T' jnz moreenv cmp byte[ecx+1],'E' jnz moreenv cmp byte[ecx+2],'R' jnz moreenv cmp byte[ecx+3],'M' jnz moreenv cmp byte[ecx+5],'l' jnz ReStart cmp byte[ecx+6],'i' jnz ReStart cmp byte[ecx+7],'n' jnz ReStart cmp byte[ecx+8],'u'%endif jnz ReStart add byte[revvoff],boldlen ;special inverse cursor on linux terminals%endif;-------ReStart:call NewFile jc E3exitMainCharLoop:call ChkCursPos call IsViMode jnz MCL mov ecx,[blockbegin] jecxz MCL push edi mov edi,ecx ;for vi only: keep Begin/End-line marker together call KeyEnd ; <------prev line------------> ; BegM......marker line........EndM ; <-------next line-----------> mov [blockende],edi ;set WS's "blockende" to one after EOL for VI marker pop edi call ShowBl1 ;i.e. "mov byte [showblock],1";-------MCL: call DispNewScreen call RestoreStatusLine call HandleChar%ifdef W32LF cmp byte [edi],RETURN ;never stay at character 0dh jnz MCL2 inc edi ;(rather stay at following 0ah)MCL2:%endif mov ebx,endeedit cmp byte [ebx],0 je MainCharLoop xor esi,esi ;just like if no arg is present cmp byte [ebx],2 je ReStart ;^KD repeat edit using another fileE3exit: call KursorStatusLine%ifdef W32 push dword w32result ;reset all to standard colors push byte 0 mov eax,[lines] inc eax mov ebx,[columns] mul bl push eax push byte DARKWHITE ;equ 7 push dword [hout] call FillConsoleOutputAttribute%endif mov ecx,text ;enter next line on terminal NEWLINE is @ byte [text] call WriteFile00;------- mov ebx,tempfile2 ;undo info (if exist) call Unlink%ifdef W32 push dword [heap] call HeapDestroy push byte 0 ;return code call ExitProcess ;Ready&Exit%else mov ecx,TERMIOS_SET call IOctlTerminal0 ;restore termios settings jmp Exit%endif;----------------------------------------------------------------------;; MAIN function for processing keys;HandleChar:call ReadChar cmp ah,0xFF ;normal chars get 0xFF in ah jne near ExtAscii ;go handling Cursor-Keys mov esi,mode test byte [esi], EM | PI jz NO_EM01 cmp al,11 je IsCtrlK mov byte [EmaCtrlK],0IsCtrlK:cmp al,13h ;^S je IsCtrlS cmp al,12h ;^R je IsCtrlS mov byte [EmaCtrlS],0IsCtrlS:NO_EM01:cmp byte [esi],VI jz ISVI1 cmp al,32 ;in WS,EM,PI,NE: handle control chars jae NormChar mov bl,al add bl,jumps1 cmp byte [esi],WS je CJump add bl,32 cmp byte [esi],EM je CJump add bl,32 cmp byte [esi],PI je CJump add bl,32CJump: jmp CompJump2ISVI1: ;in VI: most control is done in command mode... cmp al,7 ;... so maintaining another table for <Return>... je near KeyDel ;... <Del> and <DelLeft> is useless cmp al,8 je near KeyDell cmp al,RETURN je near KeyRet;-------NormChar:test byte [mode], EM | PI jz NOEM0 call ShowBl0 ;i.e. "mov byte [showblock],0"NOEM0: call CheckMode%ifdef USE_UNDO jz NormCh2 call DataForUndoOverwrite jmp short OverWriteChar%else jnz OverWriteChar%endif NormCh2:push eax%ifdef W32LF call CheckEof jz noEOL cmp word [edi-1],RETURN|(NEWLINE<<8) jnz noEOL dec edi ;move back to 0DhnoEOL:%endif call Insert1Byte pop eax jc InsWriteEnd ;error: text buffer fullOverWriteChar:cld stosbSetChg: mov byte [changed],CHANGEDInsWriteEnd:ret;-------KeyVICmdr:call ReadOneChar ;repl one char (except newline) cmp byte [edi],NEWLINE je InsWriteEnd cmp al,RETURN jnz KeyVICmdr1 mov al,NEWLINEKeyVICmdr1:%ifdef USE_UNDO call DataForUndoOverwrite%endif KeyVICmdr2:mov byte [edi],al jmp short SetChg;-------KeyEmaCtrlQ:mov esi,asknumber call GetOctalToInteger jbe InsWriteEnd xchg eax,ecx ;using decimal input for ASCII value cmp eax,256 jb NormCh2 ret;-------;; helper for HandleChar;CtrlKMenu:mov ebx,Ktable mov al,'K' jmp short MenuCtrlQMenu:mov ebx,Qtable jmp short PicoQMPicoJMenu:mov ebx,PicoJtable mov al,'J' jmp short MenuPicoQMenu:mov ebx,PicoQtablePicoQM: mov al,'Q' jmp short MenuCtrlXMenu:mov ebx,Xtable mov al,'X'Menu: mov ecx,2020205eh mov ch,al;-------MakeScanCode:call WriteTwo ;ebx expects xlat-table push ebx call GetChar pop ebx and al,01fh cmp al,Ktable_size jnb InsWriteEnd ;if no valid scancode xlatb mov ah,al ;=pseudo "scancode";------- contExtAscii:mov bl,ah ;don't use al (carries char e.g. TAB) cmp bl,jumps1 jae InsWriteEnd xor eax,eax mov [EmaCtrl],eaxCompJump2:mov bh,0 lea ebx,[bx] ;1 byte shorter than 'and ebx,0ffh' movzx ebx,word [2*ebx+jumptab1] ;2*ebx is due 2 byte per entry add ebx,_start ;offset inside code;------- call ebx ;the general code jump dispatcher;------- cmp byte [numeriere],1 ;after return from functions... jnz BZNret ;...decide whether count current line number push edi mov esi,sot xchg esi,edi xor edx,edxBZNLoop:inc edx ;edx=linenr counter call LookForward inc edi ;point to start of next line cmp edi,esi jbe BZNLoop mov [linenr],edx pop edi mov byte [numeriere],0BZNret: ret;----------------------------------------------------------------------;; processing special keys: cursor, ins, del;KeyRetNoInd:xor eax,eax jmp short KeyRetNIndKeyRet: ;;; %define NO_AUTO_INDENT ;for Izzy%ifndef NO_AUTO_INDENT%ifdef SELFTEST xor eax,eax%else call CheckMode jnz OvrRet call CountToLineBegin ;set esi / returns eax inc esi inc esi or eax,eax jz KeyRetNInd mov ebx,eax xor eax,eax dec eaxKeyRetSrch:inc eax ;search non (SPACE or TABCHAR) cmp eax,ebx jae KeyRetNInd cmp byte [esi+eax],SPACECHAR je KeyRetSrch cmp byte [esi+eax],TABCHAR je KeyRetSrch%endif%else xor eax,eax%endifKeyRetNInd:push esi push eax ;eax is 0 or =indented chars call GoDown pop eax push eax%ifdef W32LF inc eax ;1 extra for RETURN call CheckEof jz noEOL2 cmp word [edi-1],RETURN|(NEWLINE<<8) jnz noEOL2 dec edi ;move back to 0DhnoEOL2:%endif call InsertByte0 ;1 extra for NEWLINE pop ecx ;# blanks pop esi ;where to copy jc SimpleRet inc dword [linenr] cld%ifdef W32LF mov ax,RETURN|(NEWLINE<<8) ;insert 0d0ah combination stosw%else mov al,NEWLINE stosb%endif jecxz SimpleRet rep movsb ;copy upper line i.e. SPACES,TABS into nextSimpleRet:retOvrRet: xor eax,eax mov [ch2linebeg],eax jmp short DownRet;-------KeyDown:call CountColToLineBeginVisDownRet:call GoDown call LookLineDown jmp short JmpSC;-------KeyUp: call GoUp call CountColToLineBeginVis call LookLineUp jmp short JmpSC;-------KeyHalfPgUp:call CountColToLineBeginVis call LookHalfPgUp jmp short SetColumn;-------KeyHalfPgDn:call CountColToLineBeginVis call LookHalfPgDn jmp short SetColumn;-------KeyScrollUp:call CountColToLineBeginVis call LookScrUp jmp short SetColumnKeyScrollDn:call CountColToLineBeginVis call LookScrDn jmp short SetColumn;-------KeyPgUp:call CountColToLineBeginVis call LookPageUpJmpSC: jmp short SetColumn;-------KeyPgDn:call CountColToLineBeginVis call LookPgDown ;1st char last lineSetColumn:mov ecx,[ch2linebeg] ;=maximal columns xor edx,edx ;counts visible columns i.e. expand TABs dec ediSCloop: inc edi cmp edx,ecx ;from CountColToLineBeginVis jae SCret cmp byte [edi],NEWLINE ;don't go beyond line earlier line end jz SCret cmp byte [edi],TABCHAR jz SCtab inc edx ;count columns jmp short SCloopSCtab: call SpacesForTab add dl,ah cmp edx,ecx ;this tab to far away right? jna SCloop ;noSCret: ret;----------------------------------------------------------------------;; a helper for d'a and y'a vi commands; have to differ whether cursor is below or above the marked line; (at all this line based concept does not fit very well into e3); expects:; ecx valid begin of marked line; edi cursorVIsetMarker:cmp edi,ecx ja Marker_above_cursor ; X........cursor line....... ; ........................... ; .........marker line....... ; Y mov ecx,[blockende] inc ecx cmp ecx,ebp jb Mbel dec ecxMbel: mov dword [EmaMark],ecx ;i.e. store point Y;------- contKeyHome:call CountToLineBegin ;i.e. goto point X sub edi,eax ret;-------Marker_above_cursor: ; Y.......marker line ....... ; ........................... ; ........cursor line........ ; X ; mov dword [EmaMark],ecx ;i.e. store point Y call KeyEnd inc edi ;i.e. goto point X cmp edi,ebp jb Mret dec ediMret: ret;----------------------------------------------------------------------KeyIns: not byte [insstat] xor eax,eax call IsViMode jnz KeyIns2 inc eax cmp byte [VICmdMode],al jne KeyIns2 mov byte [insstat],al call KeyVImode0KeyIns2:call IsEmMode jnz KeyIns3 mov byte [showblock],alKeyIns3:ret;-------KeyVICmdJ:call KeyEnd jmp short KeyDel;-------KeyDell:call KeyLeft jz KeyDell2KeyDel: cmp edi,ebp jnb KeyIns3 xor eax,eax ;delete one @ cursor inc eax%ifdef W32LF cmp byte [edi-1],RETURN jnz KD2 dec edi ;delete one more inc eaxKD2:%endif;------- call IsViMode jne near DeleteByte mov esi,edi ;make vi's x and X pasteable mov byte [VInolinebased],1 call KeyEmaAltW2 jmp DeleteByte;------- KeyDell2:cmp edi,sot ;delete newline char jbe KeyIns3 dec dword [linenr] dec edi jmp KeyCtrlT1;-------KeyEmaCtrlT:cmp edi,sot ;xchg 2 chars jbe KeyRightEnd cmp byte [edi],NEWLINE jnz KECT dec ediKECT: %ifdef USE_UNDO call DataForUndoXchange%endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -