mirror of
https://github.com/microsoft/MS-DOS.git
synced 2024-11-29 17:15:47 +00:00
1846 lines
54 KiB
NASM
1846 lines
54 KiB
NASM
title EDLIN for MSDOS 2.0
|
||
|
||
;-----------------------------------------------------------------------;
|
||
; REVISION HISTORY: ;
|
||
; ;
|
||
; V1.02 ;
|
||
; ;
|
||
; V2.00 9/13/82 M.A. Ulloa ;
|
||
; Modified to use Pathnames in command line file ;
|
||
; specification, modified REPLACE to use an empty ;
|
||
; string intead of the old replace string when this ;
|
||
; is missing, and search and replace now start from ;
|
||
; first line of buffer (like old version of EDLIN) ;
|
||
; instead than current+1 line. Also added the U and ;
|
||
; V commands that search (replace) starting from the ;
|
||
; current+1 line. ;
|
||
; ;
|
||
; 9/15/82 M.A. Ulloa ;
|
||
; Added the quote character (^V). ;
|
||
; ;
|
||
; 9/16/82 M.A. Ulloa ;
|
||
; Corrected bug about use of quote char when going ;
|
||
; into default insert mode. Also corrected the problem ;
|
||
; with ^Z being the end of file marker. End of file is ;
|
||
; reached when an attempt to read returns less chars ;
|
||
; than requested. ;
|
||
; ;
|
||
; 9/17/82 M.A. Ulloa ;
|
||
; Corrected bug about boundaries for Copy ;
|
||
; ;
|
||
; 10/4/82 Rev. 1 M.A. Ulloa ;
|
||
; The IBM version now does NOT have the U and V ;
|
||
; commands. The MSDOS version HAS the U and V commands. ;
|
||
; Added the B switch, and modified the effect of ;
|
||
; the quote char. ;
|
||
; ;
|
||
; 10/7/82 Rev. 2 M.A. Ulloa ;
|
||
; Changed the S and R commands to start from the ;
|
||
; current line+1 (as U and V did). Took away U and V in ;
|
||
; all versions. ;
|
||
; ;
|
||
; 10/13/82 Rev. 3 M.A. Ulloa ;
|
||
; Now if parameter1 < 1 then parameter1 = 1 ;
|
||
; ;
|
||
; 10/15/82 Rev. 4 M.A. Ulloa ;
|
||
; Param4 if specified must be an absolute number that ;
|
||
; reprecents the count. ;
|
||
; ;
|
||
; 10/18/82 Rev. 5 M.A. Ulloa ;
|
||
; Fixed problem with trying to edit files with the ;
|
||
; same name as directories. Also, if the end of file is ;
|
||
; reached it checks that a LF is the last character, ;
|
||
; otherwise it inserts a CRLF pair at the end. ;
|
||
; ;
|
||
; 10/20/82 Rev. 6 M.A.Ulloa ;
|
||
; Changed the text of some error messages for IBM and ;
|
||
; rewrite PAGE. ;
|
||
; ;
|
||
; 10/25/82 Rev. 7 M.A.Ulloa ;
|
||
; Made all messages as in the IBM vers. ;
|
||
; ;
|
||
; 10/28/82 Rev. 8 M.A.Ulloa ;
|
||
; Corrected problem with parsing for options. ;
|
||
; ;
|
||
; Rev. 9 Aaron Reynolds ;
|
||
; Made error messages external. ;
|
||
; ;
|
||
; 12/08/82 Rev. 10 M.A. Ulloa ;
|
||
; Corrected problem arising with having to restore ;
|
||
; the old directory in case of a file name error. ;
|
||
; ;
|
||
; 12/17/82 Rev. 11 M.A. Ulloa ;
|
||
; Added the ROPROT equate for R/O file protection. ;
|
||
; It causes only certain operations (L,P,S,W,A, and Q) ;
|
||
; to be allowed on read only files. ;
|
||
; ;
|
||
; 12/29/82 Rev. 12 M.A. Ulloa :
|
||
; Added the creation error message. ;
|
||
; ;
|
||
; 4/14/83 Rev. 13 N.Panners ;
|
||
; Fixed bug in Merge which lost char if not ^Z. ;
|
||
; Fixed bug in Copy to correctly check ;
|
||
; for full buffers. ;
|
||
; ;
|
||
; ;
|
||
; 7/23/83 Rev. 14 N.Panners ;
|
||
; Split EDLIN into two seperate modules to ;
|
||
; allow assembly of sources on an IBM PC ;
|
||
; EDLIN and EDLPROC ;
|
||
; ;
|
||
;-----------------------------------------------------------------------;
|
||
|
||
|
||
FALSE EQU 0
|
||
TRUE EQU NOT FALSE
|
||
|
||
KANJI EQU FALSE
|
||
|
||
roprot equ true ;set to TRUE if protection to r/o files
|
||
; desired.
|
||
FCB EQU 5CH
|
||
|
||
Comand_Line_Length equ 128
|
||
quote_char equ 16h ;quote character = ^V
|
||
|
||
|
||
PAGE
|
||
|
||
.xlist
|
||
INCLUDE DOSSYM.ASM
|
||
.list
|
||
|
||
|
||
SUBTTL Contants and Data areas
|
||
PAGE
|
||
|
||
PROMPT EQU "*"
|
||
STKSIZ EQU 80H
|
||
|
||
CODE SEGMENT PUBLIC
|
||
CODE ENDS
|
||
|
||
CONST SEGMENT PUBLIC WORD
|
||
CONST ENDS
|
||
|
||
DATA SEGMENT PUBLIC WORD
|
||
DATA ENDS
|
||
|
||
DG GROUP CODE,CONST,DATA
|
||
|
||
CONST SEGMENT PUBLIC WORD
|
||
|
||
EXTRN BADDRV:BYTE,NDNAME:BYTE,bad_vers_err:BYTE,opt_err:BYTE
|
||
EXTRN NOBAK:BYTE,BADCOM:BYTE,NEWFIL:BYTE,DEST:BYTE,MRGERR:BYTE
|
||
EXTRN NODIR:BYTE,DSKFUL:BYTE,MEMFUL:BYTE,FILENM:BYTE
|
||
EXTRN NOSUCH:BYTE,TOOLNG:BYTE,EOF:BYTE,ro_err:byte,bcreat:byte
|
||
|
||
PUBLIC TXT1,TXT2,FUDGE,USERDIR,HARDCH
|
||
|
||
BAK DB "BAK"
|
||
|
||
make db "***MAUlloa/Microsoft/V20***"
|
||
rev db "14"
|
||
|
||
if roprot ;***** R/O *****
|
||
roflag db 0 ; =1 if file is r/o
|
||
endif
|
||
|
||
fourth db 0 ;fourth parameter flag
|
||
|
||
loadmod db 0 ;Load mode flag, 0 = ^Z marks the
|
||
; end of a file, 1 = viceversa.
|
||
hardch dd ?
|
||
|
||
the_root db 0 ;root directory flag
|
||
|
||
fudge db 0 ;directory changed flag
|
||
user_drive db 0
|
||
|
||
|
||
optchar db "-"
|
||
|
||
dirchar db "/",0
|
||
|
||
userdir db "/",0
|
||
db (dirstrlen) dup(0)
|
||
|
||
fname_buffer db Comand_Line_Length dup(0)
|
||
;-----------------------------------------------------------------------;
|
||
|
||
TXT1 DB 0,80H DUP (?)
|
||
TXT2 DB 0,80H DUP (?)
|
||
DELFLG DB 0
|
||
|
||
CONST ENDS
|
||
|
||
DATA SEGMENT PUBLIC WORD
|
||
|
||
PUBLIC QFLG,FCB2,OLDLEN,PARAM1,PARAM2,OLDDAT,SRCHFLG
|
||
PUBLIC COMLINE,NEWLEN,SRCHMOD,CURRENT,LSTFND,NUMPOS
|
||
PUBLIC LSTNUM,SRCHCNT,POINTER,START,ENDTXT,USER_DRIVE
|
||
|
||
;-----------------------------------------------------------------------;
|
||
; Be carefull when adding parameters, they have to follow the
|
||
; order in which they apperar here. (this is a table, ergo it
|
||
; is indexed thru a pointer, and random additions will cause the
|
||
; wrong item to be accessed). Also param4 is known to be the
|
||
; count parameter, and known to be the fourth entry in the table
|
||
; so it receives special treatment. (See GETNUM)
|
||
|
||
PARAM1 DW 1 DUP (?)
|
||
PARAM2 DW 1 DUP (?)
|
||
PARAM3 DW 1 DUP (?)
|
||
PARAM4 DW 1 DUP (?)
|
||
|
||
;-----------------------------------------------------------------------;
|
||
|
||
PTR_1 DW 1 DUP (?)
|
||
PTR_2 DW 1 DUP (?)
|
||
PTR_3 DW 1 DUP (?)
|
||
COPYSIZ DW 1 DUP (?)
|
||
OLDLEN DW 1 DUP (?)
|
||
NEWLEN DW 1 DUP (?)
|
||
LSTFND DW 1 DUP (?)
|
||
LSTNUM DW 1 DUP (?)
|
||
NUMPOS DW 1 DUP (?)
|
||
SRCHCNT DW 1 DUP (?)
|
||
CURRENT DW 1 DUP (?)
|
||
POINTER DW 1 DUP (?)
|
||
ONE4TH DW 1 DUP (?)
|
||
THREE4TH DW 1 DUP (?)
|
||
LAST DW 1 DUP (?)
|
||
ENDTXT DW 1 DUP (?)
|
||
COMLINE DW 1 DUP (?)
|
||
LASTLIN DW 1 DUP (?)
|
||
COMBUF DB 82H DUP (?)
|
||
EDITBUF DB 258 DUP (?)
|
||
EOL DB 1 DUP (?)
|
||
FCB2 DB 37 DUP (?)
|
||
FCB3 DB 37 DUP (?)
|
||
fake_fcb db 37 dup (?) ;fake for size figuring
|
||
QFLG DB 1 DUP (?)
|
||
HAVEOF DB 1 DUP (?)
|
||
ENDING DB 1 DUP (?)
|
||
SRCHFLG DB 1 DUP (?)
|
||
amnt_req dw 1 dup (?) ;ammount of bytes requested to read
|
||
olddat db 1 dup (?) ;Used in replace and search,
|
||
; replace by old data flag (1=yes)
|
||
srchmod db 1 dup (?) ;Search mode: 1=from current+1 to
|
||
; end of buffer, 0=from beg. of
|
||
; buffer to the end (old way).
|
||
MOVFLG DB 1 DUP (?)
|
||
DB STKSIZ DUP (?)
|
||
|
||
STACK LABEL BYTE
|
||
START LABEL WORD
|
||
|
||
DATA ENDS
|
||
|
||
SUBTTL Main Body
|
||
PAGE
|
||
|
||
CODE SEGMENT PUBLIC
|
||
|
||
ASSUME CS:DG,DS:DG,SS:DG,ES:DG
|
||
|
||
EXTRN QUIT:NEAR,QUERY:NEAR,FNDFIRST:NEAR,FNDNEXT:NEAR
|
||
EXTRN UNQUOTE:NEAR,LF:NEAR,CRLF:NEAR,OUT:NEAR
|
||
EXTRN REST_DIR:NEAR,KILL_BL:NEAR,INT_24:NEAR
|
||
EXTRN FINDLIN:NEAR,SHOWNUM:NEAR,SCANLN:NEAR
|
||
|
||
if Kanji
|
||
EXTRN TESTKANJ:NEAR
|
||
endif
|
||
|
||
PUBLIC CHKRANGE
|
||
|
||
ORG 100H
|
||
|
||
EDLIN:
|
||
JMP SIMPED
|
||
|
||
edl_pad db 0e00h dup (?)
|
||
|
||
HEADER DB "Vers 2.14"
|
||
|
||
NONAME:
|
||
MOV DX,OFFSET DG:NDNAME
|
||
ERRJ: JMP xERROR
|
||
|
||
SIMPED:
|
||
MOV BYTE PTR [ENDING],0
|
||
MOV SP,OFFSET DG:STACK
|
||
|
||
;Code to print header
|
||
; PUSH AX
|
||
; MOV DX,OFFSET DG:HEADER
|
||
; MOV AH,STD_CON_STRING_OUTPUT
|
||
; INT 21H
|
||
; POP AX
|
||
|
||
;----- Check Version Number --------------------------------------------;
|
||
push ax
|
||
mov ah,Get_Version
|
||
int 21h
|
||
cmp al,2
|
||
jae vers_ok ; version >= 2, enter editor
|
||
mov dx,offset dg:bad_vers_err
|
||
jmp short errj
|
||
;-----------------------------------------------------------------------;
|
||
|
||
vers_ok:
|
||
|
||
;----- Process Pathnames -----------------------------------------------;
|
||
|
||
mov ax,(char_oper shl 8) ;get switch character
|
||
int 21h
|
||
cmp dl,"/"
|
||
jnz slashok ;if not / , then not PC
|
||
mov [dirchar],"\" ;in PC, dir separator = \
|
||
mov [userdir],"\"
|
||
mov [optchar],"/" ;in PC, option char = /
|
||
|
||
slashok:
|
||
mov si,81h ;point to cammand line
|
||
|
||
call kill_bl
|
||
cmp al,13 ;A carriage return?
|
||
je noname ;yes, file name missing
|
||
|
||
mov di,offset dg:fname_buffer
|
||
xor cx,cx ;zero pathname length
|
||
|
||
next_char:
|
||
stosb ;put patname in buffer
|
||
inc cx
|
||
lodsb
|
||
cmp al,' '
|
||
je xx1
|
||
cmp al,13 ; a CR ?
|
||
je name_copied
|
||
cmp al,[optchar] ; an option character?
|
||
je an_option
|
||
jmp short next_char
|
||
|
||
xx1:
|
||
dec si
|
||
call kill_bl
|
||
cmp al,[optchar]
|
||
jne name_copied
|
||
|
||
an_option:
|
||
lodsb ;get the option
|
||
cmp al,'B'
|
||
je b_opt
|
||
cmp al,'b'
|
||
je b_opt
|
||
mov dx,offset dg:opt_err ;bad option specified
|
||
jmp xerror
|
||
|
||
b_opt:
|
||
mov [loadmod],1
|
||
|
||
name_copied:
|
||
mov byte ptr dg:[di],0 ;nul terminate the pathname
|
||
|
||
if roprot ;***** R/O *****
|
||
;----- Check that file is not R/O --------------------------------------;
|
||
push cx ;save character count
|
||
mov dx,offset dg:fname_buffer
|
||
mov al,0 ;get attributes
|
||
mov ah,chmod
|
||
int 21h
|
||
jc attr_are_ok
|
||
and cl,00000001b ;mask all but: r/o
|
||
jz attr_are_ok ;if all = 0 then file ok to edit,
|
||
mov dg:[roflag],01h ;otherwise: Error (GONG!!!)
|
||
attr_are_ok:
|
||
pop cx ;restore character count
|
||
endif
|
||
|
||
;----- Scan for directory ----------------------------------------------;
|
||
dec di ;adjust to the end of the pathname
|
||
|
||
IF KANJI
|
||
mov dx,offset dg: fname_buffer
|
||
PUSH DX
|
||
PUSH DI
|
||
MOV BX,DI
|
||
MOV DI,DX
|
||
DELLOOP:
|
||
CMP DI,BX
|
||
Jae GOTDELE
|
||
MOV AL,[DI]
|
||
INC DI
|
||
CALL TESTKANJ
|
||
JZ NOTKANJ11
|
||
INC DI
|
||
JMP DELLOOP
|
||
|
||
NOTKANJ11:
|
||
cmp al,dg:[dirchar]
|
||
JNZ DELLOOP
|
||
MOV DX,DI ;Point to char after '/'
|
||
DEC DX
|
||
DEC DX ;Point to char before '/'
|
||
JMP DELLOOP
|
||
|
||
GOTDELE:
|
||
MOV DI,DX
|
||
POP AX ;Initial DI
|
||
POP DX
|
||
SUB AX,DI ;Distance moved
|
||
SUB CX,AX ;Set correct CX
|
||
CMP DX,DI
|
||
JB sj1 ;Found a pathsep
|
||
JA sj2 ;Started with a pathsep, root
|
||
MOV AX,[DI]
|
||
CALL TESTKANJ
|
||
JNZ same_dirj
|
||
XCHG AH,AL
|
||
cmp al,dg:[dirchar]
|
||
jz sj1 ;One character directory
|
||
same_dirj:
|
||
ELSE
|
||
mov al,dg:[dirchar] ;get directory separator character
|
||
std ;scan backwards
|
||
repnz scasb ;(cx has the pathname length)
|
||
cld ;reset direction, just in case
|
||
jz sj1
|
||
ENDIF
|
||
|
||
jmp same_dir ;no dir separator char. found, the
|
||
; file is in the current directory
|
||
; of the corresponding drive. Ergo,
|
||
; the FCB contains the data already.
|
||
|
||
sj1:
|
||
jcxz sj2 ;no more chars left, it refers to root
|
||
cmp byte ptr [di],':' ;is the prvious character a disk def?
|
||
jne not_root
|
||
sj2:
|
||
mov dg:[the_root],01h ;file is in the root
|
||
not_root:
|
||
inc di ;point to dir separator char.
|
||
mov al,0
|
||
stosb ;nul terminate directory name
|
||
pop ax
|
||
push di ;save pointer to file name
|
||
mov dg:[fudge],01h ;remember that the current directory
|
||
; has been changed.
|
||
|
||
;----- Save current directory for exit ---------------------------------;
|
||
mov ah,get_default_drive ;save current drive
|
||
int 21h
|
||
mov dg:[user_drive],al
|
||
|
||
mov dl,byte ptr ds:[fcb] ;get specified drive if any
|
||
or dl,dl ;default disk?
|
||
jz same_drive
|
||
dec dl ;adjust to real drive (a=0,b=1,...)
|
||
mov ah,set_default_drive ;change disks
|
||
int 21h
|
||
cmp al,-1 ;error?
|
||
jne same_drive
|
||
mov dx,offset dg:baddrv
|
||
jmp xerror
|
||
|
||
same_drive:
|
||
mov ah,get_default_dpb
|
||
int 21h
|
||
|
||
assume ds:nothing
|
||
|
||
cmp al,-1 ;bad drive? (should always be ok)
|
||
jne drvisok
|
||
mov dx,offset dg:baddrv
|
||
jmp xerror
|
||
|
||
drvisok:
|
||
cmp [bx.dpb_current_dir],0
|
||
je curr_is_root
|
||
mov si,bx
|
||
add si,dpb_dir_text
|
||
mov di,offset dg:userdir + 1
|
||
|
||
dir_save_loop:
|
||
lodsb
|
||
stosb
|
||
or al,al
|
||
jnz dir_save_loop
|
||
|
||
curr_is_root:
|
||
push cs
|
||
pop ds
|
||
|
||
assume ds:dg
|
||
|
||
|
||
;----- Change directories ----------------------------------------------;
|
||
cmp [the_root],01h
|
||
mov dx,offset dg:[dirchar] ;assume the root
|
||
je sj3
|
||
mov dx,offset dg:[fname_buffer]
|
||
sj3:
|
||
mov ah,chdir ;change directory
|
||
int 21h
|
||
mov dx,offset dg:baddrv
|
||
jnc no_errors
|
||
jmp xerror
|
||
no_errors:
|
||
|
||
;----- Set Up int 24 intercept -----------------------------------------;
|
||
|
||
mov ax,(get_interrupt_vector shl 8) or 24h
|
||
int 21h
|
||
mov word ptr [hardch],bx
|
||
mov word ptr [hardch+2],es
|
||
mov ax,(set_interrupt_vector shl 8) or 24h
|
||
mov dx,offset dg:int_24
|
||
int 21h
|
||
push cs
|
||
pop es
|
||
|
||
;----- Parse filename to FCB -------------------------------------------;
|
||
pop si
|
||
mov di,fcb
|
||
mov ax,(parse_file_descriptor shl 8) or 1
|
||
int 21h
|
||
push ax
|
||
|
||
;-----------------------------------------------------------------------;
|
||
|
||
same_dir:
|
||
pop ax
|
||
OR AL,AL
|
||
MOV DX,OFFSET DG:BADDRV
|
||
jz sj4
|
||
jmp xerror
|
||
sj4:
|
||
CMP BYTE PTR DS:[FCB+1]," "
|
||
jnz sj5
|
||
jmp noname
|
||
sj5:
|
||
MOV SI,OFFSET DG:BAK
|
||
MOV DI,FCB+9
|
||
MOV CX,3
|
||
;File must not have .BAK extension
|
||
REPE CMPSB
|
||
JZ NOTBAK
|
||
;Open input file
|
||
MOV AH,FCB_OPEN
|
||
MOV DX,FCB
|
||
INT 21H
|
||
MOV [HAVEOF],AL
|
||
OR AL,AL
|
||
JZ HAVFIL
|
||
|
||
;----- Check that file is not a directory ------------
|
||
mov ah,fcb_create
|
||
mov dx,fcb
|
||
int 21h
|
||
or al,al
|
||
jz sj50 ;no error found
|
||
mov dx,offset dg:bcreat ;creation error
|
||
jmp xerror
|
||
sj50:
|
||
mov ah,fcb_close ;no error, close the file
|
||
mov dx,fcb
|
||
int 21h
|
||
mov ah,fcb_delete ;delete the file
|
||
mov dx,fcb
|
||
int 21h
|
||
|
||
;-----------------------------------------------------
|
||
|
||
MOV DX,OFFSET DG:NEWFIL
|
||
MOV AH,STD_CON_STRING_OUTPUT
|
||
INT 21H
|
||
HAVFIL:
|
||
MOV SI,FCB
|
||
MOV DI,OFFSET DG:FCB2
|
||
MOV CX,9
|
||
REP MOVSB
|
||
MOV AL,"$"
|
||
STOSB
|
||
STOSB
|
||
STOSB
|
||
MAKFIL:
|
||
;Create .$$$ file to make sure directory has room
|
||
MOV DX,OFFSET DG:FCB2
|
||
MOV AH,FCB_CREATE
|
||
INT 21H
|
||
OR AL,AL
|
||
JZ SETUP
|
||
CMP BYTE PTR [DELFLG],0
|
||
JNZ NOROOM
|
||
CALL DELBAK
|
||
JMP MAKFIL
|
||
NOROOM:
|
||
MOV DX,OFFSET DG:NODIR
|
||
JMP xERROR
|
||
NOTBAK:
|
||
MOV DX,OFFSET DG:NOBAK
|
||
JMP xERROR
|
||
SETUP:
|
||
XOR AX,AX
|
||
MOV WORD PTR DS:[FCB+fcb_RR],AX ;Set RR field to zero
|
||
MOV WORD PTR DS:[FCB+fcb_RR+2],AX
|
||
MOV WORD PTR [FCB2+fcb_RR],AX
|
||
MOV WORD PTR [FCB2+fcb_RR+2],AX
|
||
INC AX
|
||
MOV WORD PTR DS:[FCB+fcb_RECSIZ],AX ;Set record length to 1
|
||
MOV WORD PTR [FCB2+fcb_RECSIZ],AX
|
||
MOV DX,OFFSET DG:START
|
||
MOV DI,DX
|
||
MOV AH,SET_DMA
|
||
INT 21H
|
||
MOV CX,DS:[6]
|
||
DEC CX
|
||
MOV [LAST],CX
|
||
TEST BYTE PTR [HAVEOF],-1
|
||
JNZ SAVEND
|
||
SUB CX,OFFSET DG:START ;Available memory
|
||
SHR CX,1 ;1/2 of available memory
|
||
MOV AX,CX
|
||
SHR CX,1 ;1/4 of available memory
|
||
MOV [ONE4TH],CX ;Save amount of 1/4 full
|
||
ADD CX,AX ;3/4 of available memory
|
||
MOV DX,CX
|
||
ADD DX,OFFSET DG:START
|
||
MOV [THREE4TH],DX ;Save pointer to 3/4 full
|
||
;Read in input file
|
||
MOV DX,FCB
|
||
MOV AH,FCB_RANDOM_READ_BLOCK
|
||
mov [amnt_req],cx ;save ammount of chars requested
|
||
INT 21H
|
||
CALL SCANEOF
|
||
ADD DI,CX ;Point to last byte
|
||
SAVEND:
|
||
CLD
|
||
MOV BYTE PTR [DI],1AH
|
||
MOV [ENDTXT],DI
|
||
MOV BYTE PTR [COMBUF],128
|
||
MOV BYTE PTR [EDITBUF],255
|
||
MOV BYTE PTR [EOL],10
|
||
MOV [POINTER],OFFSET DG:START
|
||
MOV [CURRENT],1
|
||
MOV [PARAM1],1
|
||
TEST BYTE PTR [HAVEOF],-1
|
||
JNZ COMMAND
|
||
CALL APPEND
|
||
|
||
COMMAND:
|
||
MOV SP, OFFSET DG:STACK
|
||
MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 23H
|
||
MOV DX,OFFSET DG:ABORTCOM
|
||
INT 21H
|
||
MOV AL,PROMPT
|
||
CALL OUT
|
||
MOV DX,OFFSET DG:COMBUF
|
||
MOV AH,STD_CON_STRING_INPUT
|
||
INT 21H
|
||
MOV [COMLINE],OFFSET DG:COMBUF + 2
|
||
MOV AL,10
|
||
CALL OUT
|
||
PARSE:
|
||
MOV [PARAM2],0
|
||
MOV [PARAM3],0
|
||
MOV [PARAM4],0
|
||
mov [fourth],0 ;reset the fourth parameter flag
|
||
MOV BYTE PTR [QFLG],0
|
||
MOV SI,[COMLINE]
|
||
MOV BP,OFFSET DG:PARAM1
|
||
XOR DI,DI
|
||
CHKLP:
|
||
CALL GETNUM
|
||
MOV [BP+DI],DX
|
||
INC DI
|
||
INC DI
|
||
CALL SKIP1
|
||
CMP AL,","
|
||
JNZ CHKNXT
|
||
INC SI
|
||
CHKNXT:
|
||
DEC SI
|
||
CMP DI,8
|
||
JB CHKLP
|
||
CALL SKIP
|
||
CMP AL,"?"
|
||
JNZ DISPATCH
|
||
MOV [QFLG],AL
|
||
CALL SKIP
|
||
DISPATCH:
|
||
CMP AL,5FH
|
||
JBE UPCASE
|
||
AND AL,5FH
|
||
UPCASE:
|
||
MOV DI,OFFSET DG:COMTAB
|
||
MOV CX,NUMCOM
|
||
REPNE SCASB
|
||
JNZ COMERR
|
||
MOV BX,CX
|
||
MOV AX,[PARAM2]
|
||
OR AX,AX
|
||
JZ PARMOK
|
||
CMP AX,[PARAM1]
|
||
JB COMERR ;Param. 2 must be >= param 1
|
||
PARMOK:
|
||
MOV [COMLINE],SI
|
||
|
||
if roprot ;***** R/O *****
|
||
cmp [roflag],01 ;file r/o?
|
||
jne paramok2
|
||
cmp byte ptr [bx+rotable],01 ;operation allowed?
|
||
je paramok2
|
||
mov dx,offset dg:ro_err ;error
|
||
jmp short comerr1
|
||
paramok2:
|
||
endif
|
||
|
||
SHL BX,1
|
||
CALL [BX+TABLE]
|
||
COMOVER:
|
||
MOV SI,[COMLINE]
|
||
CALL SKIP
|
||
CMP AL,0DH
|
||
JZ COMMANDJ
|
||
CMP AL,1AH
|
||
JZ DELIM
|
||
CMP AL,";"
|
||
JNZ NODELIM
|
||
DELIM:
|
||
INC SI
|
||
NODELIM:
|
||
DEC SI
|
||
MOV [COMLINE],SI
|
||
JMP PARSE
|
||
|
||
COMMANDJ:
|
||
JMP COMMAND
|
||
|
||
SKIP:
|
||
LODSB
|
||
SKIP1:
|
||
CMP AL," "
|
||
JZ SKIP
|
||
RET1: RET
|
||
|
||
CHKRANGE:
|
||
CMP [PARAM2],0
|
||
JZ RET1
|
||
CMP BX,[PARAM2]
|
||
JBE RET1
|
||
COMERR:
|
||
MOV DX,OFFSET DG:BADCOM
|
||
COMERR1:
|
||
MOV AH,STD_CON_STRING_OUTPUT
|
||
INT 21H
|
||
JMP COMMAND
|
||
|
||
|
||
GETNUM:
|
||
CALL SKIP
|
||
cmp di,6 ;Is this the fourth parameter?
|
||
jne sk1
|
||
mov [fourth],1 ;yes, set the flag
|
||
sk1:
|
||
CMP AL,"."
|
||
JZ CURLIN
|
||
CMP AL,"#"
|
||
JZ MAXLIN
|
||
CMP AL,"+"
|
||
JZ FORLIN
|
||
CMP AL,"-"
|
||
JZ BACKLIN
|
||
MOV DX,0
|
||
MOV CL,0 ;Flag no parameter seen yet
|
||
NUMLP:
|
||
CMP AL,"0"
|
||
JB NUMCHK
|
||
CMP AL,"9"
|
||
JA NUMCHK
|
||
CMP DX,6553 ;Max line/10
|
||
JAE COMERR ;Ten times this is too big
|
||
MOV CL,1 ;Parameter digit has been found
|
||
SUB AL,"0"
|
||
MOV BX,DX
|
||
SHL DX,1
|
||
SHL DX,1
|
||
ADD DX,BX
|
||
SHL DX,1
|
||
CBW
|
||
ADD DX,AX
|
||
LODSB
|
||
JMP SHORT NUMLP
|
||
NUMCHK:
|
||
CMP CL,0
|
||
JZ RET1
|
||
OR DX,DX
|
||
JZ COMERR ;Don't allow zero as a parameter
|
||
RET
|
||
|
||
CURLIN:
|
||
cmp [fourth],1 ;the fourth parameter?
|
||
je comerra ;yes, an error
|
||
MOV DX,[CURRENT]
|
||
LODSB
|
||
RET
|
||
MAXLIN:
|
||
cmp [fourth],1 ;the fourth parameter?
|
||
je comerra ;yes, an error
|
||
MOV DX,-2
|
||
LODSB
|
||
RET
|
||
FORLIN:
|
||
cmp [fourth],1 ;the fourth parameter?
|
||
je comerra ;yes, an error
|
||
CALL GETNUM
|
||
ADD DX,[CURRENT]
|
||
RET
|
||
BACKLIN:
|
||
cmp [fourth],1 ;the fourth parameter?
|
||
je comerra ;yes, an error
|
||
CALL GETNUM
|
||
MOV BX,[CURRENT]
|
||
SUB BX,DX
|
||
jns sk2 ;if below beg of buffer then default to the
|
||
mov bx,1 ; beg of buffer (line1)
|
||
sk2:
|
||
MOV DX,BX
|
||
RET
|
||
|
||
comerra:
|
||
jmp comerr
|
||
|
||
|
||
COMTAB DB "QTCMWASRDLPIE;",13
|
||
|
||
NUMCOM EQU $-COMTAB
|
||
|
||
;-----------------------------------------------------------------------;
|
||
; Carefull changing the order of the next two tables. They are
|
||
; linked and chnges should be be to both.
|
||
|
||
TABLE DW NOCOM ;No command--edit line
|
||
DW NOCOM
|
||
DW ENDED
|
||
DW INSERT
|
||
DW PAGE
|
||
DW LIST
|
||
DW DELETE
|
||
dw replac_from_curr ;replace from current+1 line
|
||
dw search_from_curr ;search from current+1 line
|
||
DW APPEND
|
||
DW EWRITE
|
||
DW MOVE
|
||
DW COPY
|
||
DW MERGE
|
||
|
||
if roprot ;***** R/O *****
|
||
DW QUIT1
|
||
else
|
||
DW QUIT
|
||
endif
|
||
|
||
if roprot ;***** R/O *****
|
||
;-----------------------------------------------------------------------;
|
||
; If = 1 then the command can be executed with a file that
|
||
; is r/o. If = 0 the command can not be executed, and error.
|
||
|
||
ROTABLE db 0 ;NOCOM
|
||
db 0 ;NOCOM
|
||
db 0 ;ENDED
|
||
db 0 ;INSERT
|
||
db 1 ;PAGE
|
||
db 1 ;LIST
|
||
db 0 ;DELETE
|
||
db 0 ;replac_from_curr
|
||
db 1 ;search_from_curr
|
||
db 1 ;APPEND
|
||
db 1 ;EWRITE
|
||
db 0 ;MOVE
|
||
db 0 ;COPY
|
||
db 0 ;MERGE
|
||
db 1 ;QUIT
|
||
|
||
;-----------------------------------------------------------------------;
|
||
endif
|
||
|
||
if roprot ;***** R/O *****
|
||
quit1:
|
||
cmp [roflag],01 ;are we in r/o mode?
|
||
jne q3 ;no query....
|
||
MOV DX,OFFSET DG:FCB2 ;yes, quit without query.
|
||
MOV AH,FCB_CLOSE
|
||
INT 21H
|
||
MOV AH,FCB_DELETE
|
||
INT 21H
|
||
call rest_dir ;restore directory if needed
|
||
INT 20H
|
||
q3:
|
||
call quit
|
||
endif
|
||
|
||
SCANEOF:
|
||
cmp [loadmod],0
|
||
je sj52
|
||
|
||
;----- Load till physical end of file
|
||
cmp cx,word ptr[amnt_req]
|
||
jb sj51
|
||
xor al,al
|
||
inc al ;reset zero flag
|
||
ret
|
||
sj51:
|
||
jcxz sj51b
|
||
push di ;get rid of any ^Z at the end of the file
|
||
add di,cx
|
||
dec di ;points to last char
|
||
cmp byte ptr [di],1ah
|
||
pop di
|
||
jne sj51b
|
||
dec cx
|
||
sj51b:
|
||
xor al,al ;set zero flag
|
||
call check_end ;check that we have a CRLF pair at the end
|
||
ret
|
||
|
||
;----- Load till first ^Z is found
|
||
sj52:
|
||
PUSH DI
|
||
PUSH CX
|
||
MOV AL,1AH
|
||
or cx,cx
|
||
jz not_found ;skip with zero flag set
|
||
REPNE SCASB ;Scan for end of file mark
|
||
jnz not_found
|
||
LAHF ;Save flags momentarily
|
||
inc cx ;include the ^Z
|
||
SAHF ;Restore flags
|
||
not_found:
|
||
mov di,cx ;not found at the end
|
||
POP CX
|
||
LAHF ;Save flags momentarily
|
||
SUB CX,DI ;Reduce byte count if EOF found
|
||
SAHF ;Restore flags
|
||
POP DI
|
||
call check_end ;check that we have a CRLF pair at the end
|
||
|
||
RET2: RET
|
||
|
||
|
||
;-----------------------------------------------------------------------
|
||
; If the end of file was found, then check that the last character
|
||
; in the file is a LF. If not put a CRLF pair in.
|
||
|
||
check_end:
|
||
jnz not_end ;end was not reached
|
||
pushf ;save return flag
|
||
push di ;save pointer to buffer
|
||
add di,cx ;points to one past end on text
|
||
dec di ;points to last character
|
||
cmp di,offset dg:start
|
||
je check_no
|
||
cmp byte ptr[di],0ah ;is a LF the last character?
|
||
je check_done ;yes, exit
|
||
check_no:
|
||
mov byte ptr[di+1],0dh ;no, put a CR
|
||
inc cx ;one more char in text
|
||
mov byte ptr[di+2],0ah ;put a LF
|
||
inc cx ;another character at the end
|
||
check_done:
|
||
pop di
|
||
popf
|
||
not_end:
|
||
ret
|
||
|
||
|
||
|
||
NOMOREJ:JMP NOMORE
|
||
|
||
APPEND:
|
||
TEST BYTE PTR [HAVEOF],-1
|
||
JNZ NOMOREJ
|
||
MOV DX,[ENDTXT]
|
||
CMP [PARAM1],0 ;See if parameter is missing
|
||
JNZ PARMAPP
|
||
CMP DX,[THREE4TH] ;See if already 3/4ths full
|
||
JAE RET2 ;If so, then done already
|
||
PARMAPP:
|
||
MOV DI,DX
|
||
MOV AH,SET_DMA
|
||
INT 21H
|
||
MOV CX,[LAST]
|
||
SUB CX,DX ;Amount of memory available
|
||
jnz sj53
|
||
jmp memerr
|
||
sj53:
|
||
MOV DX,FCB
|
||
mov [amnt_req],cx ;save ammount of chars requested
|
||
MOV AH,FCB_RANDOM_READ_BLOCK
|
||
INT 21H ;Fill memory with file data
|
||
MOV [HAVEOF],AL
|
||
PUSH CX ;Save actual byte count
|
||
CALL SCANEOF
|
||
JNZ NOTEND
|
||
MOV BYTE PTR [HAVEOF],1 ;Set flag if 1AH found in file
|
||
NOTEND:
|
||
XOR DX,DX
|
||
MOV BX,[PARAM1]
|
||
OR BX,BX
|
||
JNZ COUNTLN
|
||
MOV AX,DI
|
||
ADD AX,CX ;First byte after loaded text
|
||
CMP AX,[THREE4TH] ;See if we made 3/4 full
|
||
JBE COUNTLN
|
||
MOV DI,[THREE4TH]
|
||
MOV CX,AX
|
||
SUB CX,DI ;Length remaining over 3/4
|
||
MOV BX,1 ;Look for one more line
|
||
COUNTLN:
|
||
CALL SCANLN ;Look for BX lines
|
||
CMP [DI-1],AL ;Check for full line
|
||
JZ FULLN
|
||
STD
|
||
DEC DI
|
||
MOV CX,[LAST]
|
||
REPNE SCASB ;Scan backwards for last line
|
||
INC DI
|
||
INC DI
|
||
DEC DX
|
||
CLD
|
||
FULLN:
|
||
POP CX ;Actual amount read
|
||
MOV WORD PTR [DI],1AH ;Place EOF after last line
|
||
SUB CX,DI
|
||
XCHG DI,[ENDTXT]
|
||
ADD DI,CX ;Amount of file read but not used
|
||
SUB WORD PTR DS:[FCB+fcb_RR],DI ;Adjust RR field in case end of file
|
||
SBB WORD PTR DS:[FCB+fcb_RR+2],0 ; was not reached
|
||
CMP BX,DX
|
||
JNZ EOFCHK
|
||
MOV BYTE PTR [HAVEOF],0
|
||
RET
|
||
NOMORE:
|
||
MOV DX,OFFSET DG:EOF
|
||
MOV AH,STD_CON_STRING_OUTPUT
|
||
INT 21H
|
||
RET3: RET
|
||
EOFCHK:
|
||
TEST BYTE PTR [HAVEOF],-1
|
||
JNZ NOMORE
|
||
TEST BYTE PTR [ENDING],-1
|
||
JNZ RET3 ;Suppress memory error during End
|
||
JMP MEMERR
|
||
|
||
EWRITE:
|
||
MOV BX,[PARAM1]
|
||
OR BX,BX
|
||
JNZ WRT
|
||
MOV CX,[ONE4TH]
|
||
MOV DI,[ENDTXT]
|
||
SUB DI,CX ;Write everything in front of here
|
||
JBE RET3
|
||
CMP DI,OFFSET DG:START ;See if there's anything to write
|
||
JBE RET3
|
||
XOR DX,DX
|
||
MOV BX,1 ;Look for one more line
|
||
CALL SCANLN
|
||
JMP SHORT WRTADD
|
||
WRT:
|
||
INC BX
|
||
CALL FINDLIN
|
||
WRTADD:
|
||
CMP BYTE PTR [DELFLG],0
|
||
JNZ WRTADD1
|
||
PUSH DI
|
||
CALL DELBAK ;Want to delete the .BAK file
|
||
;as soon as the first write occurs
|
||
POP DI
|
||
WRTADD1:
|
||
MOV CX,DI
|
||
MOV DX,OFFSET DG:START
|
||
SUB CX,DX ;Amount to write
|
||
JZ RET3
|
||
MOV AH,SET_DMA
|
||
INT 21H
|
||
MOV DX,OFFSET DG:FCB2
|
||
MOV AH,FCB_RANDOM_WRITE_BLOCK
|
||
INT 21H
|
||
OR AL,AL
|
||
JNZ WRTERR
|
||
MOV SI,DI
|
||
MOV DI,OFFSET DG:START
|
||
MOV [POINTER],DI
|
||
MOV CX,[ENDTXT]
|
||
SUB CX,SI
|
||
INC CX ;Amount of text remaining
|
||
REP MOVSB
|
||
DEC DI ;Point to EOF
|
||
MOV [ENDTXT],DI
|
||
MOV [CURRENT],1
|
||
RET
|
||
|
||
WRTERR:
|
||
MOV AH,FCB_CLOSE
|
||
INT 21H
|
||
MOV DX,OFFSET DG:DSKFUL
|
||
xERROR:
|
||
MOV AH,STD_CON_STRING_OUTPUT
|
||
INT 21H
|
||
;-----------------------------------------------------------------------
|
||
call rest_dir ;restore to the proper directory
|
||
;-----------------------------------------------------------------------
|
||
INT 32
|
||
|
||
RET$5: RET
|
||
|
||
PAGE:
|
||
xor bx,bx ;get last line in the buffer
|
||
call findlin
|
||
mov [lastlin],dx
|
||
|
||
mov bx,[param1]
|
||
or bx,bx ;was it specified?
|
||
jnz frstok ;yes, use it
|
||
mov bx,[current]
|
||
cmp bx,1 ;if current line =1 start from there
|
||
je frstok
|
||
inc bx ;start from current+1 line
|
||
frstok:
|
||
cmp bx,[lastlin] ;check that we are in the buffer
|
||
ja ret$5 ;if not just quit
|
||
infile:
|
||
mov dx,[param2]
|
||
or dx,dx ;was param2 specified?
|
||
jnz scndok ;yes,....
|
||
mov dx,bx ;no, take the end line to be the
|
||
add dx,22 ; start line + 23
|
||
scndok:
|
||
inc dx
|
||
cmp dx,[lastlin] ;check that we are in the buffer
|
||
jbe infile2
|
||
mov dx,[lastlin] ;we are not, take the last line as end
|
||
infile2:
|
||
cmp dx,bx ;is param1 < param2 ?
|
||
jbe ret$5 ;yes, no backwards listing, quit
|
||
push dx ;save the end line
|
||
push bx ;save start line
|
||
mov bx,dx ;set the current line
|
||
dec bx
|
||
call findlin
|
||
mov [pointer],di
|
||
mov [current],dx
|
||
pop bx ;restore start line
|
||
call findlin ;get pointer to start line
|
||
mov si,di ;save pointer
|
||
pop di ;get end line
|
||
sub di,bx ;number of lines
|
||
jmp short display
|
||
|
||
|
||
LIST:
|
||
MOV BX,[PARAM1]
|
||
OR BX,BX
|
||
JNZ CHKP2
|
||
MOV BX,[CURRENT]
|
||
SUB BX,11
|
||
JA CHKP2
|
||
MOV BX,1
|
||
CHKP2:
|
||
CALL FINDLIN
|
||
JNZ RET7
|
||
MOV SI,DI
|
||
MOV DI,[PARAM2]
|
||
INC DI
|
||
SUB DI,BX
|
||
JA DISPLAY
|
||
MOV DI,23
|
||
JMP SHORT DISPLAY
|
||
|
||
|
||
DISPONE:
|
||
MOV DI,1
|
||
|
||
DISPLAY:
|
||
|
||
; Inputs:
|
||
; BX = Line number
|
||
; SI = Pointer to text buffer
|
||
; DI = No. of lines
|
||
; Function:
|
||
; Ouputs specified no. of line to terminal, each
|
||
; with leading line number.
|
||
; Outputs:
|
||
; BX = Last line output.
|
||
; All registers destroyed.
|
||
|
||
MOV CX,[ENDTXT]
|
||
SUB CX,SI
|
||
JZ RET7
|
||
MOV BP,[CURRENT]
|
||
DISPLN:
|
||
PUSH CX
|
||
CALL SHOWNUM
|
||
POP CX
|
||
OUTLN:
|
||
LODSB
|
||
CMP AL," "
|
||
JAE SEND
|
||
CMP AL,10
|
||
JZ SEND
|
||
CMP AL,13
|
||
JZ SEND
|
||
CMP AL,9
|
||
JZ SEND
|
||
PUSH AX
|
||
MOV AL,"^"
|
||
CALL OUT
|
||
POP AX
|
||
OR AL,40H
|
||
SEND:
|
||
CALL OUT
|
||
CMP AL,10
|
||
LOOPNZ OUTLN
|
||
JCXZ RET7
|
||
INC BX
|
||
DEC DI
|
||
JNZ DISPLN
|
||
DEC BX
|
||
RET7: RET
|
||
|
||
LOADBUF:
|
||
MOV DI,2 + OFFSET DG:EDITBUF
|
||
MOV CX,255
|
||
MOV DX,-1
|
||
LOADLP:
|
||
LODSB
|
||
STOSB
|
||
INC DX
|
||
CMP AL,13
|
||
LOOPNZ LOADLP
|
||
MOV [EDITBUF+1],DL
|
||
JZ RET7
|
||
TRUNCLP:
|
||
LODSB
|
||
INC DX
|
||
CMP AL,13
|
||
JNZ TRUNCLP
|
||
DEC DI
|
||
STOSB
|
||
RET
|
||
|
||
NOTFNDJ:JMP NOTFND
|
||
|
||
replac_from_curr:
|
||
mov byte ptr [srchmod],1 ;search from curr+1 line
|
||
jmp short sj6
|
||
|
||
REPLAC:
|
||
mov byte ptr [srchmod],0 ;search from beg of buffer
|
||
sj6:
|
||
MOV BYTE PTR [SRCHFLG],0
|
||
CALL FNDFIRST
|
||
JNZ NOTFNDJ
|
||
REPLP:
|
||
MOV SI,[NUMPOS]
|
||
CALL LOADBUF ;Count length of line
|
||
SUB DX,[OLDLEN]
|
||
MOV CX,[NEWLEN]
|
||
ADD DX,CX ;Length of new line
|
||
CMP DX,254
|
||
JA TOOLONG
|
||
MOV BX,[LSTNUM]
|
||
PUSH DX
|
||
CALL SHOWNUM
|
||
POP DX
|
||
MOV CX,[LSTFND]
|
||
MOV SI,[NUMPOS]
|
||
SUB CX,SI ;Get no. of char on line before change
|
||
DEC CX
|
||
CALL OUTCNT ;Output first part of line
|
||
PUSH SI
|
||
MOV SI,1+ OFFSET DG:TXT2
|
||
MOV CX,[NEWLEN]
|
||
CALL OUTCNT ;Output change
|
||
POP SI
|
||
ADD SI,[OLDLEN] ;Skip over old stuff in line
|
||
MOV CX,DX ;DX=no. of char left in line
|
||
ADD CX,2 ;Include CR/LF
|
||
CALL OUTCNT ;Output last part of line
|
||
CALL QUERY ;Check if change OK
|
||
JNZ REPNXT
|
||
CALL PUTCURS
|
||
MOV DI,[LSTFND]
|
||
DEC DI
|
||
MOV SI,1+ OFFSET DG:TXT2
|
||
MOV DX,[OLDLEN]
|
||
MOV CX,[NEWLEN]
|
||
DEC CX
|
||
ADD [LSTFND],CX ;Bump pointer beyond new text
|
||
INC CX
|
||
DEC DX
|
||
SUB [SRCHCNT],DX ;Old text will not be searched
|
||
JAE SOMELEFT
|
||
MOV [SRCHCNT],0
|
||
SOMELEFT:
|
||
INC DX
|
||
CALL REPLACE
|
||
REPNXT:
|
||
CALL FNDNEXT
|
||
JNZ RET8
|
||
JMP REPLP
|
||
|
||
OUTCNT:
|
||
JCXZ RET8
|
||
OUTLP:
|
||
LODSB
|
||
CALL OUT
|
||
DEC DX
|
||
LOOP OUTLP
|
||
RET8: RET
|
||
|
||
TOOLONG:
|
||
MOV DX,OFFSET DG:TOOLNG
|
||
JMP SHORT PERR
|
||
|
||
search_from_curr:
|
||
mov byte ptr [srchmod],1 ;search from curr+1 line
|
||
jmp short sj7
|
||
|
||
SEARCH:
|
||
mov byte ptr [srchmod],0 ;search from beg of buffer
|
||
sj7:
|
||
MOV BYTE PTR [SRCHFLG],1
|
||
CALL FNDFIRST
|
||
JNZ NOTFND
|
||
SRCH:
|
||
MOV BX,[LSTNUM]
|
||
MOV SI,[NUMPOS]
|
||
CALL DISPONE
|
||
MOV DI,[LSTFND]
|
||
MOV CX,[SRCHCNT]
|
||
MOV AL,10
|
||
REPNE SCASB
|
||
JNZ NOTFND
|
||
MOV [LSTFND],DI
|
||
MOV [NUMPOS],DI
|
||
MOV [SRCHCNT],CX
|
||
INC [LSTNUM]
|
||
CALL QUERY
|
||
JZ PUTCURS
|
||
CALL FNDNEXT
|
||
JZ SRCH
|
||
NOTFND:
|
||
MOV DX,OFFSET DG:NOSUCH
|
||
PERR:
|
||
MOV AH,STD_CON_STRING_OUTPUT
|
||
INT 21H
|
||
RET
|
||
|
||
PUTCURS:
|
||
MOV BX,[LSTNUM]
|
||
DEC BX ;Current <= Last matched line
|
||
CALL FINDLIN
|
||
MOV [CURRENT],DX
|
||
MOV [POINTER],DI
|
||
RET9: RET
|
||
|
||
DELETE:
|
||
MOV BX,[PARAM1]
|
||
OR BX,BX
|
||
JNZ DELFIN1
|
||
MOV BX,[CURRENT]
|
||
CALL CHKRANGE
|
||
DELFIN1:
|
||
CALL FINDLIN
|
||
JNZ RET9
|
||
PUSH BX
|
||
PUSH DI
|
||
MOV BX,[PARAM2]
|
||
OR BX,BX
|
||
JNZ DELFIN2
|
||
MOV BX,DX
|
||
DELFIN2:
|
||
INC BX
|
||
CALL FINDLIN
|
||
MOV DX,DI
|
||
POP DI
|
||
SUB DX,DI
|
||
JBE COMERRJ
|
||
POP [CURRENT]
|
||
MOV [POINTER],DI
|
||
XOR CX,CX
|
||
JMP SHORT REPLACE
|
||
|
||
COMERRJ:JMP COMERR
|
||
|
||
|
||
NOCOM:
|
||
DEC [COMLINE]
|
||
MOV BX,[PARAM1]
|
||
OR BX,BX
|
||
JNZ HAVLIN
|
||
MOV BX,[CURRENT]
|
||
INC BX ;Default is current line plus one
|
||
CALL CHKRANGE
|
||
HAVLIN:
|
||
CALL FINDLIN
|
||
MOV SI,DI
|
||
MOV [CURRENT],DX
|
||
MOV [POINTER],SI
|
||
jz sj12
|
||
ret
|
||
sj12:
|
||
CMP SI,[ENDTXT]
|
||
JZ RET12
|
||
CALL LOADBUF
|
||
MOV [OLDLEN],DX
|
||
MOV SI,[POINTER]
|
||
CALL DISPONE
|
||
CALL SHOWNUM
|
||
MOV AH,STD_CON_STRING_INPUT ;Get input buffer
|
||
MOV DX,OFFSET DG:EDITBUF
|
||
INT 21H
|
||
MOV AL,10
|
||
CALL OUT
|
||
MOV CL,[EDITBUF+1]
|
||
MOV CH,0
|
||
JCXZ RET12
|
||
MOV DX,[OLDLEN]
|
||
MOV SI,2 + OFFSET DG:EDITBUF
|
||
;-----------------------------------------------------------------------
|
||
call unquote ;scan for quote chars if any
|
||
;-----------------------------------------------------------------------
|
||
MOV DI,[POINTER]
|
||
|
||
REPLACE:
|
||
|
||
; Inputs:
|
||
; CX = Length of new text
|
||
; DX = Length of original text
|
||
; SI = Pointer to new text
|
||
; DI = Pointer to old text in buffer
|
||
; Function:
|
||
; New text replaces old text in buffer and buffer
|
||
; size is adjusted. CX or DX may be zero.
|
||
; CX, SI, DI all destroyed. No other registers affected.
|
||
|
||
CMP CX,DX
|
||
JZ COPYIN
|
||
PUSH SI
|
||
PUSH DI
|
||
PUSH CX
|
||
MOV SI,DI
|
||
ADD SI,DX
|
||
ADD DI,CX
|
||
MOV AX,[ENDTXT]
|
||
SUB AX,DX
|
||
ADD AX,CX
|
||
CMP AX,[LAST]
|
||
JAE MEMERR
|
||
XCHG AX,[ENDTXT]
|
||
MOV CX,AX
|
||
SUB CX,SI
|
||
CMP SI,DI
|
||
JA DOMOV
|
||
ADD SI,CX
|
||
ADD DI,CX
|
||
STD
|
||
DOMOV:
|
||
INC CX
|
||
|
||
REP MOVSB
|
||
CLD
|
||
POP CX
|
||
POP DI
|
||
POP SI
|
||
COPYIN:
|
||
REP MOVSB
|
||
RET12: RET
|
||
|
||
MEMERR:
|
||
MOV DX,OFFSET DG:MEMFUL
|
||
MOV AH,STD_CON_STRING_OUTPUT
|
||
INT 21H
|
||
JMP COMMAND
|
||
|
||
MOVERR:
|
||
MOV DX,OFFSET DG:BADCOM
|
||
ERRORJ:
|
||
JMP COMERR
|
||
|
||
MOVE:
|
||
MOV BYTE PTR [MOVFLG],1
|
||
JMP SHORT BLKMOVE
|
||
COPY:
|
||
MOV BYTE PTR [MOVFLG],0
|
||
|
||
BLKMOVE:
|
||
MOV BX,[PARAM3] ;Third parameter must be specified
|
||
OR BX,BX
|
||
MOV DX,OFFSET DG:DEST
|
||
JZ ERRORJ
|
||
MOV BX,[PARAM1] ;Get the first parameter
|
||
OR BX,BX ;Not specified?
|
||
JNZ NXTARG
|
||
MOV BX,[CURRENT] ;Defaults to the current line
|
||
CALL CHKRANGE
|
||
MOV [PARAM1],BX ;Save it since current line may change
|
||
NXTARG:
|
||
CALL FINDLIN ;Get a pointer to the line
|
||
MOV [PTR_1],DI ;Save it
|
||
MOV BX,[PARAM2] ;Get the second parameter
|
||
OR BX,BX ;Not specified?
|
||
JNZ HAVARGS
|
||
MOV BX,[CURRENT] ;Defaults to the current line
|
||
MOV [PARAM2],BX ;Save it since current line may change
|
||
HAVARGS:
|
||
;Parameters must not overlap
|
||
MOV DX,[PARAM3]
|
||
CMP DX,[PARAM1]
|
||
JBE NOERROR
|
||
CMP DX,[PARAM2]
|
||
JBE MOVERR
|
||
NOERROR:
|
||
INC BX ;Get pointer to line Param2+1
|
||
CALL FINDLIN
|
||
MOV SI,DI
|
||
MOV [PTR_2],SI ;Save it
|
||
MOV CX,DI
|
||
MOV DI,[PTR_1] ;Restore pointer to line Param1
|
||
SUB CX,DI ;Calculate number of bytes to copy
|
||
MOV [COPYSIZ],CX ;Save in COPYSIZ
|
||
PUSH CX ;And on the stack
|
||
MOV AX,[PARAM4] ;Is count specified?
|
||
OR AX,AX
|
||
JZ MEM_CHECK
|
||
MUL [COPYSIZ]
|
||
OR DX,DX
|
||
JZ COPYSIZ_OK
|
||
JMP MEMERR
|
||
COPYSIZ_OK:
|
||
MOV CX,AX
|
||
MOV [COPYSIZ],CX
|
||
MEM_CHECK:
|
||
MOV AX,[ENDTXT]
|
||
MOV DI,[LAST]
|
||
SUB DI,AX
|
||
CMP DI,CX
|
||
JAE HAV_ROOM
|
||
JMP MEMERR
|
||
HAV_ROOM:
|
||
MOV BX,[PARAM3]
|
||
PUSH BX
|
||
CALL FINDLIN
|
||
MOV [PTR_3],DI
|
||
MOV CX,[ENDTXT]
|
||
SUB CX,DI
|
||
INC CX
|
||
MOV SI,[ENDTXT]
|
||
MOV DI,SI
|
||
ADD DI,[COPYSIZ]
|
||
MOV [ENDTXT],DI
|
||
STD
|
||
REP MOVSB
|
||
CLD
|
||
POP BX
|
||
CMP BX,[PARAM1]
|
||
JB GET_PTR_2
|
||
MOV SI,[PTR_1]
|
||
JMP SHORT COPY_TEXT
|
||
GET_PTR_2:
|
||
MOV SI,[PTR_2]
|
||
COPY_TEXT:
|
||
MOV BX,[PARAM4]
|
||
MOV DI,[PTR_3]
|
||
POP CX
|
||
MOV [COPYSIZ],CX
|
||
COPY_TEXT_1:
|
||
REP MOVSB
|
||
DEC BX
|
||
CMP BX,0
|
||
JLE MOV_CHK
|
||
MOV [PARAM4],BX
|
||
SUB SI,[COPYSIZ]
|
||
MOV CX,[COPYSIZ]
|
||
JMP SHORT COPY_TEXT_1
|
||
MOV_CHK:
|
||
CMP BYTE PTR[MOVFLG],0
|
||
JZ COPY_DONE
|
||
MOV DI,[PTR_1]
|
||
MOV SI,[PTR_2]
|
||
MOV BX,[PARAM3]
|
||
CMP BX,[PARAM1]
|
||
JAE DEL_TEXT
|
||
ADD DI,[COPYSIZ]
|
||
ADD SI,[COPYSIZ]
|
||
DEL_TEXT:
|
||
MOV CX,[ENDTXT]
|
||
SUB CX,SI
|
||
REP MOVSB
|
||
MOV [ENDTXT],DI
|
||
MOV CX,[PARAM2]
|
||
SUB CX,[PARAM1]
|
||
MOV BX,[PARAM3]
|
||
SUB BX,CX
|
||
JNC MOVE_DONE
|
||
COPY_DONE:
|
||
MOV BX,[PARAM3]
|
||
MOVE_DONE:
|
||
CALL FINDLIN
|
||
MOV [POINTER],DI
|
||
MOV [CURRENT],BX
|
||
RET
|
||
|
||
|
||
MOVEFILE:
|
||
MOV CX,[ENDTXT] ;Get End-of-text marker
|
||
MOV SI,CX
|
||
SUB CX,DI ;Calculate number of bytes to copy
|
||
INC CX
|
||
MOV DI,DX
|
||
STD
|
||
REP MOVSB ;Copy CX bytes
|
||
XCHG SI,DI
|
||
CLD
|
||
INC DI
|
||
MOV BP,SI
|
||
SETPTS:
|
||
MOV [POINTER],DI ;Current line is first free loc
|
||
MOV [CURRENT],BX ; in the file
|
||
MOV [ENDTXT],BP ;End-of-text is last free loc before
|
||
RET
|
||
|
||
NAMERR:
|
||
JMP COMERR1
|
||
|
||
|
||
MERGE:
|
||
MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 1
|
||
MOV DI,OFFSET DG:FCB3
|
||
INT 21H
|
||
OR AL,AL
|
||
MOV DX,OFFSET DG:BADDRV
|
||
JNZ NAMERR
|
||
MOV [COMLINE],SI
|
||
MOV DX,OFFSET DG:FCB3
|
||
MOV AH,FCB_OPEN
|
||
INT 21H
|
||
OR AL,AL
|
||
MOV DX,OFFSET DG:FILENM
|
||
JNZ NAMERR
|
||
MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 23H
|
||
MOV DX,OFFSET DG:ABORTMERGE
|
||
INT 21H
|
||
MOV BX,[PARAM1]
|
||
OR BX,BX
|
||
JNZ MRG
|
||
MOV BX,[CURRENT]
|
||
CALL CHKRANGE
|
||
MRG:
|
||
CALL FINDLIN
|
||
MOV BX,DX
|
||
MOV DX,[LAST]
|
||
CALL MOVEFILE
|
||
;Set DMA address for reading in new file
|
||
MOV DX,[POINTER]
|
||
MOV AH,SET_DMA
|
||
INT 21H
|
||
XOR AX,AX
|
||
MOV WORD PTR DS:[FCB3+fcb_RR],AX
|
||
MOV WORD PTR DS:[FCB3+fcb_RR+2],AX
|
||
INC AX
|
||
MOV WORD PTR DS:[FCB3+fcb_RECSIZ],AX
|
||
MOV DX,OFFSET DG:FCB3
|
||
MOV CX,[ENDTXT]
|
||
SUB CX,[POINTER]
|
||
MOV AH,FCB_RANDOM_READ_BLOCK
|
||
INT 21H
|
||
CMP AL,1
|
||
JZ FILEMRG
|
||
MOV DX,OFFSET DG:MRGERR
|
||
MOV AH,STD_CON_STRING_OUTPUT
|
||
INT 21H
|
||
MOV CX,[POINTER]
|
||
JMP SHORT RESTORE
|
||
FILEMRG:
|
||
ADD CX,[POINTER]
|
||
MOV SI,CX
|
||
DEC SI
|
||
LODSB
|
||
CMP AL,1AH
|
||
JNZ RESTORE
|
||
DEC CX
|
||
RESTORE:
|
||
MOV DI,CX
|
||
MOV SI,[ENDTXT]
|
||
INC SI
|
||
MOV CX,[LAST]
|
||
SUB CX,SI
|
||
REP MOVSB
|
||
MOV [ENDTXT],DI
|
||
MOV BYTE PTR [DI],1AH
|
||
MOV DX,OFFSET DG:FCB3
|
||
MOV AH,FCB_CLOSE
|
||
INT 21H
|
||
MOV DX,OFFSET DG:START
|
||
MOV AH,SET_DMA
|
||
INT 21H
|
||
RET
|
||
|
||
|
||
INSERT:
|
||
MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 23H ;Set vector 23H
|
||
MOV DX,OFFSET DG:ABORTINS
|
||
INT 21H
|
||
MOV BX,[PARAM1]
|
||
OR BX,BX
|
||
JNZ INS
|
||
MOV BX,[CURRENT]
|
||
CALL CHKRANGE
|
||
INS:
|
||
CALL FINDLIN
|
||
MOV BX,DX
|
||
MOV DX,[LAST]
|
||
CALL MOVEFILE
|
||
INLP:
|
||
CALL SETPTS ;Update the pointers into file
|
||
CALL SHOWNUM
|
||
MOV DX,OFFSET DG:EDITBUF
|
||
MOV AH,STD_CON_STRING_INPUT
|
||
INT 21H
|
||
CALL LF
|
||
MOV SI,2 + OFFSET DG:EDITBUF
|
||
CMP BYTE PTR [SI],1AH
|
||
JZ ENDINS
|
||
;-----------------------------------------------------------------------
|
||
call unquote ;scan for quote chars if any
|
||
;-----------------------------------------------------------------------
|
||
MOV CL,[SI-1]
|
||
MOV CH,0
|
||
MOV DX,DI
|
||
INC CX
|
||
ADD DX,CX
|
||
JC MEMERRJ1
|
||
JZ MEMERRJ1
|
||
CMP DX,BP
|
||
JB MEMOK
|
||
MEMERRJ1:
|
||
CALL END_INS
|
||
JMP MEMERR
|
||
MEMOK:
|
||
REP MOVSB
|
||
MOV AL,10
|
||
STOSB
|
||
INC BX
|
||
JMP SHORT INLP
|
||
|
||
ABORTMERGE:
|
||
MOV DX,OFFSET DG:START
|
||
MOV AH,SET_DMA
|
||
INT 21H
|
||
|
||
ABORTINS:
|
||
MOV AX,CS ;Restore segment registers
|
||
MOV DS,AX
|
||
MOV ES,AX
|
||
MOV SS,AX
|
||
MOV SP,OFFSET DG:STACK
|
||
STI
|
||
CALL CRLF
|
||
CALL ENDINS
|
||
JMP COMOVER
|
||
|
||
ENDINS:
|
||
CALL END_INS
|
||
RET
|
||
|
||
END_INS:
|
||
MOV BP,[ENDTXT]
|
||
MOV DI,[POINTER]
|
||
MOV SI,BP
|
||
INC SI
|
||
MOV CX,[LAST]
|
||
SUB CX,BP
|
||
REP MOVSB
|
||
DEC DI
|
||
MOV [ENDTXT],DI
|
||
MOV AX,(SET_INTERRUPT_VECTOR SHL 8) OR 23H
|
||
MOV DX,OFFSET DG:ABORTCOM
|
||
INT 21H
|
||
RET
|
||
|
||
FILLBUF:
|
||
MOV [PARAM1],-1 ;Read in max. no of lines
|
||
CALL APPEND
|
||
ENDED:
|
||
;Write text out to .$$$ file
|
||
MOV BYTE PTR [ENDING],1 ;Suppress memory errors
|
||
MOV BX,-1 ;Write max. no of lines
|
||
CALL WRT
|
||
TEST BYTE PTR [HAVEOF],-1
|
||
JZ FILLBUF
|
||
MOV DX,[ENDTXT]
|
||
MOV AH,SET_DMA
|
||
INT 21H
|
||
MOV CX,1
|
||
MOV DX,OFFSET DG:FCB2
|
||
MOV AH,FCB_RANDOM_WRITE_BLOCK
|
||
INT 21H ;Write end-of-file byte
|
||
;Close .$$$ file
|
||
MOV AH,FCB_CLOSE
|
||
INT 21H
|
||
MOV SI,FCB
|
||
LEA DI,[SI+fcb_FILSIZ]
|
||
MOV DX,SI
|
||
MOV CX,9
|
||
REP MOVSB
|
||
MOV SI,OFFSET DG:BAK
|
||
MOVSW
|
||
MOVSB
|
||
;Rename original file .BAK
|
||
MOV AH,FCB_RENAME
|
||
INT 21H
|
||
MOV SI,FCB
|
||
MOV DI,OFFSET DG:FCB2 + fcb_FILSIZ
|
||
MOV CX,6
|
||
REP MOVSW
|
||
;Rename .$$$ file to original name
|
||
MOV DX,OFFSET DG:FCB2
|
||
INT 21H
|
||
call rest_dir ;restore directory if needed
|
||
INT 20H
|
||
|
||
ABORTCOM:
|
||
MOV AX,CS
|
||
MOV DS,AX
|
||
MOV ES,AX
|
||
MOV SS,AX
|
||
MOV SP,OFFSET DG:STACK
|
||
STI
|
||
CALL CRLF
|
||
JMP COMMAND
|
||
|
||
DELBAK:
|
||
MOV BYTE PTR [DELFLG],1
|
||
MOV DI,9+OFFSET DG:FCB2
|
||
MOV SI,OFFSET DG:BAK
|
||
MOVSW
|
||
MOVSB
|
||
;Delete old backup file (.BAK)
|
||
MOV AH,FCB_DELETE
|
||
MOV DX,OFFSET DG:FCB2
|
||
INT 21H
|
||
MOV DI,9+OFFSET DG:FCB2
|
||
MOV AL,"$"
|
||
STOSB
|
||
STOSB
|
||
STOSB
|
||
RET
|
||
|
||
CODE ENDS
|
||
END EDLIN
|
||
|