1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
|
PAGE 60,132;
TITLE EDLCMD1.ASM
;======================= START OF SPECIFICATIONS =========================
;
; MODULE NAME: EDLCMD1.SAL
;
; DESCRIPTIVE NAME: EDLIN ROUTINES
;
; FUNCTION: THIS MODULE PROVIDES ROUTINES NEEDED FOR EDLIN'S EXECUTION.
;
; ENTRY POINT: ANY CALLED ROUTINE
;
; EXIT NORMAL: NA
;
; EXIT ERROR : NA
;
; INTERNAL REFERENCES:
;
; EXTERNAL REFERENCES:
;
; ROUTINE: EDLCMD2 - ROUTINES MAY BE CALLED FROM EDLCMD2
; EDLMES - ROUTINES MAY BE CALLED FROM EDLMES
;
; NOTES: THIS MODULE IS TO BE PREPPED BY SALUT WITH THE "PR" OPTIONS.
; LINK EDLIN+EDLCMD1+EDLCMD2+EDLMES+EDLPARSE
;
; REVISION HISTORY:
;
; AN000 VERSION DOS 4.00 - REVISIONS MADE RELATE TO THE FOLLOWING:
;
; - IMPLEMENT SYSPARSE
; - IMPLEMENT MESSAGE RETRIEVER
; - IMPLEMENT DBCS ENABLING
; - ENHANCED VIDEO SUPPORT
; - EXTENDED OPENS
; - SCROLLING ERROR
;
; COPYRIGHT: "MS DOS EDLIN UTILITY"
; "VERSION 4.00 (C) COPYRIGHT 1988 Microsoft"
;
;======================= END OF SPECIFICATIONS ===========================
include edlequ.asm
SUBTTL Contants and Data areas
PAGE
CODE SEGMENT PUBLIC
CODE ENDS
CONST SEGMENT PUBLIC WORD
CONST ENDS
cstack segment stack
cstack ends
DATA SEGMENT PUBLIC WORD
DATA ENDS
DG GROUP CODE,CONST,cstack,DATA
CONST SEGMENT PUBLIC WORD
EXTRN DSKFUL_ptr:word,READ_ERR_PTR:word
EXTRN NOSUCH_ptr:word,TOOLNG_ptr:word,EOF_ptr:word
extrn txt1:byte,txt2:byte
CONST ENDS
cstack segment stack
cstack ends
DATA SEGMENT PUBLIC WORD
extrn ParamCt:WORD
extrn current:word,pointer:word,start:word,endtxt:word
extrn wrt_handle:word,editbuf:byte,path_name:byte,fname_len:word
extrn arg_buf:byte,arg_buf_ptr:word
extrn olddat:byte,oldlen:word,newlen:word,param1:word,param2:word
extrn srchflg:byte,srchmod:byte,comline:word,lstfnd:word,numpos:word
extrn lstnum:word,srchcnt:word,amnt_req:word,delflg:byte,lastlin:word
extrn three4th:word,one4th:word,last:word,rd_handle:word,ending:byte
extrn haveof:byte
extrn Disp_Len:Byte
DATA ENDS
CODE SEGMENT PUBLIC
ASSUME CS:DG,DS:DG,SS:CStack,ES:DG
extrn findlin:near,shownum:near,loadbuf:near
extrn delbak:near,unquote:near,lf:near
extrn dispone:near,display:near,query:near
extrn quit:near,scanln:near,scaneof:near
extrn fndfirst:near,fndnext:near,replace:near,memerr:near
extrn std_printf:near,chkrange:near,comerr:near
public xerror,bad_read,append,nocom,pager,list
public delete,replac_from_curr,search_from_curr,ewrite,wrt
NOMOREJ:JMP NOMORE
APPEND:
CMP ParamCt,1
JZ AppendOK
JMP ComErr
AppendOK:
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
jb parmapp
return ;If so, then done already
PARMAPP:
MOV DI,DX
MOV CX,[LAST]
SUB CX,DX ;Amount of memory available
jnz sj53
jmp memerr
sj53:
MOV DX,[ENDTXT]
MOV BX,[RD_HANDLE]
mov [amnt_req],cx ;Save number of chars requested
MOV AH,READ
INT 21H ;Fill memory with file data
CMP CX,AX ;Did we read less than we asked for?
JZ SJ55
; Make sure this is an end-of-file by trying to read more
PUSH AX ;Save old byte count
ADD DX,AX ;Point to next open space in buffer
MOV CX,1 ;Just one character past EOF
MOV AH,READ
INT 21H
CMP AX,0 ;Is it EOF?
POP AX
JNZ SJ54 ;No -- we have one more character
MOV BYTE PTR [HAVEOF],1 ;Yes - set old style system call flag
JMP SHORT SJ55
SJ54:
INC AX ;Include one more char in byte count
sj55:
MOV CX,AX ;Want byte count in CX
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
CMP HavEof,1
JNZ DoBackScan
;
; We have an incomplete line in the buffer at end of file. Fix it up to be
; pretty.
;
MOV BYTE PTR [DI],13 ; CR
MOV BYTE PTR [DI+1],10 ; LF
ADD DI,2 ; length is 2 greater
POP CX
ADD CX,2
PUSH CX
JMP SHORT FULLN
DoBackScan:
DEC DI
MOV CX,[LAST]
STD
REPNE SCASB ;Scan backwards for last line
CLD
INC DI
INC DI
DEC DX
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
; Must seek for old partial line
OR DI,DI
JZ FULLN1
PUSH DX
PUSH BX
MOV BX,[RD_HANDLE]
MOV DX,DI
NEG DX
MOV CX,-1
MOV AL,1
MOV AH,LSEEK
INT 21H
POP BX
POP DX
JC BAD_READ
FULLN1:
CMP BX,DX
JNZ EOFCHK
MOV BYTE PTR [HAVEOF],0
return
NOMORE:
MOV DX,OFFSET DG:EOF_ptr
call std_printf
ret3: return
BAD_READ:
MOV DX,OFFSET DG:READ_ERR_ptr
MOV DI,offset dg:path_name
ADD DI,[FNAME_LEN]
MOV AL,0
STOSB
JMP XERROR
EOFCHK:
TEST BYTE PTR [HAVEOF],-1
JNZ NOMORE
TEST BYTE PTR [ENDING],-1
retnz ;Suppress memory error during End
JMP MEMERR
EWRITE:
CMP ParamCt,1
JBE EWriteOK
JMP ComErr
EWriteOK:
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
retz
MOV BX,[WRT_HANDLE]
MOV AH,WRITE
INT 21H
JC WRTERR
CMP AX,CX ; MZ correct full disk detection
JNZ WRTERR ; MZ correct full disk detection
MOV SI,DI
MOV DI,OFFSET DG:START
MOV [POINTER],DI
MOV CX,[ENDTXT]
SUB CX,SI
INC CX ;Amount of text remaining
CLD
REP MOVSB
DEC DI ;Point to EOF
MOV [ENDTXT],DI
MOV [CURRENT],1
return
WRTERR:
MOV BX,[WRT_HANDLE]
MOV AH,CLOSE
INT 21H
MOV DX,OFFSET DG:DSKFUL_ptr
xERROR:
push cs
pop ds
call std_printf
mov al,0ffh
mov ah,exit
int 21h
NOTFNDJ:JMP NOTFND
replac_from_curr:
CMP ParamCt,2
JBE Replace1
JMP ComErr
Replace1:
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
jbe len_ok
Jmp TOOLONG
len_ok:
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
mov di,offset dg:arg_buf ;Initialize the output string buffer
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
xor al,al
stosb
mov dx,offset dg:arg_buf_ptr
call std_printf
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
retnz
JMP REPLP
OUTCNT:
JCXZ RET8
OUTLP:
LODSB
stosb
DEC DX
LOOP OUTLP
RET8: return
TOOLONG:
MOV DX,OFFSET DG:TOOLNG_ptr
JMP SHORT PERR
search_from_curr:
CMP ParamCt,2
JBE Search1
JMP ComErr
Search1:
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
CLD
REPNE SCASB
JNZ NOTFND
MOV [LSTFND],DI
MOV [NUMPOS],DI
MOV [SRCHCNT],CX
INC [LSTNUM]
CALL QUERY
JZ PUTCURS1
CALL FNDNEXT
JZ SRCH
NOTFND:
MOV DX,OFFSET DG:NOSUCH_ptr
PERR:
call std_printf
return
;
; Replace enters here with LSTNUM pointing to the correct line.
;
PUTCURS:
MOV BX,[LSTNUM]
jmp short putcursor
;
; Search enters here with LSTNUM pointing AFTER the correct line
;
putcurs1:
MOV BX,[LSTNUM]
DEC BX ;Current <= Last matched line
putcursor:
CALL FINDLIN
MOV [CURRENT],DX
MOV [POINTER],DI
return
;
; n,mD deletes a range of lines. Allowable values for n are:
; 1 ... LAST. Allowable values for m are:
; 1 ... LAST.
; nD deletes a single line
; D deletes the current line
;
DELETE:
CMP ParamCt,2 ; at most two parameters specified.
JA ComErrJ
MOV BX,Param1
OR BX,BX ; default first arg?
JNZ DelParm2
MOV BX,Current ; use current as default
MOV Param1,BX
DelParm2:
MOV BX,Param2 ; did we default second arg?
OR BX,BX
JNZ DelCheck ; no, use it.
MOV BX,Param1 ; use param1 as default
MOV Param2,BX
DelCheck:
MOV BX,Param1
CALL ChkRange ; returns by itself if bad range
;
; BX is first line of range to be deleted. Param2 is last line in range to
; be deleted. Get pointer to beginning of block. Save location
;
CALL FINDLIN ; Grab line
retnz ; If not found => return
PUSH BX
PUSH DI
;
; Get pointer past end of block (Param2+1).
;
MOV BX,Param2
INC BX
CALL FINDLIN
;
; Set up pointers. Compute number of chars to move.
;
MOV SI,DI ; move from second line+1
POP DI ; restore destination (first line)
POP Current ; Current line is first param
MOV Pointer,DI ; internal current line
MOV CX,EndTxt ; compute count
SUB CX,SI
JB ComErrJ ; should never occur: ChkRange
INC CX ; remember ^Z at end
CLD
REP MOVSB ; move data
DEC DI
MOV EndTxt,DI ; reset end pointer
return
COMERRJ:
JMP COMERR
PAGER:
CMP ParamCt,2
JA ComErrJ
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
jbe frstok1
return ;if not just quit
frstok1:
mov dx,[param2]
or dx,dx ;was param2 specified?
jnz scndok ;yes,....
mov dx,bx ;no, take the end line to be the
; start line + length of active display
;=========================================================================
; This modification is to provide support for screens larger than
; 24 lines.
;
; Date : 6/10/87
;=========================================================================
push ax ;an000;save affected registers
mov ah,00h ;an000;zero out high byte
mov al,dg:disp_len ;an000;set ax to active display length
sub ax,2 ;an000;adjust for length of screen & current
; line
add dx,ax ;an000;this gives us the last line to be
; printed
pop ax ;an000;restore affected registers
;=========================================================================
scndok:
inc dx
cmp dx,[lastlin] ;check that we are in the buffer
jbe infile
mov dx,[lastlin] ;we are not, take the last line as end
infile:
cmp dx,bx ;is param1 < param2 ?
retz
ja sj33
jmp comerr ;yes, no backwards listing, print error
sj33:
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_lines
LIST:
CMP ParamCt,2
JBE ListOK
JMP ComERR
ListOK:
MOV BX,[PARAM1]
OR BX,BX
JNZ CHKP2
MOV BX,[CURRENT]
SUB BX,11
JA CHKP2
MOV BX,1
CHKP2:
CALL FINDLIN
retnz
MOV SI,DI
MOV DI,[PARAM2]
INC DI
SUB DI,BX
JA DISPLAY_lines
;=========================================================================
; This modification is to provide support for screens larger than
; 24 lines.
;
; Date : 6/10/87
;=========================================================================
push ax ;an000;save affected registers
mov ah,00h ;an000;zero out high byte
mov al,dg:disp_len ;an000;set ax to active display length dec ax ;an000;allow room at bottom for
; messages
mov di,ax ;an000;number of lines to print an
; entire screen less 1.
pop ax ;an000;restore affected registers
;=========================================================================
display_lines:
call DISPLAY
return
Break <NOCOM - edit a single line>
;
; NOCOM is called when there is a single line being edited. This occurs when
; the command letter is CR or is ;.
;
NOCOM:
CMP ParamCt,2
JB NoComOK
JMP ComErr
NoComOK:
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
ret12: return
sj12:
CMP SI,[ENDTXT]
retz
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
CALL lf
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 cl,[EditBuf+1] ;an000; dms;get new line length
mov ch,0 ;an000; dms;clear high byte
MOV DI,[POINTER]
JMP Replace ; MZ 11/30
CODE ENDS
END
|