forked from microsoft/MS-DOS
/
STRIN.ASM
403 lines (375 loc) · 12 KB
/
STRIN.ASM
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
; SCCSID = @(#)strin.asm 1.2 85/04/18
Break
; Inputs:
; DS:DX Point to an input buffer
; Function:
; Fill buffer from console input until CR
; Returns:
; None
procedure $STD_CON_STRING_INPUT,NEAR ;System call 10
ASSUME DS:NOTHING,ES:NOTHING
MOV AX,SS
MOV ES,AX
MOV SI,DX
XOR CH,CH
LODSW
;
; AL is the buffer length
; AH is the template length
;
OR AL,AL
retz ;Buffer is 0 length!!?
MOV BL,AH ;Init template counter
MOV BH,CH ;Init template counter
;
; BL is the number of bytes in the template
;
CMP AL,BL
JBE NOEDIT ;If length of buffer inconsistent with contents
CMP BYTE PTR [BX+SI],c_CR
JZ EDITON ;If CR correctly placed EDIT is OK
;
; The number of chars in the template is >= the number of chars in buffer or
; there is no CR at the end of the template. This is an inconsistant state
; of affairs. Pretend that the template was empty:
;
NOEDIT:
MOV BL,CH ;Reset buffer
EDITON:
MOV DL,AL
DEC DX ;DL is # of bytes we can put in the buffer
;
; Top level. We begin to read a line in.
;
NEWLIN:
MOV AL,[CARPOS]
MOV [STARTPOS],AL ;Remember position in raw buffer
PUSH SI
MOV DI,OFFSET DOSGROUP:INBUF ;Build the new line here
MOV [INSMODE],CH ;Insert mode off
MOV BH,CH ;No chars from template yet
MOV DH,CH ;No chars to new line yet
invoke $STD_CON_INPUT_NO_ECHO ;Get first char
CMP AL,c_LF ;Linefeed
JNZ GOTCH ;Filter out LF so < works
;
; This is the main loop of reading in a character and processing it.
;
; BH is the index of the next byte in the template
; BL is the length of the template
; DH is the number of bytes in the buffer
; DL is the length of the buffer
;
entry GETCH
invoke $STD_CON_INPUT_NO_ECHO
GOTCH:
;
; Brain-damaged Tim Patterson ignored ^F in case his BIOS did not flush the
; input queue.
;
CMP AL,"F"-"@"
JZ GETCH
;
; If the leading char is the function-key lead byte
;
CMP AL,[ESCCHAR]
JZ ESCape ;change reserved keyword DBM 5-7-87
;
; Rubout and ^H are both destructive backspaces.
;
CMP AL,c_DEL
JZ BACKSPJ
CMP AL,c_BS
JZ BACKSPJ
;
; ^W deletes backward once and then backs up until a letter is before the
; cursor
;
CMP AL,"W" - "@"
; The removal of the comment characters before the jump statement will
; cause ^W to backup a word.
;*** JZ WordDel
NOP
NOP
CMP AL,"U" - "@"
; The removal of the comment characters before the jump statement will
; cause ^U to clear a line.
;*** JZ LineDel
NOP
NOP
;
; CR terminates the line.
;
CMP AL,c_CR
JZ ENDLIN
;
; LF goes to a new line and keeps on reading.
;
CMP AL,c_LF
JZ PHYCRLF
;
; ^X (or ESC) deletes the line and starts over
;
CMP AL,[CANCHAR]
JZ KILNEW
;
; Otherwise, we save the input character.
;
SAVCH:
CMP DH,DL
JAE BUFFUL ; buffer is full.
STOSB
INC DH ; increment count in buffer.
invoke BUFOUT ;Print control chars nicely
CMP BYTE PTR [INSMODE],0
JNZ GETCH ; insertmode => don't advance template
CMP BH,BL
JAE GETCH ; no more characters in template
INC SI ; Skip to next char in template
INC BH ; remember position in template
JMP SHORT GETCH
BACKSPJ: JMP SHORT BACKSP
BUFFUL:
MOV AL,7 ; Bell to signal full buffer
invoke OUTT
JMP SHORT GETCH
ESCape: ;change reserved keyword DBM 5-7-87
transfer OEMFunctionKey ; let the OEM's handle the key dispatch
ENDLIN:
STOSB ; Put the CR in the buffer
invoke OUTT ; Echo it
POP DI ; Get start of user buffer
MOV [DI-1],DH ; Tell user how many bytes
INC DH ; DH is length including CR
COPYNEW:
SaveReg <DS,ES>
RestoreReg <DS,ES> ; XCHG ES,DS
MOV SI,OFFSET DOSGROUP:INBUF
MOV CL,DH ; set up count
REP MOVSB ; Copy final line to user buffer
return
;
; Output a CRLF to the user screen and do NOT store it into the buffer
;
PHYCRLF:
invoke CRLF
JMP GETCH
;
; Delete the previous line
;
LineDel:
OR DH,DH
JZ GetCh
Call BackSpace
JMP LineDel
;
; delete the previous word.
;
WordDel:
WordLoop:
Call BackSpace ; backspace the one spot
OR DH,DH
JZ GetChJ
MOV AL,ES:[DI-1]
cmp al,'0'
jb GetChj
cmp al,'9'
jbe WordLoop
OR AL,20h
CMP AL,'a'
JB GetChJ
CMP AL,'z'
JBE WordLoop
GetChJ:
JMP GetCh
;
; The user wants to throw away what he's typed in and wants to start over. We
; print the backslash and then go to the next line and tab to the correct spot
; to begin the buffered input.
;
entry KILNEW
MOV AL,"\"
invoke OUTT ;Print the CANCEL indicator
POP SI ;Remember start of edit buffer
PUTNEW:
invoke CRLF ;Go to next line on screen
MOV AL,[STARTPOS]
invoke TAB ;Tab over
JMP NEWLIN ;Start over again
;
; Destructively back up one character position
;
entry BackSp
Call BackSpace
JMP GetCh
BackSpace:
OR DH,DH
JZ OLDBAK ;No chars in line, do nothing to line
CALL BACKUP ;Do the backup
MOV AL,ES:[DI] ;Get the deleted char
CMP AL," "
JAE OLDBAK ;Was a normal char
CMP AL,c_HT
JZ BAKTAB ;Was a tab, fix up users display
;; 9/27/86 fix for ctrl-U backspace
CMP AL,"U"-"@" ; ctrl-U is a section symbol not ^U
JZ OLDBAK
CMP AL,"T"-"@" ; ctrl-T is a paragraphs symbol not ^T
JZ OLDBAK
;; 9/27/86 fix for ctrl-U backspace
CALL BACKMES ;Was a control char, zap the '^'
OLDBAK:
CMP BYTE PTR [INSMODE],0
retnz ;In insert mode, done
OR BH,BH
retz ;Not advanced in template, stay where we are
DEC BH ;Go back in template
DEC SI
return
BAKTAB:
PUSH DI
DEC DI ;Back up one char
STD ;Go backward
MOV CL,DH ;Number of chars currently in line
MOV AL," "
PUSH BX
MOV BL,7 ;Max
JCXZ FIGTAB ;At start, do nothing
FNDPOS:
SCASB ;Look back
JNA CHKCNT
CMP BYTE PTR ES:[DI+1],9
JZ HAVTAB ;Found a tab
DEC BL ;Back one char if non tab control char
CHKCNT:
LOOP FNDPOS
FIGTAB:
SUB BL,[STARTPOS]
HAVTAB:
SUB BL,DH
ADD CL,BL
AND CL,7 ;CX has correct number to erase
CLD ;Back to normal
POP BX
POP DI
JZ OLDBAK ;Nothing to erase
TABBAK:
invoke BACKMES
LOOP TABBAK ;Erase correct number of chars
JMP SHORT OLDBAK
BACKUP:
DEC DH ;Back up in line
DEC DI
BACKMES:
MOV AL,c_BS ;Backspace
invoke OUTT
MOV AL," " ;Erase
invoke OUTT
MOV AL,c_BS ;Backspace
JMP OUTT ;Done
;User really wants an ESC character in his line
entry TwoEsc
MOV AL,[ESCCHAR]
JMP SAVCH
;Copy the rest of the template
entry COPYLIN
MOV CL,BL ;Total size of template
SUB CL,BH ;Minus position in template, is number to move
JMP SHORT COPYEACH
entry CopyStr
invoke FINDOLD ;Find the char
JMP SHORT COPYEACH ;Copy up to it
;Copy one char from template to line
entry COPYONE
MOV CL,1
;Copy CX chars from template to line
COPYEACH:
MOV BYTE PTR [INSMODE],0 ;All copies turn off insert mode
CMP DH,DL
JZ GETCH2 ;At end of line, can't do anything
CMP BH,BL
JZ GETCH2 ;At end of template, can't do anything
LODSB
STOSB
invoke BUFOUT
INC BH ;Ahead in template
INC DH ;Ahead in line
LOOP COPYEACH
GETCH2:
JMP GETCH
;Skip one char in template
entry SKIPONE
CMP BH,BL
JZ GETCH2 ;At end of template
INC BH ;Ahead in template
INC SI
JMP GETCH
entry SKIPSTR
invoke FINDOLD ;Find out how far to go
ADD SI,CX ;Go there
ADD BH,CL
JMP GETCH
;Get the next user char, and look ahead in template for a match
;CX indicates how many chars to skip to get there on output
;NOTE: WARNING: If the operation cannot be done, the return
; address is popped off and a jump to GETCH is taken.
; Make sure nothing extra on stack when this routine
; is called!!! (no PUSHes before calling it).
FINDOLD:
invoke $STD_CON_INPUT_NO_ECHO
CMP AL,[ESCCHAR] ; did he type a function key?
JNZ FindSetup ; no, set up for scan
invoke $STD_CON_INPUT_NO_ECHO ; eat next char
JMP NotFnd ; go try again
FindSetup:
MOV CL,BL
SUB CL,BH ;CX is number of chars to end of template
JZ NOTFND ;At end of template
DEC CX ;Cannot point past end, limit search
JZ NOTFND ;If only one char in template, forget it
PUSH ES
PUSH DS
POP ES
PUSH DI
MOV DI,SI ;Template to ES:DI
INC DI
REPNE SCASB ;Look
POP DI
POP ES
JNZ NOTFND ;Didn't find the char
NOT CL ;Turn how far to go into how far we went
ADD CL,BL ;Add size of template
SUB CL,BH ;Subtract current pos, result distance to skip
return
NOTFND:
POP BP ;Chuck return address
JMP GETCH
entry REEDIT
MOV AL,"@" ;Output re-edit character
invoke OUTT
POP DI
PUSH DI
PUSH ES
PUSH DS
invoke COPYNEW ;Copy current line into template
POP DS
POP ES
POP SI
MOV BL,DH ;Size of line is new size template
JMP PUTNEW ;Start over again
entry EXITINS
entry ENTERINS
NOT BYTE PTR [INSMODE]
JMP GETCH
;Put a real live ^Z in the buffer (embedded)
entry CTRLZ
MOV AL,"Z"-"@"
JMP SAVCH
;Output a CRLF
entry CRLF
MOV AL,c_CR
invoke OUTT
MOV AL,c_LF
JMP OUTT
EndProc $STD_CON_STRING_INPUT