Category : C Source Code
Archive   : CEXPRESS.ZIP
Filename : EDITLINE.ASM
; unsigned char *return_string,col,row,color,max_len,st,est,ext,ch_case;
EXTRN _memory_model:byte
EXTRN _error_code:byte
EXTRN _beep_on:byte
_TEXT SEGMENT BYTE PUBLIC 'CODE'
ASSUME CS:_TEXT
PUBLIC _edit_line
_edit_line proc near
push bp ;
mov bp,sp ;
push di ;
push si ;
cmp _memory_model,0 ;near or far?
jle begin ;jump if near
inc bp ;else add 2 to BP
inc bp ;
begin: push ds ;
jmp A5 ;jump over data
EscapeCode db ? ;holds escape code or zero
ExtendedCode db ? ;same
DeleteCase db 0 ;flags that Del or Backspc key hit
beepon db ? ;keeps _beep_on parameter
LeftLimit db ? ;left cursor limit on screen
RightLimit db ? ;right cursor limit
Case db ? ;flags kind of case change
CaseChange db ? ;flags whether case change
Max_Len db ? ;holds MaxLen parameter
StringEnd db ? ;col of last char of string
errorcode db ? ;holds return code
StringPos db ? ;pts to string variable = cursor pos
Beep PROC
push dx ;save cursor ptr
cmp cs:beepon,0 ;beep on?
jz A1 ;jump if not
mov dl,7 ;beep char
mov ah,2 ;DOS function to write char
int 21h ;make the beep
A1: pop dx ;
ret
Beep ENDP
DisplayChars PROC ;writes changed char string on screen
or di,di ;zero chars to write?
jz A3 ;
A2: mov ah,2 ;function to set cursor
mov bh,0 ;page
int 10h ;
mov al,[si] ;get char
mov bl,[bp+10] ;attribute
mov bh,0 ;page
mov cx,1 ;number chars to write
mov ah,9 ;function number
int 10h ;
inc si ;forward string ptr
inc dl ;forward cursor ptr
dec di ;loop till all chars shifted
jnz A2 ;
cmp cs:DeleteCase,1 ;
jne A4 ;
A3: mov cs:DeleteCase,0 ;
mov byte ptr[si],' ' ;
inc di ;through loop once more
jmp short A2 ;go write space at end of string
A4: ret
DisplayChars ENDP
A5: mov bl,_beep_on ;get _beep_on value
mov cs:beepon,bl ;keep in local variable
cmp _memory_model,2 ;data near or far?
jb L1 ;
lds si,dword ptr[bp+4] ;DS:SI pts to Strg
les di,dword ptr[bp+4] ;ES:DI too
inc bp ;add 2 to BP since dword ptr
inc bp ;
jmp short L2 ;
L1: mov ax,ds ;ES = DS
mov es,ax ;
mov si,[bp+4] ;
mov di,si ;
L2: cmp byte ptr[si],0 ;test for null string
je L4 ;if not null, change to Pascal string
mov cx,255 ;max string length
sub al,al ;seek terminating null
repne scasb ;
dec di ;point to null
mov cx,di ;calculate number bytes
sub cx,si ;
mov ah,cl ;keep string length
dec di ;point to last ptr of string
L3: mov al,es:[di] ;shift the chars
mov es:[di+1],al ;
dec di ;
loop L3 ;
mov [si],ah ;
mov di,si ;reset DI
L4: mov cs:errorcode,0 ;default return code
mov cs:ExtendedCode,0 ;
mov cs:EscapeCode,0 ;
mov al,[bp+18] ;Ext
mov bl,[bp+16] ;Esc
cmp al,0 ;escape char is extended code?
jz A6 ;
mov cs:EscapeCode,bl ;ASCII code
jmp short A7 ;
A6: mov cs:ExtendedCode,bl ;
;---Figure out character case:
A7: mov al,[bp+20] ;get CharCase
mov cs:CaseChange,0 ;flags no case change
cmp al,97 ;lower case?
jb A8 ;jump if not
sub al,32 ;make uppercase
A8: cmp al,'U' ;specify uppercase?
jne A9 ;
mov cs:Case,1 ;uppercase
inc cs:CaseChange ;1 = case change made
jmp short A0 ;
A9: cmp al,'L' ;specify lowercase?
jne A0 ;
mov cs:Case,0 ;lowercase
inc cs:CaseChange ;1 = case change made
;---Initialize parameters:
A0: mov dh,[bp+8] ;get Row
or dh,dh ;zero?
jz B1 ;quit if so
dec dh ;count from zero
mov dl,[bp+6] ;get Col
or dl,dl ;zero?
jz B1 ;quit if so
dec dl ;count from zero
mov cs:LeftLimit,dl ;set LeftLimit
mov al,dl ;copy
mov ah,[bp+12] ;get MaxLen
mov cs:Max_Len,ah ;copy
or ah,ah ;zero?
jnz B2 ;jump ahead if not
B1: jmp F4 ;quit
B2: add al,ah ;figure RightLimit
dec al ;
mov cs:RightLimit,al ;
mov al,[si] ;get string length
cmp al,cs:max_len ;
jna B3 ;quit if too long
mov cs:errorcode,1 ;1 = string too long
jmp short B1 ;quit
B3: mov bl,al ;copy strg len
add bl,dl ;add Col offset
dec bl ;count from zero
mov cs:StringEnd,bl ;save col pos of end of string
mov bl,[bp+14] ;get cursor start pos
inc bl ;adjust to count from 1
mov cs:StringPos,bl ;save
or bl,bl ;zero?
jz B5 ;then assume 1
cmp bl,al ;start pos in string?
jna B4 ;jump if so
mov bl,al ;else set to char after end of string
inc bl ;
mov cs:StringPos,bl ;
B4: dec bl ;count from zero
add dl,bl ;add to start col
cmp dl,cs:RightLimit ;cursor in field?
ja B1 ;out or range error if not
B5: mov ah,2 ;function to set cursor
mov bh,0 ;page number
int 10h ;set the cursor
;---Ready to go, get keystroke:
B6: mov di,si ;Ctrl-cursor moves change DI
mov ah,7 ;DOS function to get keystroke
int 21h ;
or al,al ;extended code?
jz B7 ;
jmp D6 ;jump ahead if not extended
B7: mov ah,7 ;get extended code
int 21h ;
mov bl,cs:ExtendedCode ;test for escape char
or bl,bl ;zero = escape not extended code
jz B8 ;
cmp bl,al ;the code?
jne B8 ;
mov cs:errorcode,2 ;
jmp F4 ;quit
B8: cmp al,75 ;cursor-left
jne C1 ;
cmp dl,cs:LeftLimit ;cursor against left margin?
je B0 ;
dec dl ;dec cursor ptr
dec cs:StringPos ;dec string ptr
B9: mov ah,2 ;func to set cursor
mov bh,0 ;page
int 10h ;move cursor
jmp short B6 ;
B0: call beep ;
jmp short B6 ;go get next key
C1: cmp al,77 ;cursor-right
jne C3 ;
cmp dl,cs:RightLimit ;cursor against right margin?
je B0 ;beep if so
mov al,cs:StringEnd ;don't let go beyond space after last char
cmp al,255 ;can't move cursor if null string
je B0 ;
cmp dl,al ;
ja B0 ;
C2: inc dl ;inc cursor ptr
inc cs:StringPos ;inc string ptr
jmp short B9 ;go move cursor
C3: cmp al,115 ;Ctrl cursor-left
jne C7 ;
cmp dl,cs:LeftLimit ;cursor against left margin?
je B0 ;
sub cx,cx ;
mov cl,cs:StringPos ;offset of cursor in string
dec cx ;adjust
std ;will scan backwards
add di,cx ;
mov al,' ' ;seek space char
cmp byte ptr es:[di],' ' ;at first char of word?
je C5 ;jump if so
C4: repne scasb ;
jnz C6 ;jump if not found
add cx,2 ;new position
mov cs:StringPos,cl ;set string ptr
mov dl,cs:LeftLimit ;
add dl,cl ;
dec dl ;
jmp short B9 ;go set cursor
C5: mov al,' ' ;
repe scasb ;seek first non-space char
jz C6 ;jump if not found
jmp short C4 ;now find start of next word
C6: mov cs:StringPos,1 ;
mov dl,cs:LeftLimit ;
jmp short B9 ;
C7: cmp al,116 ;Ctrl cursor-right
jne D3 ;
cmp dl,cs:RightLimit ;cursor against left margin?
je B0 ;
mov al,cs:StringEnd ;cursor at last char?
cmp dl,al ;
jne C8 ;
C8: inc al ;
cmp dl,al ;
jne C9 ;
jmp B0 ;
C9: sub cx,cx ;
mov cl,es:[di] ;get string length
sub ax,ax ;figure number chars to scan
mov al,cs:StringPos ;
sub cl,al ;
mov bx,cx ;keep copy
cld ;scan forward
add di,ax ;set string ptr
inc di ;
mov al,' ' ;seek space char
cmp byte ptr es:[di],' ' ;at space char?
jne C0 ;
cmp byte ptr es:[di-1],' ' ;prior char a space?
je C9B ;if not, run through all spaces
jmp C2 ;otherwise, just forward cursor 1 col
C9B: mov al,' ' ;
repe scasb ;seek first non-space char
jz D1 ;jump if not found
C0: repne scasb ;
jnz D1 ;jump if not found
sub bx,cx ;number chars traversed
add dl,bl ;forward cursor ptr
add cs:StringPos,bl ;forward string ptr
jmp B9 ;go set cursor
D1: mov al,[si] ;place cursor at end of string
cmp al,cs:Max_Len ;
je D2 ;
inc al ;
D2: mov cs:StringPos,al ;
mov dl,cs:LeftLimit ;figure cursor position
add dl,al ;
dec dl ;
jmp B9 ;
D3: cmp al,83 ;Del key?
jne D5 ;
mov al,[si] ;is there a char above the cursor?
cmp cs:StringPos,al ;
jna D4 ;jump if so
call beep ;beep
jmp B6 ;go get next key
D4: jmp E2 ;go join Backspace routine
D5: jmp B6 ;go get next key
D6: mov bl,cs:EscapeCode ;test for escape char
or bl,bl ;zero = escape not extended code
jz D7 ;
cmp bl,al ;the code?
jne D7 ;
mov cs:errorcode,2 ;
jmp F4 ;quit
;---Make case change if required:
D7: cmp cs:CaseChange,0 ;case change required?
je D9 ;jump ahead if not
cmp cs:Case,0 ;all lowercase?
jne D8 ;jump if not
cmp al,65 ;see if uppercase
jb D9 ;
cmp al,90 ;
ja D9 ;
add al,32 ;convert
jmp short D9 ;
D8: cmp al,97 ;see if lowercase
jb D9 ;
cmp al,122 ;
ja D9 ;
sub al,32 ;convert
;---Intercept CARRIAGE RETURN:
D9: cmp al,13 ;Carriage Return?
jne D0 ;jump if not
jmp F4 ;go quit
;---Intercept BACKSPACE:
D0: cmp al,8 ;backspace?
jne E6 ;jump if not
cmp dl,cs:LeftLimit ;cursor at start of line?
jne E1 ;jump if room for backspace
call beep ;else beep
jmp short E5 ;
E1: dec dl ;move cursor ptr to prior char
dec cs:StringPos ;dec string ptr
;---For DEL or backspace, remove char from string:
E2: sub ax,ax ;pt SI to char to be removed
mov cx,ax ;
mov cl,[si] ;string length
mov al,cs:StringPos ;
sub cx,ax ;number characters to shift
or cx,cx ;
jz E4 ;
add si,ax ;
E3: mov al,[si+1] ;get next char
mov [si],al ;shift
inc si ;next
loop E3 ;
mov si,di ;move SI back to descriptor
E4: dec byte ptr[si] ;dec descriptor
;---Write the new string:
mov cs:DeleteCase,1 ;flag that deleting char
sub ax,ax ;clear AX
mov al,[si] ;get string length
sub al,cs:StringPos ;figure length
inc al ;number chars to display
sub cx,cx ;
mov cl,cs:StringPos ;
add si,cx ;
push di ;need DI as counter
mov di,ax ;
push dx ;save cursor position
call DisplayChars ;
dec cs:StringEnd ;
pop dx ;
mov ah,2 ;set cursor
mov bh,0 ;
int 10h ;
pop di ;start of string ptr
mov si,di ;
E5: jmp B6 ;go get next key
E6: cmp al,31 ;reject all other control codes
ja E7 ;
call beep ;
jmp B6 ;go get next key
;---Add a character to the data string:
E7: mov bl,[si] ;get string length
cmp bl,cs:Max_len ;in range?
jne E8 ;jump ahead if OK
call Beep ;go beep
jmp B6 ;go get next keystroke
E8: push ax ;save input char
sub ax,ax ;point SI to end of string
mov al,[si] ;
or ax,ax ;if null, point to first byte
jnz E9 ;
inc ax ;
E9: add si,ax ;
mov cl,cs:StringEnd ;does cursor follow last char?
cmp dl,cl ;
jna E0 ;jump if not
cmp dl,cs:LeftLimit ;special case when starting will null strg
jne F2 ;
E0: sub cl,dl ;number chars
inc cl ; to shift
sub ch,ch ;extend to word
or cx,cx ;test for zero length
jnz F1 ;jump ahead if nonzero
dec si ;pull back pointer
jmp short F2 ;skip character shift
F1: mov al,[si] ;shift the string segment
mov [si+1],al ;
dec si ;
loop F1 ;
F2: pop ax ;fetch input char
inc si ;back to cursor position
mov [si],al ;insert new char
mov si,di ;si back to start of string
inc byte ptr[si] ;inc string descriptor
inc cs:StringEnd ;forward end-of-strg col ptr
inc cs:StringPos ;forward string position ptr
inc dl ;forward cursor ptr
;---Now rewrite portion of string on display:
mov cs:DeleteCase,0 ;flag DisplayChars that not Del case
sub cx,cx ;figure offset in data string
mov bx,cx ;
mov cl,[si] ;get string length
mov bl,cs:StringPos ;
sub cx,bx ;equals number chars to write - 2
add cx,2 ;
add si,bx ;set string ptr
dec si ;
push di ;need DI as counter
mov di,cx ;
push dx ;save cursor position
dec dl ;pull back cursor
call DisplayChars ;go write chars
pop dx ;restore cursor pos
cmp dl,cs:RightLimit ;don't push cursor beyond MaxLen
jna F3 ;
dec dl ;
dec cs:StringPos ;
F3: mov ah,2 ;
mov bh,0 ;
int 10h ;
pop di ;
mov si,di ;point SI back to string descriptor
jmp B6 ;go do next keystroke
;---Exit code:
F4: mov al,cs:errorcode ;set errorcode
pop ds ;
mov _error_code,al ;
sub cx,cx ;change to C string
mov cl,[si] ;get string length
jcxz F6 ;quit if null
F5: inc si ;
mov al,[si] ;
mov [si-1],al ;
loop F5 ;
mov byte ptr [si],0 ;null terminator
F6: pop si ;
pop di ;
pop bp ;
cmp _memory_model,0 ;quit
jle quit ;
db 0CBh ;RET far
quit: ret ;RET near
_edit_line ENDP
_TEXT ENDS
END
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/