home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Shareware - Software Farm 2
/
wosw_2.zip
/
wosw_2
/
CPROG
/
CEXPRESS.ZIP
/
KEYBOARD.ASM
/
EDITLINE.ASM
< prev
next >
Wrap
Assembly Source File
|
1989-05-03
|
13KB
|
462 lines
;void edit_line(return_string,col,row,color,max_len,st,esc,ext,ch_case);
; 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