4 ;======================= START OF SPECIFICATIONS =========================
6 ; MODULE NAME: EDLIN.SAL
8 ; DESCRIPTIVE NAME: LINE TEXT EDITOR
10 ; FUNCTION: EDLIN IS A SIMPLE, LINE ORIENTED TEXT EDITOR. IT PROVIDES
11 ; USERS OF DOS THE ABILITY TO CREATE AND EDIT TEXT FILES.
15 ; INPUT: DOS COMMAND LINE
23 ; INTERNAL REFERENCES:
25 ; EXTERNAL REFERENCES:
27 ; ROUTINE: EDLCMD1 - CONTAINS ROUTINES CALLED BY EDLIN
28 ; EDLCMD1 - CONTAINS ROUTINES CALLED BY EDLIN
29 ; EDLMES - CONTAINS ROUTINES CALLED BY EDLIN
31 ; NOTES: THIS MODULE IS TO BE PREPPED BY SALUT WITH THE "PR" OPTIONS.
32 ; LINK EDLIN+EDLCMD1+EDLCMD2+EDLMES+EDLPARSE
36 ; AN000 VERSION 4.00 - REVISIONS MADE RELATE TO THE FOLLOWING:
38 ; - IMPLEMENT SYSPARSE
39 ; - IMPLEMENT MESSAGE RETRIEVER
40 ; - IMPLEMENT DBCS ENABLING
41 ; - ENHANCED VIDEO SUPPORT
45 ; COPYRIGHT: "MS DOS EDLIN UTILITY"
46 ; "VERSION 4.00 (C) COPYRIGHT 1988 Microsoft"
47 ; "LICENSED MATERIAL - PROPERTY OF Microsoft"
50 ; MICROSOFT REVISION HISTORY:
54 ; V2.00 9/13/82 M.A.U ;
56 ; 2/23/82 Rev. 13 N. P ;
57 ; Changed to 2.0 system calls. ;
58 ; Added an error message for READ-ONLY files ;
60 ; 11/7/83 Rev. 14 N. P ;
61 ; Changed to .EXE format and added Printf ;
63 ; V2.50 11/15/83 Rev. 1 M.A. U ;
64 ; Official dos 2.50 version. Some random bug ;
65 ; fixes and message changes. ;
67 ; 11/30/83 Rev. 2 MZ ;
68 ; Close input file before rename. ;
69 ; Jmp to replace after line edit ;
71 ; 02/01/84 Rev. 3 M.A. U ;
72 ; Now it is called 3.00 dos. Repaired problem ;
73 ; with using printf and having %'s as data. ;
75 ; 02/15/84 MZ make out of space a fatal error with output;
77 ; 03/28/84 MZ fixes bogus (totally) code in MOVE/COPY ;
79 ; 04/02/84 MZ fixes DELETE and changes MOVE/COPY/EDIT ;
81 ; V3.20 08/29/86 Rev. 1 S.M. G ;
83 ; 08/29/86 M001 MSKK TAR 593, TAB MOVEMENT ;
85 ; 08/29/86 M002 MSKK TAR 157, BLKMOVE 1,1,1m, 1,3,1m ;
87 ; 08/29/86 M003 MSKK TAR 476, EDLCMD2,MAKECAPS,kana char;
89 ; 08/29/86 M004 MSKK TAR 191, Append load size ;
91 ; 08/29/86 M005 IBMJ TAR Transfer Load command ;
94 ;======================= END OF SPECIFICATIONS =========================== ;
98 SUBTTL Contants
and Data areas
100 extrn parser_command
:near ;an000;SYSPARSE
105 CONST
SEGMENT PUBLIC WORD
111 DATA SEGMENT PUBLIC WORD
114 DG GROUP
CODE,CONST
,cstack
,DATA
116 CONST
SEGMENT PUBLIC WORD
118 public bak
,$$$
file,delflg
,loadmod
,txt1
,txt2
120 EXTRN BADDRV_ptr
:word,NDNAME_ptr
:word,bad_vers_err
:byte,opt_err_ptr
:word
121 EXTRN NOBAK_ptr
:word,BADCOM_ptr
:word,NEWFIL_ptr
:word,DEST_ptr
:word,MRGERR_ptr
:word
122 EXTRN NODIR_ptr
:word,FILENM_ptr
:word,ro_err_ptr
:word,bcreat_ptr
:word
123 EXTRN TOO_MANY_ptr
:word,lf_ptr
:word,prompt_ptr
:word
124 EXTRN MemFul_Ptr
:word
130 fourth db 0 ;fourth parameter flag
132 loadmod db 0 ;Load mode flag, 0 = ^Z marks the
133 ; end of a file, 1 = viceversa.
136 TXT1
DB 0,80H
DUP (?
)
137 TXT2
DB 0,80H
DUP (?
)
148 DATA SEGMENT PUBLIC WORD
150 extrn arg_buf_ptr
:word ;an000;
151 extrn line_num_buf_ptr
:word ;an000;
153 public path_name
,ext_ptr
,start
,line_num
,line_flag
154 public arg_buf
,wrt_handle
,temp_path
155 public current
,pointer
,qflg
,editbuf
,amnt_req
,fname_len
,delflg
,lastlin
156 public olddat
,oldlen
,newlen
,srchflg
,srchmod
157 public comline
,lstfnd
,numpos
,lstnum
,last
,srchcnt
158 public rd_handle
,haveof
,ending
,three4th
,one4th
160 public lc_adj
;an000;page length adj. factor
161 public lc_flag
;an000;display cont. flag
162 public pg_count
;an000;lines left on screen
163 public Disp_Len
;an000;display length
164 public Disp_Width
;an000;display width
165 public continue
;an000;boolean T/F
166 public temp_path
;an000;pointer to filespec buf
168 Video_Buffer
label word ;an000;buffer for video attr
175 dw ?
;an000;dms;# of colors
176 dw ?
;an000;dms;# of pixels in width
177 dw ?
;an000;dms;# of pixels in len.
178 dw ?
;an000;dms;# of chars in width
179 dw ?
;an000;dms;# of chars in length
182 video_org db ?
;an000;original video mode on
184 lc_adj db ?
;an000;page length adj. factor
185 lc_flag db ?
;an000;display cont. flag
186 pg_count db ?
;an000;lines left on screen
187 Disp_Len db ?
;an000;display length
188 Disp_Width db ?
;an000;display width
189 continue db ?
;an000;boolean T/F
192 ;-----------------------------------------------------------------------;
193 ; This is a table that is sequentially filled via GetNum. Any additions to it
194 ; must be placed in the correct position. Currently Param4 is known to be a
195 ; count and thus is treated specially.
197 public param1
,param2
,Param3
,param4
,ParamCt
202 ParamCt
DW ?
; count of passed parameters
203 if kanji
; Used in TESTKANJ:
204 LBTbl dd ?
; long pointer to lead byte table
205 endif
; in the dos (from syscall 63H)
207 ;-----------------------------------------------------------------------;
209 PUBLIC PTR_1
, PTR_2
, PTR_3
, OLDLEN
, NEWLEN
, LSTFND
, LSTNUM
, NUMPOS
, SRCHCNT
210 PUBLIC CURRENT
, POINTER
, ONE4TH
, THREE4TH
, LAST
, ENDTXT
, COPYSIZ
211 PUBLIC COMLINE
, LASTLIN
, COMBUF
, EDITBUF
, EOL
, QFLG
, ENDING
, SRCHFLG
212 PUBLIC PATH_NAME
, FNAME_LEN
, RD_HANDLE
, TEMP_PATH
, WRT_HANDLE
, EXT_PTR
213 PUBLIC MRG_PATH_NAME
, MRG_HANDLE
, amnt_req
, olddat
, srchmod
, MOVFLG
, org_ds
219 ; These comprise the known state of the internal buffer. All editing
220 ; functions must preserve these values.
222 CURRENT
DW ?
; the 1-based index of the current line
223 POINTER
DW ?
; pointer to the current line
224 ENDTXT
DW ?
; pointer to end of buffer. (at ^Z)
225 LAST
DW ?
; offset of last byte of memory
227 ; The label Start is the beginning of the in-core buffer.
231 ; Internal temporary pointers
237 QFLG
DB ?
; TRUE => query for replacement
246 COPYSIZ
DW ?
; total length to copy
247 COPYLEN
DW ?
; single copy length
250 COMBUF
DB 82H
DUP (?
)
251 EDITBUF
DB 258 DUP (?
)
255 PATH_NAME
DB 128 DUP(0)
258 TEMP_PATH
DB 128 DUP(?
)
261 MRG_PATH_NAME
DB 128 DUP(?
)
263 amnt_req dw ?
; amount of bytes requested to read
264 olddat db ?
; Used in replace and search, replace
265 ; by old data flag (1=yes)
266 srchmod db ?
; Search mode: 1=from current+1 to
267 ; end of buffer, 0=from beg. of
268 ; buffer to the end (old way).
270 org_ds dw ?
;Orginal ds points to header block
272 arg_buf db 258 dup (?
)
274 EA_Flag db False
;an000; dms;set to false
276 EA_Buffer_Size dw ?
;an000; dms;EA buffer's size
278 EA_Parm_List
label word ;an000; dms;EA parms
279 dd dg
:Start
;an000; dms;ptr to EA's
280 dw 0001h ;an000; dms;additional parms
282 dw 0002h ;an000; dms;iomode
288 EVEN
;align on word boundaries
290 ; Byte before start of data buffer must be < 40H !!!!!!
292 dw 0 ;we scan backwards looking for
293 ;a character which can't be part
294 ;of a two-byte seqence. This
295 ;double byte sequence will cause the back
304 ASSUME
CS:DG
,DS:NOTHING
,ES:NOTHING
,SS:CStack
308 extrn pre_load_message
:near ;an000;message loader
309 extrn disp_fatal
:near ;an000;fatal message
310 extrn printf
:near ;an000;new PRINTF routine
312 extrn findlin
:near,shownum
:near,loadbuf
:near,crlf
:near,lf
:near
313 extrn abortcom
:near,delbak
:near,unquote
:near,kill_bl
:near
314 extrn make_caps
:near,dispone
:near,display:near,query
:near
315 extrn quit
:near,make_cntrl
:near,scanln
:near,scaneof
:near
316 extrn fndfirst
:near,fndnext
:near,replace
:near,memerr
:near
317 extrn xerror
:near,bad_read
:near,append
:near
318 extrn nocom
:near,pager
:near,list
:near,search_from_curr
:near
319 extrn replac_from_curr
:near,ewrite
:near,wrt
:near,delete
:near
322 extrn filespec
:byte ;an000;parser's filespec
323 extrn parse_switch_b
:byte ;an000;result of switch scan
325 public std_printf
,command
,chkrange
,comerr
335 std_printf proc
near ;ac000;convert to proc
339 pop dx ;an000;balance the push
342 std_printf endp
;ac000;end proc
345 MOV DX,OFFSET DG
:NDNAME_ptr
350 push ax ;ac000;save for drive compare
352 push cs ;an000;exchange cs/es
355 push cs ;an000;exchange cs/ds
357 assume
ds:dg
,es:dg
;an000;establish addressibility
361 call EDLIN_DISP_GET
;an000;get current video
365 ;=========================================================================
366 ; invoke PRE_LOAD_MESSAGE here. If the messages were not loaded we will
367 ; exit with an appropriate error message.
370 ;=========================================================================
372 call PRE_LOAD_MESSAGE
;an000;invoke SYSLOADMSG
373 ; $if c ;an000;if the load was unsuccessful
375 mov ah,exit
;an000;exit EDLIN. PRE_LOAD_MESSAGE
376 ; has said why we are exiting
385 ;----- Check for valid drive specifier --------------------------------;
390 MOV DX,OFFSET DG
:BADDRV_ptr
393 MOV AX,(CHAR_OPER
SHL 8) ;GET SWITCH CHARACTER
396 JNZ CMD_LINE
;IF NOT / , THEN NOT PC
397 MOV OPTCHAR
,"/" ;IN PC, OPTION CHAR = /
400 push ds ; SAVE! all regs destroyed on this
403 mov ax,(ECS_call
shl 8) or 00h ; get kanji lead tbl
407 mov word ptr [LBTbl
],si
408 mov word ptr [LBTbl
+2],ds
422 ;----- Process any options ------------------------------------------;
424 ;=========================================================================
425 ; The system parser, called through PARSER_COMMAND, parses external
426 ; command lines. In the case of EDLIN we are looking for two parameters
427 ; on the command line.
429 ; Parameter 1 - Filespec (REQUIRED)
430 ; Parameter 2 - \B switch (OPTIONAL)
432 ; PARSER_COMMAND - exit_normal : ffffh
433 ; exit_error : not = ffffh
434 ;=========================================================================
437 call PARSER_COMMAND
;an000;invoke sysparse
439 cmp ax,nrm_parse_exit
;an000;was it a good parse
440 ; $if z ;an000;it was a good parse
442 call EDLIN_COMMAND
;an000;interface results
447 cmp ax,too_many
;an000;too many operands
448 ; $if z ;an000;we have too many
450 jmp badopt
;an000;say why and exit
454 cmp ax,op_missing
;an000;required parm missing
455 ; $if z ;an000;missing parm
457 jmp noname
;an000;say why and exit
461 cmp ax,sw_missing
;an000;is it an invalid switch
462 ; $if z ;an000;invalid switch
464 jmp badopt
;an000;say why and exit
471 ;=========================================================================
472 ;======================= begin .BAK check ================================
473 ; Check for .BAK extension on the filename
475 push ds ;an000;save reg.
476 push cs ;an000;set up addressibility
480 push ax ;an000;save reg.
481 mov ax,offset dg
:path_name
;an000;point to path_name
482 add ax,[fname_len
] ;an000;calculate end of path_name
483 mov si,ax ;an000;point to end of path_name
484 pop ax ;an000;restore reg.
486 MOV CX,4 ;compare 4 bytes
487 SUB SI,4 ;Point 4th to last char
488 MOV DI,OFFSET DG
:BAK
;Point to string ".BAK"
489 REPE CMPSB ;Compare the two strings
495 ;======================= end .BAK check ==================================
497 ;======================= begin NOTBAK ====================================
498 ; we have a file without a .BAK extension, try to open it
506 ;=========================================================================
507 ; implement EXTENDED OPEN
508 ;=========================================================================
510 push es ;an000;save reg.
511 mov bx,RW ;an000;open for read/write
512 mov cx,ATTR
;an000;file attributes
513 mov dx,RW_FLAG
;an000;action to take on open
514 mov di,0ffffh ;an000;nul parm list
516 call EXT_OPEN1
;an000;open for R/W;DMS:6/10/87
517 pop es ;an000;restore reg.
519 ;=========================================================================
522 JC CHK_OPEN_ERR
;an open error occurred
523 MOV RD_HANDLE
,AX ;Save the handle
525 call Calc_Memory_Avail
;an000; dms;enough memory?
527 mov bx,RD_Handle
;an000; dms;set up for call
528 call Query_Extend_Attrib
;an000; dms;memory required?
530 cmp dx,cx ;an000; dms;enough memory for EA's?
531 ; $if b ;an000; dms;no
533 call EA_Fail_Exit
;an000; dms;say why and exit
534 ; $endif ;an000; dms;
537 mov bx,RD_Handle
;an000; dms;set up for call
538 mov EA_Flag
,True
;an000; dms;
539 call Get_Extended_Attrib
;an000; dms;get attribs
541 Jmp HavFil
;work with the opened file
543 ;======================= end NOTBAK ======================================
546 MOV DX,OFFSET DG
:OPT_ERR_ptr
;Bad option specified
549 ;=========================================================================
551 ; The open of the file failed. We need to figure out why and report the
552 ; correct message. The circumstances we can handle are:
554 ; open returns pathnotfound => bad drive or file name
555 ; open returns toomanyopenfiles => too many open files
556 ; open returns access denied =>
557 ; chmod indicates read-only => cannot edit read only file
558 ; else => file creation error
559 ; open returns filenotfound =>
560 ; creat ok => close, delete, new file
561 ; creat fails => file creation error
566 cmp ax,error_path_not_found
568 cmp ax,error_too_many_open_files
570 cmp ax,error_access_denied
577 MOV DX,OFFSET DG
:PATH_NAME
580 test cx,attr_read_only
585 cmp ax,error_file_not_found
586 jnz FileCreationError
588 ; Try to create the file to see if it is OK.
594 ;=========================================================================
595 ; implement EXTENDED OPEN
596 ;=========================================================================
598 mov bx,RW ;an000;open for read/write
599 mov cx,ATTR
;an000;file attributes
600 mov dx,CREAT_FLAG
;an000;action to take on open
601 mov di,0ffffh ;an000;null parm list
602 call EXT_OPEN1
;an000;create file;DMS:6/10/87
604 ;=========================================================================
617 MOV DX,OFFSET DG
:PATH_NAME
621 jc FileCreationError
; This should NEVER be taken!!!
622 MOV HAVEOF
,0FFH ; Flag from a system 1.xx call
627 cmp ax,error_access_denied
630 MOV DX,OFFSET DG
:nodir_ptr
634 mov dx,offset dg
:BCreat_PTR
638 MOV DX,OFFSET DG
:RO_ERR_ptr
642 MOV DX,OFFSET DG
:BADDRV_PTR
646 MOV DX,OFFSET DG
:TOO_MANY_ptr
659 MOV DX,OFFSET DG
:NOBAK_ptr
668 MOV DX,OFFSET DG
:NEWFIL_ptr
; Print new file message
671 MOV SI,OFFSET DG
:PATH_NAME
674 MOV DI,OFFSET DG
:TEMP_PATH
683 MOV DI,DX ;Point to last char in filename
688 MOV SI,OFFSET DG
:$$$
FILE
692 ;Create .$$$ file to make sure directory has room
695 ;=========================================================================
696 ; implement EXTENDED OPEN
697 ;=========================================================================
699 mov bx,RW ;an000;open for read/write
700 mov cx,ATTR
;an000;file attributes
701 mov dx,Creat_Open_Flag
;an000;action to take on open
702 cmp EA_Flag
,True
;an000;EA_Buffer used?
705 mov di,offset dg
:EA_Parm_List
;an000; point to buffer
709 mov di,0ffffh ;an000;nul parm list
712 call EXT_OPEN2
;an000;create file;DMS:6/10/87
714 ;=========================================================================
719 ; We determine the size of the available memory. Use the word in the PDB at
720 ; [2] to determine the number of paragraphs. Then truncate this to 64K at
723 push ds ;save ds for size calc
736 pop ds ;restore ds after size calc
739 MOV DI,OFFSET DG
:START
742 SUB CX,OFFSET DG
:START
;Available memory
743 SHR CX,1 ;1/2 of available memory
745 SHR CX,1 ;1/4 of available memory
746 MOV [ONE4TH
],CX ;Save amount of 1/4 full
747 ADD CX,AX ;3/4 of available memory
749 ADD DX,OFFSET DG
:START
750 MOV [THREE4TH
],DX ;Save pointer to 3/4 full
751 MOV DX,OFFSET DG
:START
754 MOV BYTE PTR [DI],1
AH
756 MOV BYTE PTR [COMBUF
],128
757 MOV BYTE PTR [EDITBUF
],255
758 MOV BYTE PTR [EOL
],10
759 MOV [POINTER
],OFFSET DG
:START
762 MOV [PARAM1
],0 ;M004 Leave room in memory, was -1
766 ; The above setting of PARAM1 to -1 causes this call to APPEND to try to read
767 ; in as many lines that will fit, BUT.... What we are doing is simulating
768 ; the user issuing an APPEND command, and if the user asks for more lines
769 ; than we get then an "Insufficient memory" error occurs. In this case we
770 ; DO NOT want this error, we just want as many lines as possible read in.
771 ; The twiddle of ENDING suppresses the memory error
773 MOV BYTE PTR [ENDING
],1 ;Suppress memory errors
775 MOV ENDING
,0 ; restore correct initial value
777 Break <Main command
loop>
780 ; Main read/parse/execute loop. We reset the stack all the time as there
781 ; are routines that JMP back here. Don't blame me; Tim Paterson write this.
784 push cs ;an000;set up addressibility
788 assume
ds:dg
,es:dg
;an000;
791 MOV AX,(SET_INTERRUPT_VECTOR
SHL 8) OR 23H
792 MOV DX,OFFSET DG
:ABORTCOM
794 mov dx,offset dg
:prompt_ptr
796 MOV DX,OFFSET DG
:COMBUF
797 MOV AH,STD_CON_STRING_INPUT
799 MOV [COMLINE
],OFFSET DG
:COMBUF
+ 2
800 mov dx,offset dg
:lf_ptr
806 mov [fourth
],0 ;reset the fourth parameter flag
809 MOV BP,OFFSET DG
:PARAM1
814 ; AL has first char after arg
819 MOV ParamCt
,DI ; set up count of parameters
820 SHR ParamCt
,1 ; convert to index (1-based)
822 CALL SKIP1
; skip to next parameter
823 CMP AL,"," ; is there a comma?
824 JZ CHKLP
; if so, then get another arg
825 DEC SI ; point at char next
826 CALL Kill_BL
; skip all blanks
827 CMP AL,"?" ; is there a ?
828 JNZ DISPATCH
; no, got command letter
829 MOV QFLG
,-1 ; signal query
838 MOV DI,OFFSET DG
:COMTAB
842 SUB DI,1+OFFSET DG
:COMTAB
; convert to index
848 JB COMERR
; Param. 2 must be >= param 1
877 Break <Range Checking
and argument parsing
>
880 ; People call here. we need to reset the stack.
881 ; Inputs: BX has param1
882 ; Outputs: Returns if BX <= Param2
890 POP DX ; clean up return address
892 MOV DX,OFFSET DG
:BADCOM_ptr
898 ; GetNum parses off 1 argument from the command line. Argument forms are:
899 ; nnn a number < 65536
900 ; +nnn current line + number
901 ; -nnn current line - number
909 cmp di,6 ;Is this the fourth parameter?
911 mov [fourth
],1 ;yes, set the flag
922 MOV CL,0 ;Flag no parameter seen yet
928 CMP DX,6553 ;Max line/10
929 JAE COMERR
;Ten times this is too big
930 MOV CL,1 ;Parameter digit has been found
945 JZ COMERR
;Don't allow zero as a parameter
949 cmp [fourth
],1 ;the fourth parameter?
950 je comerra
;yes, an error
955 cmp [fourth
],1 ;the fourth parameter?
956 je comerra
;yes, an error
960 MOV DI,OFFSET DG
:START
974 cmp [fourth
],1 ;the fourth parameter?
975 je comerra
;yes, an error
980 cmp [fourth
],1 ;the fourth parameter?
981 je comerra
;yes, an error
985 JA OkLin
; if negative or zero
986 MOV BX,1 ; use first line
994 Break <Dispatch Table
>
996 ;-----------------------------------------------------------------------;
997 ; Careful changing the order of the next two tables. They are linked and
998 ; changes should be be to both.
1000 COMTAB
DB 13,";ACDEILMPQRSTW"
1003 TABLE
DW NOCOM
; Blank line
1005 DW APPEND
; A(ppend)
1007 DW DELETE
; D(elete)
1009 DW INSERT
; I(nsert)
1014 dw replac_from_curr
; R(eplace)
1015 dw search_from_curr
; S(earch)
1024 Break <Move
and Copy commands
>
1030 MOV BYTE PTR [MOVFLG
],1
1037 MOV BYTE PTR [MOVFLG
],0
1039 ; We are to move/copy a number of lines from one range to another.
1041 ; Memory looks like this:
1045 ; pointer-> line n Current has n in it
1052 ; Bounds check on args.
1053 ; set ptr1 and ptr2 to range before move
1054 ; set copysiz to number to move
1055 ; open up copysize * count for destination
1056 ; if destination is before ptr1 then
1057 ; add copysize * count to both ptrs
1058 ; while count > 0 do
1059 ; move from ptr1 to destination for copysize bytes
1062 ; move from ptr2 through end to ptr1
1063 ; set endtxt to last byte moved.
1064 ; set current, pointer to original destination
1069 ; Make sure that all correct arguments are specified.
1071 MOV BX,[PARAM3
] ; get destination of move/copy
1072 OR BX,BX ; must be specified (non-0)
1073 MOV DX,OFFSET DG
:DEST_ptr
1074 JZ ERROR1J
; is 0 => error
1076 ; get arg 1 (defaulting if necessary) and range check it.
1078 MOV BX,[PARAM1
] ; get first argument
1079 OR BX,BX ; do we default it?
1080 JNZ NXTARG
; no, assume it is OK.
1081 MOV BX,[CURRENT
] ; Defaults to the current line
1082 CALL CHKRANGE
; Make sure it is good.
1083 MOV [PARAM1
],BX ; set it
1085 CALL FINDLIN
; find first argument line
1086 JNZ ErrorJ
; line not found
1089 ; get arg 2 (defaulting if necessary) and range check it.
1091 MOV BX,[PARAM2
] ; Get the second parameter
1092 OR BX,BX ; do we default it too?
1094 MOV BX,[CURRENT
] ; Defaults to the current line
1095 MOV [PARAM2
],BX ; Stash it away
1098 JNZ ErrorJ
; line not found
1100 INC BX ;Get pointer to line Param2+1
1102 MOV [PTR_2
],DI ;Save it
1104 ; We now have true line number arguments and pointers to the relevant places.
1105 ; ptr_1 points to beginning of region and ptr_2 points to first byte beyond
1108 ; Check args for correct ordering of first two arguments
1112 jbe havargs1
; first must be <= second
1116 ; make sure that the third argument is not contained in the first range
1119 CMP DX,[PARAM1
] ; third must be <= first or
1122 JA NoError
; third must be > last
1126 ; Determine number to move
1129 SUB CX,Ptr_1
; Calculate number of bytes to copy
1131 MOV CopyLen
,CX ; Save for individual move.
1132 MOV AX,[PARAM4
] ; Was count defaulted?
1134 JZ SizeOk
; yes, CX has correct value
1135 MUL [COPYSIZ
] ; convert to true size
1136 MOV CX,AX ; move to count register
1137 OR DX,DX ; overflow?
1139 JMP MEMERR
; yes, bomb.
1143 ; Check to see that we have room to grow by copysiz
1145 MOV AX,[ENDTXT
] ; get pointer to last byte
1146 MOV DI,[LAST
] ; get offset of last location in memory
1147 SUB DI,AX ; remainder of space
1148 CMP DI,CX ; is there at least copysiz room?
1153 ; Find destination of move/copy
1159 ; open up copysiz bytes of space at destination
1161 ; move (p3, p3+copysiz, endtxt-p3);
1163 MOV SI,EndTxt
; get source pointer to end
1165 SUB CX,DI ; number of bytes from here to end
1166 INC CX ; remember ^Z at end
1167 MOV DI,SI ; destination starts at end
1168 ADD DI,[COPYSIZ
] ; plus size we are opening
1169 MOV [ENDTXT
],DI ; new end point
1171 REP MOVSB ; and store everything
1174 ; relocate ptr_1 and ptr_2 if we moved them
1177 CMP BX,Ptr_1
; was dest before source?
1178 JA NoReloc
; no, above. no relocation
1181 ADD Ptr_2
,BX ; relocate pointers
1184 ; Now we copy for count times copylen bytes from ptr_1 to ptr_3
1186 ; move (ptr_1, ptr_3, copylen);
1188 MOV BX,Param4
; count (0 and 1 are both 1)
1189 MOV DI,Ptr_3
; destination
1191 MOV CX,CopyLen
; number to move
1192 MOV SI,Ptr_1
; start point
1193 REP MOVSB ; move the bytes
1194 SUB BX,1 ; exhaust count?
1195 JG CopyText
; no, go for more
1199 CMP BYTE PTR MovFlg
,0
1202 ; Delete the source text between ptr_1 and ptr_2
1204 ; move (ptr_2, ptr_1, endtxt-ptr_2);
1206 MOV DI,Ptr_1
; destination
1207 MOV SI,Ptr_2
; source
1208 MOV CX,EndTxt
; pointer to end
1209 SUB CX,SI ; number of bytes to move
1212 MOV BYTE PTR ES:[DI],1
Ah ; remember ^Z terminate
1213 MOV EndTxt
,DI ; new end of file
1215 ; May need to relocate current line (parameter 3).
1217 MOV BX,Param3
; get new current line
1218 CMP BX,Param1
; do we need to relocate
1219 JBE CopyDone
; no, current line is before removed M002
1220 ADD BX,Param1
; add in first
1221 SUB BX,Param2
; current += first-last - 1;
1226 ; we are done. Make current line the destination
1228 MOV BX,Param3
; set parameter 3 to be current
1234 Break <MoveFile
- open up a hole
in the internal
file>
1237 ; MoveFile moves the text in the buffer to create a hole
1239 ; Inputs: DX is spot in buffer for destination
1240 ; DI is spot in buffer for source
1242 MOV CX,[ENDTXT
] ;Get End-of-text marker
1244 SUB CX,DI ;Calculate number of bytes to copy
1245 INC CX ; remember ^Z
1248 REP MOVSB ;Copy CX bytes
1254 MOV [POINTER
],DI ;Current line is first free loc
1255 MOV [CURRENT
],BX ; in the file
1256 MOV [ENDTXT
],BP ;End-of-text is last free loc before
1260 cmp ax,error_file_not_found
1262 MOV DX,OFFSET DG
:FILENM_ptr
1266 MOV DX,OFFSET DG
:BADDRV_ptr
1277 MOV DI,OFFSET DG
:MRG_PATH_NAME
1297 ;=========================================================================
1298 ; implement EXTENDED OPEN
1299 ;=========================================================================
1301 push es ;an000;save reg.
1302 mov bx,ext_read
;an000;open for read
1303 mov cx,ATTR
;an000;file attributes
1304 mov dx,OPEN_FLAG
;an000;action to take on open
1305 mov di,0ffffh ;an000;null parm list
1306 call EXT_OPEN3
;an000;create file;DMS:6/10/87
1307 pop es ;an000;restore reg.
1309 ;=========================================================================
1314 MOV AX,(SET_INTERRUPT_VECTOR
SHL 8) OR 23H
1315 MOV DX,OFFSET DG
:ABORTMERGE
1338 MOV DX,OFFSET DG
:MRGERR_ptr
1356 inc cx ; remember ^Z
1358 dec di ; unremember ^Z
1371 MOV AX,(SET_INTERRUPT_VECTOR
SHL 8) OR 23H
;Set vector 23H
1372 MOV DX,OFFSET DG
:ABORTINS
1385 CALL SETPTS
;Update the pointers into file
1387 MOV DX,OFFSET DG
:EDITBUF
1388 MOV AH,STD_CON_STRING_INPUT
1391 MOV SI,2 + OFFSET DG
:EDITBUF
1392 CMP BYTE PTR [SI],1
AH
1394 ;-----------------------------------------------------------------------
1395 call unquote
;scan for quote chars if any
1396 ;-----------------------------------------------------------------------
1417 MOV DX,OFFSET DG
:START
1422 MOV AX,CS ;Restore segment registers
1447 MOV AX,(SET_INTERRUPT_VECTOR
SHL 8) OR 23H
1448 MOV DX,OFFSET DG
:ABORTCOM
1454 MOV [PARAM1
],-1 ;Read in max. no of lines
1461 ;Write text out to .$$$ file
1469 MOV BYTE PTR [ENDING
],1 ;Suppress memory errors
1470 MOV BX,-1 ;Write max. no of lines
1472 TEST BYTE PTR [HAVEOF
],-1
1478 INT 21H
;Write end-of-file byte
1480 ;Close input file ; MZ 11/30
1482 MOV BX,[RD_HANDLE
] ; MZ 11/30
1483 MOV AH,CLOSE
; MZ 11/30
1492 ;Rename original file .BAK
1495 MOV SI,OFFSET DG
:BAK
1499 MOV DX,OFFSET DG
:PATH_NAME
1500 MOV DI,OFFSET DG
:TEMP_PATH
1504 MOV SI,OFFSET DG
:$$$
FILE
1509 ;Rename .$$$ file to original name
1511 MOV DX,OFFSET DG
:TEMP_PATH
1512 MOV DI,OFFSET DG
:PATH_NAME
1520 ;=========================================================================
1521 ; EDLIN_DISP_GET: This routine will give us the attributes of the
1522 ; current display, which are to be used to restore the screen
1523 ; back to its original state on exit from EDLIN. We also
1524 ; set the screen to a text mode here with an 80 X 25 color
1527 ; Inputs : VIDEO_GET - 0fH (get current video mode)
1528 ; VIDEO_SET - 00h (set video mode)
1529 ; VIDEO_TEXT- 03h (80 X 25 color mode)
1531 ; Outputs : VIDEO_ORG - Original video attributes on entry to EDLIN
1533 ;=========================================================================
1535 EDLIN_DISP_GET proc
near ;an000;video attributes
1537 push ax ;an000;save affected regs.
1544 push cs ;an000;exchange cs/ds
1547 mov ax,440
Ch ;an000;generic ioctl
1548 mov bx,Std_Out
;an000;Console
1549 mov cx,(Display_Attr
shl 8) or Get_Display
;an000;get display
1550 mov dx,offset dg
:Video_Buffer
;an000;buffer for video attr.
1552 ; $if nc ;an000;function returned a
1555 mov si,dx ;an000;get pointer
1556 mov ax,word ptr dg
:[si].Display_Length_Char
;an000;get video len.
1557 dec ax ;an000;allow room for message
1558 mov dg
:Disp_Len
,al ;an000;put it into var.
1559 mov ax,word ptr dg
:[si].Display_Width_Char
;an000;get video width
1560 mov dg
:Disp_Width
,al ;an000;put it into var.
1561 ; $else ;an000;function failed use
1565 mov al,Def_Disp_Len
;an000;get default length
1566 dec al ;an000;leave room for messages
1567 mov dg
:Disp_Len
,al ;an000;use default length
1568 mov dg
:Disp_Width
,Def_Disp_Width
;an000;use default width
1572 pop ds ;an000;restore affected regs.
1579 ret ;an000;return to caller
1581 EDLIN_DISP_GET endp
;an000;end proc.
1584 ;=========================================================================
1585 ; EXT_OPEN1 : This routine opens a file for read/write access. If the file
1586 ; if not present for opening the open will fail and return with a
1589 ; Inputs : BX - Open mode
1590 ; CX - File attributes
1593 ; Outputs: CY - If error
1596 ;=========================================================================
1598 EXT_OPEN1 proc
near ;an000;open for R/W
1601 push ds ;an000;save regs
1604 mov ah,ExtOpen
;an000;extended open
1605 mov al,0 ;an000;reserved by system
1606 mov si,offset dg
:path_name
;an000;point to PATH_NAME
1608 int 21h
;an000;invoke function
1609 pop si ;an000;restore regs
1612 ret ;an000;return to caller
1614 EXT_OPEN1 endp
;an000;end proc.
1616 ;=========================================================================
1617 ; EXT_OPEN2 : This routine will attempt to create a file for read/write
1618 ; access. If the files exists the create will fail and return
1619 ; with the carry set.
1621 ; Inputs : BX - Open mode
1622 ; CX - File attributes
1625 ; Outputs: CY - If error
1628 ;=========================================================================
1630 EXT_OPEN2 proc
near ;an000;create a file
1633 push ds ;an000;save regs
1636 mov ah,ExtOpen
;an000;extended open
1637 mov al,0 ;an000;reserved by system
1638 mov si,offset dg
:temp_path
;an000;point to TEMP_PATH
1640 int 21h
;an000;invoke function
1642 pop si ;an000;restore regs
1645 ret ;an000;return to caller
1647 EXT_OPEN2 endp
;an000;end proc.
1649 ;=========================================================================
1650 ; EXT_OPEN3 : This routine will attempt to create a file for read
1651 ; access. If the files exists the create will fail and return
1652 ; with the carry set.
1654 ; Inputs : BX - Open mode
1655 ; CX - File attributes
1658 ; Outputs: CY - If error
1661 ;=========================================================================
1663 EXT_OPEN3 proc
near ;an000;create a file
1666 push ds ;an000;save regs
1669 mov ah,ExtOpen
;an000;extended open
1670 mov al,0 ;an000;reserved by system
1671 mov si,offset dg
:mrg_path_name
;an000;point to mrg_path_name
1673 int 21h
;an000;invoke function
1675 pop si ;an000;restore regs
1678 ret ;an000;return to caller
1680 EXT_OPEN3 endp
;an000;end proc.
1683 ;=========================================================================
1684 ; EDLIN_COMMAND : This routine provides an interface between the new
1685 ; parser and the existing logic of EDLIN. We will be
1686 ; interfacing the parser with three existing variables.
1688 ; Inputs : FILESPEC - Filespec entered by the user and passed by
1691 ; PARSE_SWITCH_B - Contains the result of the parse for the
1692 ; /B switch. This is passed by the parser.
1694 ; Outputs: PATH_NAME - Filespec
1695 ; LOADMOD - Flag for /B switch
1696 ; FNAME_LEN - Length of filespec
1699 ;=========================================================================
1701 EDLIN_COMMAND proc
near ;an000;interface parser
1703 push ax ;an000;save regs.
1708 mov si,offset dg
:filespec
;an000;get its offset
1709 mov di,offset dg
:path_name
;an000;get its offset
1711 mov cx,00h ;an000;cx will count filespec
1713 cmp parse_switch_b
,true
;an000;do we have /B switch
1714 ; $if z ;an000;we have the switch
1716 mov [LOADMOD
],01h ;an000;signal switch found
1720 ; $do ;an000;while we have filespec
1722 lodsb ;an000;move byte to al
1723 cmp al,nul
;an000;see if we are at
1726 ; $leave e ;an000;exit while loop
1728 stosb ;an000;move byte to path_name
1729 inc cx ;an000;increment the length
1731 ; $enddo ;an000;end do while
1735 mov [FNAME_LEN
],cx ;an000;save filespec's length
1737 pop si ;an000; restore regs
1742 ret ;an000;return to caller
1744 EDLIN_COMMAND endp
;an000;end proc
1746 ;=========================================================================
1747 ; Get_Extended_Attrib : This routine gets the extended attributes of
1748 ; the file that was opened.
1750 ;=========================================================================
1752 Get_Extended_Attrib proc
near ;an000; dms;
1754 mov ax,5702h
;an000; dms;get extended attrib
1755 mov si,0ffffh ;an000; dms;all attribs
1756 mov cx,dg
:EA_Buffer_Size
;an000; dms;buffer size
1757 mov di,offset dg
:Start
;an000; dms;point to buffer
1758 int 21h
;an000; dms;
1761 Get_Extended_Attrib endp
;an000; dms;
1764 ;=========================================================================
1765 ; Query_Extend_Attrib : This routine gets the extended attributes of
1766 ; the file that was opened.
1768 ; Inputs : Start - Buffer for extended attributes
1770 ; Outputs : CX - size in paras
1772 ;=========================================================================
1774 Query_Extend_Attrib proc
near ;an000; dms;
1776 mov ax,5702h
;an000; dms;get extended attrib
1777 mov si,0ffffh ;an000; dms;all attribs
1778 mov cx,0000h ;an000; dms;get buffer size
1779 mov di,offset dg
:Start
;an000; dms;point to buffer
1780 int 21h
;an000; dms;
1781 mov dg
:EA_Buffer_Size
,cx ;an000; dms;save buffer size
1784 Query_Extend_Attrib endp
;an000; dms;
1787 ;=========================================================================
1788 ; Calc_Memory_Avail : This routine will calculate the memory
1789 ; available for use by EDLIN.
1791 ; Inputs : ORG_DS - DS of PSP
1793 ; Outputs : DX - paras available
1794 ;=========================================================================
1796 Calc_Memory_Avail proc
near ;an000; dms;
1798 push ds ;save ds for size calc
1799 push cx ;an000; dms;
1800 push di ;an000; dms;
1806 mov dx,cx ;an000; dms;put paras in DX
1814 Calc_Memory_Avail endp
;an000; dms;
1816 ;=========================================================================
1817 ; EA_Fail_Exit : This routine tells the user that there was
1818 ; Insufficient memory and exits EDLIN.
1820 ; Inputs : MemFul_Ptr - "Insufficient memory"
1823 ;=========================================================================
1825 EA_Fail_Exit proc
near ;an000; dms;
1827 mov dx,offset dg
:MemFul_Ptr
;an000; dms;"Insufficient
1829 push cs ;an000; dms;xchange ds/cs
1832 call Std_Printf
;an000; dms;print message
1833 mov ah,exit
;an000; dms;exit
1834 xor al,al ;an000; dms;clear al
1835 int 21h
;an000; dms;
1838 EA_Fail_Exit endp
;an000; dms;