📄 e3-16.asm
字号:
;-------------------------------------------------------------------------;; Copyright (C) 2002 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 library 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; Library General Public License for more details.;; You should have received a copy of the GNU Library General Public; License along with this library; if not, write to the Free Software; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA;;--------------------------------------------------------------------------;; This is e3-16, a 16 bit derived work of 32 bit micro editor e3, ...; ...running on ELKS (==Embeddable Linux Kernel Subset) and DOS.; Unlike e3 we are supporting WStar key bindings only.; Unlike e3 "BAK-files" (*~) are not yet created.;TAB equ 8TABCHAR equ 09h ; ^ISPACECHAR equ ' 'CHANGED equ '*'UNCHANGED equ SPACECHARNEWLINE equ 0aherrlen equ 100MAXERRNO equ 30ERRNOMEM equ 12ERRNOIO equ 5sBREITE equ 80 ;colssHOEHE equ 24 ;rowsMAXLEN equ 0x7FFFmaxfilenamelen equ 255%ifdef ELKS;;;; %define LESSWRITEOPS stdin equ 0 stdout equ 1 O_WRONLY_CREAT_TRUNC equ 1101q O_RDONLY equ 0 PERMS equ 644q%else ;-------------- normfarbe equ 07h kursorfarbe equ 70h slinefarbe equ 1eh ;yellow on blue blockfarbe equ 15 O_WRONLY_CREAT_TRUNC equ 0%endifsection .textbits 16global _startglobal _main ; for ELKS and the ld86 linker_start: _main:EXE_startcode:%ifdef EXESTUB..start:%endif;-------%ifdef ELKS call InitBSS pop ax pop bx pop si ;si points to first arg%else%ifdef COM org 100h%else%ifdef EXESTUB mov ax,data mov es,ax push ax%else%ifdef EXE EXE_realstacksize equ 0x800 org 0e0hheader_start:;EXE header adapted from a NASM contribution by Yann Guidon <whygee_corp@hol.fr> db 'M','Z' ; EXE file signature dw EXE_allocsize % 512 dw (EXE_allocsize + 511) / 512 dw 0 ; relocation information: none dw (header_end-header_start)/16 ; header size in paragraphs dw (EXE_absssize + EXE_realstacksize) / 16 ; min extra mem dw (EXE_absssize + EXE_realstacksize) / 16 ; max extra mem dw -10h ; Initial SS (before fixup) dw EXE_endbss + EXE_realstacksize ; 2k dw 0 ; (no) Checksum dw 100h ; Initial IP - start just after the header dw -10h ; Initial CS (before fixup) dw 0 ; file offset to relocation table: none dw 0,0,0 ; (no overlay)header_end: ; here we go... (@ org 100h)%endif%endif%endif call InitBSS call GetArg%ifdef EXESTUB pop ds%endif%endif;-----------------------------------------------------------------------;; start with OUTER editor loop;ReStart:call NewFile jc E3exitMainCharLoop:call DispNewScreen call RestoreStatusLine call HandleChar cmp byte [endedit],0 je MainCharLoop xor si,si ;just like if no arg is present cmp byte [endedit],2 je ReStart ;^KD repeat edit using another fileE3exit: call KursorStatusLine;-------%ifdef ELKS mov bx,stdout ;file handle mov cx,newline ;enter next line on terminal xor dx,dx inc dx ;mov dx,1 push dx call WriteFile pop ax ;mov ax,1 xor bx,bx ;return 0 int 80h%else mov ah,4ch int 21h%endif;----------------------------------------------------------------------;; MAIN function for processing keys;HandleChar:call ReadChar jz ExtAscii ;DOS version got ah=0 by int 16 for F-keys and cursor keys cmp al,19h ;^Y is the last ja NormChar mov bl,al add bl,jumps1 jmp short CompJump2NormChar:call CheckMode jnz OverWriteChar push ax xor ax,ax inc ax call InsertByte pop ax jc InsWriteEnd ;error: text buffer fullOverWriteChar:cld stosb mov byte [changed],CHANGEDInsWriteEnd:ret;-------;; helper for HandleChar;CtrlKMenu:mov bx,Ktable mov cx,4b5eh ;^K jmp short MenuCtrlQMenu:mov bx,Qtable mov cx,515eh ;^QMenu: call MakeScanCode jc EndeRet ;if no valid scancodeExtAscii:mov bl,ah ;don't use al (carries char e.g. TAB) sub bl,lowest ;= scan code first key in jumptab1 jb EndeRet cmp bl,jumps1 jae EndeRetCompJump2:and bx,0ffh shl bx,1 ;2*bx is due 2 byte per entry;------- call [bx+jumptab1];------- cmp byte [numeriere],1 ;after return from functions... jnz BZNret ;...decide whether count current line number mov word [linenr],0 push di mov si,sot xchg si,diBZNLoop:inc word [linenr] call LookForward inc di ;point to start of next line%ifndef ELKS inc di ;for DOS one extra %endif cmp di,si jbe BZNLoop pop di mov byte [numeriere],0BZNret: ret;-------MakeScanCode:call WriteTwo ;bx expects xlat-table push bx call GetChar pop bx and al,01fh cmp al,26 jnb exit xlatb mov ah,al ;returns pseudo "scancode" stcexit: cmc ;ok=ncEndeRet:ret;----------------------------------------------------------------------;; processing special keys: cursor, ins, del;KeyRet: call CheckMode jnz OvrRet call CountToLineBegin ;set si / returns ax inc si inc si xor bx,bx or ax,ax jz KeyRetNoIndent dec bxKeyRetSrch:inc bx ;search non (SPACE or TABCHAR) cmp byte [si+bx],SPACECHAR je KeyRetSrch cmp byte [si+bx],TABCHAR je KeyRetSrchKeyRetNoIndent: push si push bx ;ax is 0 or =indented chars call GoDown pop ax push ax inc ax ;1 extra for 0ah%ifndef ELKS inc ax%endif call InsertByte pop cx ;# blanks pop si ;where to copy jc SimpleRet inc word [linenr] cld%ifdef ELKS mov al,NEWLINE stosb%else mov ax,0a0dh stosw%endif jcxz SimpleRet rep movsb ;copy upper line i.e. SPACES,TABS into nextSimpleRet:retOvrRet: mov word [ch2linebeg],0 jmp short DownRet;-------KeyDown:call CountColToLineBeginVisDownRet:call GoDown call LookLineDown jmp short SetColumn;-------KeyUp: call GoUp call CountColToLineBeginVis call LookLineUp jmp short SetColumn;-------KeyPgUp:call CountColToLineBeginVis call LookPageUp jmp short SetColumn;-------KeyPgDn:call CountColToLineBeginVis call LookPgDown ;1st char last line;-------SetColumn:mov cx,[ch2linebeg] ;maximal columns xor dx,dx ;counts visible columns i.e. expand TABs dec dilod: inc di cmp dx,cx ;from CountColToLineBeginVis jae fert%ifdef ELKS cmp byte [di],NEWLINE ;don't go beyond line earlier line end%else cmp byte [di],0dh%endif jz fert cmp byte [di],TABCHAR jz isTab inc dx ;count columns jmp short lodisTab: call SpacesForTab add dl,ah cmp dx,cx ;this tab to far away right? jna lod ;nofert: ret;-------KeyHome:call CountToLineBegin sub di,ax ret;-------KeyEnd: call CountToLineEnd add di,ax ;points to a 0ah char ret;-------KeyIns: not byte [insstat] ret;-------KeyDell:call KeyLeft jz KeyDell2KeyDel: cmp di,bp jnb KeyLeftEnd mov ax,1 ;delete one @ cursor%ifndef ELKS cmp byte [di],0dh jnz KeyDell3 inc ax%endifKeyDell3:jmp DeleteByteKeyDell2:call CheckBOF ;cmp di,sot delete newline char jbe KeyLeftEnd dec word [linenr] dec di%ifndef ELKS dec di%endif jmp BisNeueZeile;-------KeyLeft:cmp byte [di-1],NEWLINE ;FIXME another check of BOF jz KeyLeftEnd ;jmp if at BOL dec diKeyLeftEnd:ret;-------KeyRight:%ifdef ELKS cmp byte [di],NEWLINE%else cmp byte [di],0dh%endif jz KeyRightEnd ;at right margin inc diKeyRightEnd:ret;-------KeyCLeft3:call CheckBOF ;cmp di,sot bzw sot-1 jbe KeyCLEnd dec di%ifndef ELKS dec di%endifKeyCtrlLeft:call KeyLeft jz KeyCLeft3 cmp byte [di],2fh jbe KeyCtrlLeft cmp byte [di-1],2fh ja KeyCtrlLeftKeyCLEnd:ret;-------KeyCRight3:call CheckEOF jae KeyCREnd inc diKeyCtrlRight:call KeyRight jz KeyCRight3 cmp byte [di],2fh jbe KeyCtrlRight cmp byte [di-1],2fh ja KeyCtrlRightKeyCREnd:ret;; processing special keys from the Ctrl-Q menu;;-------KeyCtrlQA:call AskForReplace jc CtrlQFEnd mov byte [bereitsges],2CQACtrlL:push di call FindText jc CtrlQFNotFound mov ax,[suchlaenge] call DeleteByte mov ax,[repllaenge] call InsertByte mov si, replacetext call MoveBlock jmp short CQFFound;-------KeyCtrlQF:call AskForFind jc CtrlQFEnd mov byte [bereitsges],1CQFCtrlL:push di call FindText jc CtrlQFNotFoundCQFFound:pop si ;dummyCQFNum: mov byte [numeriere],1 retCtrlQFNotFound:pop diCtrlQFEnd:ret;-------KeyCtrlQC:mov di,bp jmp short CQFNum;-------KeyCtrlQR:mov di,sot jmp short CQFNum;-------KeyCtrlQP:mov di,[veryold] jmp short CQFNum ;-------KeyCtrlL:mov al,[bereitsges] ;2^QA 1^QF 0else dec al jz CQFCtrlL dec al jz CQACtrlLSimpleRet4:ret;-------KeyCtrlQB:mov ax,di mov di,[blockbegin]CtrlQB2:or di,di ;exit of no marker set jnz CQFNum xchg di,ax ;old mov di,ax ret;-------KeyCtrlQK:xchg ax,di ;old mov ax,di mov di,[blockende] jmp short CtrlQB2;-------KeyCtrlQY:call CountToLineEnd jmp short CtrlTEnd1;-------KeyCtrlY:call CountToLineBegin sub di,ax ;di at begin call CountToLineEnd call DeleteByteCheckMarker jmp short BisNeueZeile;-------KeyCtrlT:call CountToWordBegin%ifdef ELKS cmp byte [di],NEWLINE%else cmp byte [di],0dh%endif jnz CtrlTEnd1BisNeueZeile:call CheckEOF jz SimpleRet4%ifdef ELKS mov ax,1 ;0ah%else mov ax,2 ;0dh,0ah %endifCtrlTEnd1:jmp DeleteByteCheckMarker;-------KeyCtrlQI:mov dx,asklineno call GetAsciiToInteger jbe CtrlQFEnd ;CY or ZR set mov di,sot call LookPD2 jmp CheckENum;----------------------------------------------------------------------;; processing special Keys from Ctrl-K menu;KeyCtrlKY:call CheckBlock jc SimpleRet3 ;no block: no action mov ax,[blockende] mov di,[blockbegin] sub ax,si ;block length mov di,si ;begin call DeleteByte ;out cx:=0 mov [blockende],cx mov [blockbegin],cx jmp CQFNum;-------KeyCtrlKH:xor byte [showblock],1 ;flip flopSimpleRet3:ret;-------KeyCtrlKK:mov [blockende],di jmp short KCKB;-------KeyCtrlKW:call CheckBlock jc SimpleRet2 ;no action call SaveBlock jmp short CtrlKREnd;-------KeyCtrlKC:call CopyBlock jc SimpleRet2CtrlKC2:mov [blockbegin],di add ax,di mov [blockende],ax ret;-------KeyCtrlKV:call CopyBlock jc SimpleRet2 push di cmp di,[blockbegin] pushf mov di,[blockbegin] call DeleteByte popf pop di jb CtrlKC2 mov [blockende],di sub di,axKeyCtrlKB:mov [blockbegin],diKCKB: mov byte [showblock],1SimpleRet2:ret;-------KeyCtrlKR:call ReadBlock jc CtrlKREnd call KeyCtrlKB add cx,di mov [blockende],cxCtrlKREnd:jmp RestKursPos;-------KeyCtrlKS:call SaveFile pushf ;(called by ^kd) call RestKursPos popf jc CtrlKSEnd mov byte [changed],UNCHANGEDCtrlKSEnd:ret;-------KeyCtrlKQ:cmp byte [changed],UNCHANGED jz CtrlKQ2 mov dx, asksave call DE1 call RestKursPos and al,0dfh cmp al,'N' ;confirm jnz KeyCtrlKXCtrlKQ2:mov byte [endedit],1 ret KeyCtrlKD:call KeyCtrlKS jc CtrlKSEnd mov byte [endedit],2 retKeyCtrlKX:call KeyCtrlKS jc CtrlKSEnd inc byte [endedit]KeyKXend:ret;---------------------------------------------------------------------;; the general PAGE DISPLAY function: called after any pressed key;; side effect: sets 'columne' for RestoreStatusLine function (displays columne); 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 dx counts columns in text lines; register cx screen line counter and helper for rep stos; register si text index; register di screen line buffer index;DispNewScreen:call GetEditScreenSize ;check changed tty size xor ax,ax%ifdef ELKS mov byte[isbold],al mov byte[inverse],al%endif mov [zloffset],ax mov [columne],ax mov [fileptr],di ;for seeking current cursor pos call CountColToLineBeginVis ;i.e. expanding TABs cmp ax,[columns] jb DispShortLine sub ax,[columns] inc ax mov [zloffset],axDispShortLine:call LookPgBegin ;go on 1st char upper left on screen mov si,di ;si for reading chars from text mov cx,[lines] jcxz KeyKXend ;window appears too small cld%ifndef ELKS dec si%endif mov bh,0 dec bhDispNewLine:%ifndef ELKS inc si%endif inc bh ;new line mov di,screenline ;line display buffer xor dx,dx ;reset char counter mov bl,0 ;reset screen column%ifdef LESSWRITEOPS cmp cx,1 ;not in status line jz DCL0 call SetColor2 ;set initial character color per each lineDCL0:%endifDispCharLoop: cmp si,[fileptr] ;display char @ cursor postion ? jnz DispCharL1 cmp byte[tabcnt],0 jnz DispCharL1 mov [kurspos],bx mov byte [columne],bl mov ax,[zloffset] ;chars scrolled left hidden add [columne],ax%ifdef ELKS stc call SetInverseStatus jnc DispEndLine%else mov ah,kursorfarbe cmp byte [insstat],1 jz DispEndLine%endifDispCharL1:call SetColor;-------DispEndLine:cmp si,bp 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 si,bp jnz ELZ6 inc si ;set si>bp will later trigger "ja FillLine" jmp short ELZ2 ELZ6: lodsb cmp al,TABCHAR jnz ELZ3 push ax ;preserve color attribute call SpacesForTab ;ah = space_up_to_next_tab location dec ah ;count out the tab char itself mov byte[tabcnt],ah pop axELZ2: mov al,SPACECHARELZ3: %ifdef ELKS cmp al,NEWLINE%else cmp al,0dh%endif jz FillLine cmp al,SPACECHAR jae ELZ9 ;simply ignore chars like carriage_return etc. mov al,'.'ELZ9: cmp al,7fh jne ELZ8 mov al,'.'ELZ8: cmp bl,byte [columns] ;screen width jae DispEndLine ;continue reading line until end inc dx ;also count hidden chars (left margin)KZA6: cmp dx,[zloffset] jbe DispCharLoop ;load new char (but no display)%ifdef ELKS stosB
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -