]>
wirehaze git hosting - MS-DOS.git/blob - v4.0/src/CMD/EDLIN/EDLCMD2.ASM
2 TITLE Edlcmd2
- PART2 procedures called
from EDLIN
5 ;======================= START OF SPECIFICATIONS =========================
7 ; MODULE NAME: EDLCMD2.SAL
9 ; DESCRIPTIVE NAME: EDLIN ROUTINES
11 ; FUNCTION: THIS MODULE PROVIDES ROUTINES NEEDED FOR EDLIN'S EXECUTION.
13 ; ENTRY POINT: ANY CALLED ROUTINE
19 ; INTERNAL REFERENCES:
21 ; EXTERNAL REFERENCES:
23 ; ROUTINE: EDLCMD1 - ROUTINES MAY BE CALLED FROM EDLCMD1
24 ; EDLMES - ROUTINES MAY BE CALLED FROM EDLMES
26 ; NOTES: THIS MODULE IS TO BE PREPPED BY SALUT WITH THE "PR" OPTIONS.
27 ; LINK EDLIN+EDLCMD1+EDLCMD2+EDLMES+EDLPARSE
32 ; AN000 VERSION DOS 4.00 - REVISIONS MADE RELATE TO THE FOLLOWING:
34 ; - IMPLEMENT SYSPARSE
35 ; - IMPLEMENT MESSAGE RETRIEVER
36 ; - IMPLEMENT DBCS ENABLING
37 ; - ENHANCED VIDEO SUPPORT
41 ; COPYRIGHT: "MS DOS EDLIN UTILITY"
42 ; "VERSION 4.00 (C) COPYRIGHT 1988 Microsoft"
44 ;======================= END OF SPECIFICATIONS ===========================
51 CONST
SEGMENT PUBLIC WORD
57 DATA SEGMENT PUBLIC WORD
61 DG GROUP
CODE,CONST
,cstack
,DATA
63 CONST
SEGMENT PUBLIC WORD
64 extrn crlf_ptr
:byte,lf_ptr
:byte,qmes_ptr
:byte,ask_ptr
:byte
65 extrn bak
:byte,$$$
file:byte,delflg
:byte,loadmod
:byte,txt1
:byte
66 extrn txt2
:byte,memful_ptr
:word,YES_BYTE
:BYTE
68 extrn Del_Bak_Ptr
:byte ;an000;dms;
69 extrn cont_ptr
:byte ;an000;dms:6/10/87
73 DATA SEGMENT PUBLIC WORD
75 extrn current
:word,pointer
:word,start
:word,endtxt
:word
76 extrn wrt_handle
:word,editbuf
:byte,ext_ptr
:word,qflg
:byte
77 extrn temp_path
:byte,line_num
:word,line_flag
:byte
78 extrn line_num_buf_ptr
:byte,arg_buf
:byte,arg_buf_ptr
:word
79 extrn olddat
:byte,oldlen
:word,newlen
:word,param1
:word,param2
:word
80 extrn srchflg
:byte,srchmod
:byte,comline
:word,lstfnd
:word,numpos
:word
81 extrn lstnum
:word,last
:word,srchcnt
:word,amnt_req
:word
83 extrn lc_adj
:byte ;an000;dms:6/10/87
84 extrn continue
:byte ;an000;dms:6/10/87
85 extrn pg_count
:byte ;an000;dms:6/10/87
86 extrn Disp_Len
:byte ;an000;dms;
87 extrn Disp_Width
:byte ;an000;dms;
88 extrn lc_flag
:byte ;an000;dms:6/10/87
98 ASSUME
CS:DG
,DS:DG
,SS:CStack
,ES:DG
100 public findlin
,shownum
,loadbuf
,crlf
,lf
,abortcom
,unquote
101 public kill_bl
,make_caps
,display,dispone
,make_cntrl
102 public query
,quit
,scanln
,delbak
,scaneof
,memerr
103 public fndfirst
,fndnext
,replace
107 extrn std_printf
:near,command
:near,chkrange
:near,ComErr
:NEAR
114 ; BX = Line number to be located in buffer (0 means last line+1)
116 ; DX = Actual line found
117 ; DI = Pointer to start of line DX
118 ; Zero set if BX = DX (if specified line found)
119 ; AL,CX destroyed. No other registers affected.
123 CMP BX,DX ; fast find. Current = requested
125 JA FINDIT
; start scanning at current?
126 OR BX,BX ; special case of EOF?
128 MOV DX,1 ; set up for scan at beginning
129 MOV DI,OFFSET DG
:START
130 CMP BX,DX ; at beginning?
133 MOV CX,[ENDTXT
] ; count of bytes in buffer
136 MOV AL,10 ; LF is what we look for.
137 OR AL,AL ; Clear zero flag for JCXZ
139 JCXZ RET4
; at end? Yes, no skip.
140 REPNE SCASB ; find EOL
141 INC DX ; increment count
142 CMP BX,DX ; find correct line?
143 JNZ FINLIN
; no, try again.
147 ; BX = Line number to be displayed
149 ; Displays line number on terminal in 8-character
150 ; format, suppressing leading zeros.
151 ; AX, CX, DX destroyed. No other registers affected.
154 mov dx,offset dg
:line_num_buf_ptr
172 ; SI = Pointer to text buffer
175 ; Ouputs specified no. of line to terminal, each
176 ; with leading line number.
178 ; BX = Last line output.
179 ; All registers destroyed.
183 retz
; no lines to display
184 ;=========================================================================
185 ; Initialize screen size and line counts for use by display.
188 ;=========================================================================
190 push ax ;an000;save affected regs
192 mov al,dg
:disp_len
;an000;length of video display
193 mov pg_count
,al ;an000;init. screen size ctr.
195 pop ax ;an000;restore affected regs
197 ;=========================================================================
199 mov dx,di ;number of lines to print
201 ; CX is the number of bytes in the buffer
202 ; dx is the number of lines to be output
208 mov di,offset dg
:arg_buf
210 ; Copy chars until CR/LF or end of line hit
214 CMP DI,254+offset dg
:arg_buf
; are we at end of buffer?
215 JAE StoreDone
; Yes, do NOT store
232 CMP AL,10 ; perform copy until LF is seen
235 ; Make sure buffer ends with CRLF
237 cmp byte ptr [di-1],10
240 ; No LF seen. See if CR
242 cmp byte ptr [di-1],CR
252 call EDLIN_DISP_COUNT
;an000;determine lines printed
255 mov dx,offset dg
:arg_buf_ptr
261 call EDLIN_PG_COUNT
;an000;adjust screen line count
263 cmp lc_flag
,false
;an000;continue DISPLAY?
270 MOV DI,1+OFFSET DG
:TXT1
271 mov byte ptr[olddat
],1 ;replace with old value if none new
273 OR AL,AL ;Reset zero flag in case CX is zero
275 cmp al,1
ah ;terminated with a ^Z ?
277 mov byte ptr[olddat
],0 ;do not replace with old value
283 CMP BYTE PTR [SRCHFLG
],0
289 MOV DI,1+OFFSET DG
:TXT2
291 CMP BYTE PTR [SRCHFLG
],0
303 cmp byte ptr[srchmod
],0
305 mov bx,1 ;start from line number 1
309 INC BX ;Default search and replace to current+1
319 SBB BX,-1 ;Decrement everything except zero
334 ; [TXT1+1] has string to search for
335 ; [OLDLEN] has length of the string
336 ; [LSTFND] has starting position of search in text buffer
337 ; [LSTNUM] has line number which has [LSTFND]
338 ; [SRCHCNT] has length to be searched
339 ; [NUMPOS] has beginning of line which has [LSTFND]
341 ; Zero flag set if match found
342 ; [LSTFND],[LSTNUM],[SRCHCNT] updated for continuing the search
343 ; [NUMPOS] has beginning of line in which match was made
349 OR DI,DI ;Clear zero flag in case CX=0
350 REPNE SCASB ;look for first byte of string
352 retnz
;return if you don't find
354 call kanji_check
;see if the found byte is on a character boundary
358 MOV BX,DI ;Save search position
361 MOV SI,2 + OFFSET DG
:TXT1
362 CMP AL,AL ;Set zero flag in case CX=0
374 ;Determine line number of match
388 ;Kanji_check idea is to scan backwards to the first
389 ; character which can't be a kanji or part of one
390 ; (.lt. 40h) then scan forward to see if the
391 ; current byte is on character boundary
393 ;Output ZR <==> we're on a character boundary
394 ; NZ <==> we're not on character boundary i.e. No Match
396 push ax ;save search character
398 dec di ;point to the character we found
399 mov si,di ;start searching bakwards from there
405 inc si ;point to first non-kanji
408 cmp si,di ;are we at current byte?
409 jae passed_char
;if we are, or are passed it, exit
410 call next_char
;otherwise advance si to next char
411 jmp short kan_loop
;and loop
417 ;Next_char si points to a character boundary
418 ; advance si to point to the beginning of the next char
431 ;--------------------------------------------------------------------;
432 ; TESTKANJ ~ FIND OUT IS THE BYTE IS A KANJI PREFIX ;
434 ; entry: AL byte to test ;
436 ; exit: NZ if lead byte ortherwise ZR ;
440 ;--------------------------------------------------------------------;
444 xchg ah,al ;put byte in ah
447 lds si,cs:[lbtbl
] ;get pointer to lead byte table
449 lodsb ;direction flag should be OK
450 or al,al ;are we at the end of table?
452 cmp al,ah ;is START RANGE > CHARACTER?
453 ja notlead
;brif so, not a lead character (carry clear)
454 lodsb ;get second range byte
455 cmp ah,al ;is CHARACTER > END RANGE
456 ja ktlop
;brif so, not a lead character (check next range)
472 ; SI points into command line buffer
473 ; DI points to result buffer
475 ; Moves [SI] to [DI] until ctrl-Z (1AH) or
476 ; RETURN (0DH) is found. Termination char not moved.
478 ; AL = Termination character
479 ; CX = No of characters moved.
480 ; SI points one past termination character
481 ; DI points to next free location
487 ;-----------------------------------------------------------------------
488 cmp al,quote_char
;a quote character?
489 jne sj101
;no, skip....
490 lodsb ;yes, get quoted character
493 ;-----------------------------------------------------------------------
509 MOV BYTE PTR [DI-1],cl
514 cmp byte ptr[olddat
],1 ;replace with old text?
516 mov byte ptr[di-1],cl ;zero text buffer char count
520 MOV CL,BYTE PTR [DI-1]
527 ; CX = Length of new text
528 ; DX = Length of original text
529 ; SI = Pointer to new text
530 ; DI = Pointer to old text in buffer
532 ; New text replaces old text in buffer and buffer
533 ; size is adjusted. CX or DX may be zero.
534 ; CX, SI, DI all destroyed. No other registers affected.
570 MOV DX,OFFSET DG
:MEMFUL_ptr
576 MOV DI,2 + OFFSET DG
:EDITBUF
600 ;----- Load till physical end of file
602 cmp cx,word ptr[amnt_req
]
605 inc al ;reset zero flag
609 push di ;get rid of any ^Z at the end of the file
611 dec di ;points to last char
612 cmp byte ptr [di],1
ah
617 xor al,al ;set zero flag
618 call check_end
;check that we have a CRLF pair at the end
621 ;----- Load till first ^Z is found
628 jz not_found
;skip with zero flag set
629 REPNE SCASB ;Scan for end of file mark
631 LAHF ;Save flags momentarily
632 inc cx ;include the ^Z
635 mov di,cx ;not found at the end
637 LAHF ;Save flags momentarily
638 SUB CX,DI ;Reduce byte count if EOF found
641 call check_end
;check that we have a CRLF pair at the end
646 ;-----------------------------------------------------------------------
647 ; If the end of file was found, then check that the last character
648 ; in the file is a LF. If not put a CRLF pair in.
651 jnz not_end
;end was not reached
652 pushf ;save return flag
653 push di ;save pointer to buffer
654 add di,cx ;points to one past end on text
655 dec di ;points to last character
656 cmp di,offset dg
:start
658 cmp byte ptr[di],0ah ;is a LF the last character?
659 je check_done
;yes, exit
661 mov byte ptr[di+1],0dh ;no, put a CR
662 inc cx ;one more char in text
663 mov byte ptr[di+2],0ah ;put a LF
664 inc cx ;another character at the end
673 mov dx,offset dg
:crlf_ptr
678 MOV dx,offset dg
:lf_ptr
694 ;Delete old backup file (.BAK)
696 MOV BYTE PTR [DELFLG
],1
703 MOV DX,OFFSET DG
:TEMP_PATH
705 ; $if c ;error ? ;an000; dms;
707 cmp ax,Access_Denied
;file read only? ;an000; dms;
708 ; $if e ;yes ;an000; dms;
710 mov bx,[Wrt_Handle
] ;close .$$$ file ;an000; dms;
711 mov ah,Close
;close function ;an000; dms;
712 int 21h
;close it ;an000; dms;
714 mov di,[Ext_Ptr
] ;point to extension ;an000; dms;
715 mov si,offset dg
:$$$
File ;point to .$$$ extension;an000; dms;
716 movsw ;get .$$$ extension ;an000; dms;
719 mov dx,offset dg
:Temp_Path
;point to .$$$ file ;an000; dms;
720 mov ah,Unlink
;delete it ;an000; dms;
721 int 21h
; ;an000; dms;
723 mov di,[Ext_Ptr
] ;point to extension ;an000; dms;
724 mov si,offset dg
:BAK
;point to .BAK extension;an000; dms;
725 movsw ;get .BAK extension ;an000; dms;
728 mov dx,offset dg
:Del_Bak_Ptr
;point to error message ;an000; dms;
729 jmp Xerror
;display message & exit ;an000; dms;
736 MOV SI,OFFSET DG
:$$$
FILE
743 ;-----------------------------------------------------------------------;
744 ; Will scan buffer given pointed to by SI and get rid of quote
745 ;characters, compressing the line and adjusting the length at the
746 ;begining of the line.
747 ; Preserves al registers except flags and AX .
754 mov cl,[si-1] ;length of buffer
759 jcxz unq_done
;no more chars in the buffer, exit
760 repnz scasb ;search for quote character
761 jnz unq_done
;none found, exit
762 push cx ;save chars left in buffer
763 push di ;save pointer to quoted character
764 push ax ;save quote character
765 mov al,byte ptr[di] ;get quoted character
768 pop ax ;restore quote character
770 dec di ;points to the quote character
771 inc cx ;include the carriage return also
772 rep movsb ;compact line
773 pop di ;now points to after quoted character
775 jcxz sj13
;if quote char was last of line do not adjust
776 dec cx ;one less char left in the buffer
778 dec byte ptr[si-1] ;one less character in total buffer count also
789 ;-----------------------------------------------------------------------;
790 ; Convert the character in AL to the corresponding control
791 ; character. AL has to be between @ and _ to be converted. That is,
792 ; it has to be a capital letter. All other letters are left unchanged.
805 ;---- Kill spaces in buffer --------------------------------------------;
806 ;=========================================================================
807 ; kill_bl : Parses over spaces in a buffer.
810 ;=========================================================================
813 push bx ;an000;save affected reg.
816 lodsb ;get rid of blanks
818 je kill_bl_cont
;an000;it is a tab
821 je kill_bl_cont
;an000;if LF
824 je kill_bl_cont
;an000;we have a space
826 if kanji
;an000;is this a kanji assembly
827 call testkanj
;an000;do we have a dbcs lead byte
828 ; $if nz ;an000;yes, we have a lead byte
830 cmp al,dbcs_lead_byte
;an000;is it 81h
831 ; $if z ;an000;it is 81h
833 mov bl,ds:[si] ;an000;set up for compare
834 cmp bl,asian_blk
;an000;is it 40h
835 ; $if z ;an000;we have an asian blank
837 lodsb ;an000;skip byte containing 81h
841 ; $endif ;an000;fall through no delim
844 ; $endif ;an000;end test for dbcs lead byte
846 endif
;an000;end conditional assembly
848 pop bx ;an000;restore affected reg.
851 ;----- Capitalize the character in AL ----------------------------------;
855 ; AL contains a character to capitalize ;
859 ; AL contains a capitalized character ;
861 ;-----------------------------------------------------------------------;
868 JA CAPS1
; M003 MSKK TAR 476, kana chars
882 MOV DX,OFFSET DG
:QMES_ptr
888 MOV AX, (STD_CON_INPUT_FLUSH
SHL 8) + 0
889 INT 21H
; Eat the trailing byte.
893 ;=========================================================================
894 ; We are invoking the VAL_YN proc here. This will replace the
895 ; method of Y/N validation used prior to DOS 4.00.
898 ;=========================================================================
900 call val_yn
;an000;pass Y/N byte in AL to macro
901 cmp ax,yes
;an000;did we return a Y
902 jz NoCRLF
;an000; dms; close the file
903 cmp ax,no
;an000; dms; return N?
904 ; $if ne ;an000; dms; neither N or Y - reprompt
906 push dx ;an000; dms; must be N
907 mov dx,offset dg
:crlf_ptr
;an000; dms; spit out CRLF
908 call std_printf
;an000; dms; and return
909 pop dx ;an000; dms; to caller
910 jmp Quit1
;an000; dms; reprompt
911 ; $endif ;an000; dms;
913 push dx ;an000; dms; must be N
914 mov dx,offset dg
:crlf_ptr
;an000; dms; spit out CRLF
915 call std_printf
;an000; dms; and return
916 pop dx ;an000; dms; to caller
919 ;=========================================================================
920 ; End of Y/N validation check for qmes_ptr
921 ;=========================================================================
927 MOV DX,OFFSET DG
:TEMP_PATH
935 TEST BYTE PTR [QFLG
],-1
937 MOV DX,OFFSET DG
:ASK_ptr
946 MOV AX,(STD_CON_INPUT_FLUSH
SHL 8) + 0
947 INT 21H
;Eat the trailing byte
949 INC AX ; non zero flag
954 CMP AL,13 ;Carriage return means yes
956 ;=========================================================================
957 ; We are invoking the VAL_YN proc here. This will replace the
958 ; method of Y/N validation used prior to DOS 4.00.
959 ; This invocation of val_yn will return ZR if Y is found, otherwise
963 ;=========================================================================
965 call val_yn
;an000;pass Y/N byte in AL to macro
966 cmp ax,yes
;an000;did we return a Y
967 je Query_Exit
;an000; dms; exit Y/N validation
968 cmp ax,no
;an000; dms; N response?
969 jne Query
;an000; dms; no - reprompt user
970 cmp ax,yes
;an000; dms; must have N response - force
975 ;=========================================================================
976 ; End of Y/N validation check for ask_ptr
977 ;=========================================================================
981 ;=========================================================================
982 ; EDLIN_DISP_COUNT: This routine will determine the number of lines
983 ; actually displayed to the screen. Lines displayed to
984 ; the screen for one EDLIN line printed will be calculated
985 ; by the following formula:
987 ; LINES_PRINTED = (LINE_LEN + 10) / SCREEN_WIDTH
989 ; LINES_PRINTED - Actual number of lines printed on screen
990 ; for one EDLIN line. If LINES_PRINTED has
991 ; a remainder, it will be rounded up.
993 ; LINE_LEN - The length, in bytes, of the EDLIN line
996 ; SCREEN_WIDTH - The width in bytes of the current display.
998 ; Inputs : DI - offset into buffer containing line printed
999 ; DISP_WIDTH - width of current video output
1001 ; Outputs: LC_ADJ - factor to adjust line counter by
1004 ;=========================================================================
1006 EDLIN_DISP_COUNT proc
near ;an000;lines printed
1008 push dx ;an000;save affected regs
1014 mov bx,offset dg
:arg_buf
;an000;arg_buf holds line
1016 mov ax,di ;an000;where print line ends
1017 sub ax,bx ;an000;diff = line's length
1018 add ax,10 ;an000;adjust for leading blks
1019 mov cl,dg
:disp_width
;an000;set up for division
1020 div cl ;an000;divide AX by the
1021 ; width of the console
1022 cmp ah,0 ;an000;see if a remainder
1023 ; $if nz ;an000;if a remainder
1025 add al,1 ;an000;increment AL 1
1030 mov lc_adj
,al ;an000;number of lines printed
1032 pop cx ;an000;restore affected regs
1038 ret ;an000;return to caller
1040 EDLIN_DISP_COUNT endp
;an000;end proc
1042 ;=========================================================================
1043 ; EDLIN_PG_COUNT : This routine determines whether or not we will continue
1044 ; displaying text lines based on the count of lines that
1045 ; can be output to the current video screen.
1047 ; Inputs : LC_ADJ - adjustment factor for number of lines printed
1048 ; PG_COUNT - number of lines remaining on current video
1050 ; DX - holds the total number of lines to print
1051 ; CONTINUE - signals if the user wants to continue
1054 ; Outputs: LC_FLAG - used to signal completion of print
1057 ;=========================================================================
1059 EDLIN_PG_COUNT proc
near ;an000;track remaining lines
1061 push ax ;an000;save affected regs
1063 mov lc_flag
,true
;an000;init. flag to signal
1066 mov al,pg_count
;an000;set up for page adj.
1067 cmp al,lc_adj
;an000;see if we are at end
1070 mov pg_count
,0 ;an000;set pg_count to 0
1074 sub al,lc_adj
;an000;adjust number of lines
1075 mov pg_count
,al ;an000;save remaining line ct.
1079 dec dx ;an000;decrease total number
1080 ; of lines to print by 1
1081 ; $if nz ;an000;more lines to print
1083 cmp pg_count
,0 ;an000;have we printed screen
1084 ; $if be ;an000;we have printed screen
1086 call EDLIN_PG_PROMPT
;an000;prompt the user to
1088 cmp continue
,true
;an000;did user say continue
1089 ; $if z ;an000;continue
1091 mov al,dg
:disp_len
;an000;begin init of screen
1092 ; dec al ;an000; length
1093 mov pg_count
,al ;an000;
1094 ; $else ;an000;do not continue
1097 mov lc_flag
,false
;an000;signal no more to print
1102 ; $else ;an000;total lines printed
1105 mov lc_flag
,false
;an000;signal no more to print
1109 pop ax ;an000;restore affected regs
1111 ret ;an000;return to caller
1113 EDLIN_PG_COUNT endp
;an000;end procedure
1115 ;=========================================================================
1116 ; EDLIN_PG_PROMPT : This routine prompts the user as to whether or not to
1117 ; continue printing lines to the video display, if lines
1118 ; are still present for printing.
1122 ; Outputs: CONTINUE - flag that signals other routines whether or
1123 ; not to continue printing.
1126 ;=========================================================================
1128 EDLIN_PG_PROMPT proc
near ;an000;ask user to continue?
1130 push dx ;an000;save affected regs.
1135 mov dx,offset dg
:cont_ptr
;an000;point to Continue msg.
1136 call std_printf
;an000;invoke message ret.
1138 push ax ;an000;save affected regs.
1139 call crlf
;an000;send crlf
1140 pop ax ;an000;restore affected regs.
1142 call val_yn
;an000;Y/N validation
1144 cmp ax,yes
;an000;did we have a Y
1145 jz EPP_True_Exit
;an000;we had a Y
1146 cmp ax,no
;an000;did we have a N
1147 jz EPP_False_Exit
;an000;yes
1148 jmp EPP_Reprompt
;an000;neither Y or N - reprompt
1152 mov Continue
,True
;an000;flag Y found
1153 jmp EPP_Exit
;an000;exit routine
1157 mov Continue
,False
;an000;flag N found
1161 pop ax ;an000;restore affected regs.
1164 ret ;an000;return to caller
1166 EDLIN_PG_PROMPT endp
;an000;end procedure
1168 ;=========================================================================
1169 ; val_yn: This proc validates a Y/N response entered by the user. The
1170 ; routine uses the new functionality of "GET EXTENDED COUNTRY
1171 ; INFORMATION" being implemented in DOS 4.00.
1173 ; Inputs : AL - character to be validated for Y/N response
1175 ; Outputs: AX - 00h = "N"o
1177 ;=========================================================================
1179 val_yn proc
near ;an000;validate Y/N response
1181 push dx ;an000;save affected registers
1185 mov dl,al ;an000;character to be checked for Y/N
1186 mov ah,GetExtCntry
;an000;get extended country information
1187 mov al,yn_chk
;an000;perform Y/N checking
1188 mov cx,max_len
;an000;max. len. of Y/N char.
1189 int 21h
;an000;invoke function
1191 pop bx ;an000;restore affected registers
1195 ret ;an000;return to caller
1197 val_yn endp
;an000;end proc