home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
pcmagazi
/
1990
/
16
/
history.asm
< prev
next >
Wrap
Assembly Source File
|
1990-04-29
|
9KB
|
364 lines
; HISTORY.ASM
; (c) 1989, 1990 Ashok P. Nadkarni
;
; This module implements the history feature of the cmdedit program.
INCLUDE common.inc
INCLUDE buffers.inc
PUBLIC hist_top
PUBLIC hist_init
PUBLIC hist_fwd
PUBLIC hist_back
PUBLIC hist_fwd_match
PUBLIC hist_bck_match
PUBLIC remember
PUBLIC hist_type
PUBLIC execute_auto_recall
PUBLIC execute_rsthist
PUBLIC hist_ptr
PUBLIC history
CSEG SEGMENT PARA PUBLIC 'CODE'
EXTRN linebuf:BYTE ;line buffer
EXTRN lastchar:WORD
EXTRN dot:WORD ;current position in line buffer
; The history stack is maintained as a string stack using the functions in
; the string stack library. The top and bottom of the stack are always
; zero length strings (the bottom is always a zero length sentinel
; implemented by the string stack package but the top is explicitly
; maintained by the history code.
history $string_stack 2 DUP (<>) ;Buffer descriptors
hist_ptr DW ? ;Ptr to current buffer descriptor
DGROUP GROUP CSEG
EXTRN bell:PROC
EXTRN set_disp_marks:PROC
EXTRN erase_to_dot:PROC
ASSUME CS:DGROUP,DS:DGROUP,ES:DGROUP,SS:DGROUP
;+
; FUNCTION : hist_init
;
; Initializes the various data structures associated with the
; command history buffers. CALLER MUST ENSURE PASSED ADDRESSES ARE VALID
; AND BUFFER IS LARGE ENOUGH.
;
; Parameters:
; AX - length of buffer in bytes
; BX - address of buffer
; CX - 0 if DOS buffer, any other value if application buffer
;
; Returns:
; Nothing.
; Registers destroyed : BX,CX
;-
hist_init proc near
push bx
mov bx,offset DGROUP:history ;bx := address of buffer descriptors
jcxz @hist_init_1 ;if DOS, bx OK
add bx,TYPE $string_stack ;else point to application descriptor
@hist_init_1:
xchg ax,cx ;CX = buffer size
pop ax ;AX = Buffer address
;BX points to appropriate descriptor
call near ptr strstk_init ;Initialize buffer and descriptor
xor al,al ;Push a zero length string onto stack
mov cl,1 ;Force onto stack
call near ptr strstk_push ;Assumes no errors
ret
hist_init endp
;+
; FUNCTION : execute_rsthist
execute_rsthist proc near
mov bx,offset DGROUP:history ;bx := address of buffer descriptors
jcxz @execute_rsthist_1 ;if DOS, bx OK
add bx,TYPE $string_stack ;else point to application descriptor
@execute_rsthist_1:
call near ptr strstk_reset ;Initialize buffer and descriptor
xor al,al ;Push a zero length string onto stack
mov cl,1 ;Force onto stack
call near ptr strstk_push ;Assumes no errors
ret
execute_rsthist endp
;+
; FUNCTION : hist_type
;
; Sets the hist_ptr global to point at the descriptor for the
; current caller (DOS or application).
;
; Parameters:
; CX = 0 if DOS, anything else for application
;
; Returns:
; Nothing.
; Registers destroyed : BX
;-
hist_type proc near
mov bx,offset DGROUP:history ;address of first descriptor
mov hist_ptr,bx
ret
hist_type endp
;+
; FUNCTION : hist_top
;
; Resets the history pointer to the null string at top of history stack.
; The line buffer itslef is NOT changed.
; Parameters:
; None.
;
; Returns:
; Nothing.
; Registers destroyed: BX
;-
hist_top proc near
mov bx,hist_ptr ;Point to current descriptor
call near ptr strstk_settop ;Set to top of history stack.
ret
hist_top endp
;+
; FUNCTION : hist_back
;
; Gets the previous history line (if there is one) and stores it
; in the line buffer. Also makes it the current line.
;
; Parameters:
; None.
;
; Returns:
; Nothing.
; Registers destroyed: AX,BX,CX
;-
hist_back proc near
mov dot,offset DGROUP:linebuf
jmp hist_bck_match ;Will return to caller
hist_back endp
;+
; FUNCTION : hist_fwd
;
; Gets the next history line (if there is one) and stores it
; in the line buffer. Also makes it the current line.
;
; Parameters:
; None.
;
; Returns:
; Nothing.
; Registers destroyed :
;-
hist_fwd proc near
mov dot,offset DGROUP:linebuf
jmp hist_fwd_match ;Will return to caller
hist_fwd endp
;+
;
; FUNCTION : hist_copy
;
; Copies the current history line into the line buffer. The dot
; is set to the beginning of the line.
;
; Parameters:
; BX = points to the beginning of a line in the history buffer.
;
; Returns:
; Nothing.
;
; Registers destroyed:
;-
hist_copy proc near
mov bx,hist_ptr ;Current descriptor
mov ax,offset DGROUP:linebuf ;the history line storage
push ax ;Remember
mov dot,ax ;Cursor will be at the beginning of line
xchg ax,dx ;dx->first char in line (parameter)
mov ax,lastchar ;ax->upper limit (parameter)
call near ptr set_disp_marks ;Indicate changed range
;No registers destroyed
mov ax,dx ;Restore beginning of line
sub cx,LINEBUF_SIZE ;cx<-max length of line
push cx ;Save it
call near ptr strstk_copy ;Copy history line into linebuf
;AX == length of history string
pop cx ;
jnc @hist_copy_90 ;Jump if no error from strstk_copy
call near ptr bell ;History line too long for buffer
mov ax,cx ;Number of bytes = max length of line
@hist_copy_90:
pop dx ;dx->beginning of line
add ax,dx ;ax->end
mov lastchar,ax ;Update end of line
call near ptr set_disp_marks ;Indicate changed range
;No registers destroyed
ret
hist_copy endp
;+
;
; FUNCTION : remember
;
; Saves the line buffer in the history area. If the line already
; exists, it is moved to the top of the stack.
;
; Parameters:
; None.
;
; Returns:
; Nothing.
;
; Registers destroyed:
; AX,BX,CX,DX
;-
remember proc near
mov bx,hist_ptr ;Descriptor
call near ptr strstk_settop ;Reset stack pointer
mov ax,offset DGROUP:linebuf ;AX->line to be stored
mov cx,lastchar
sub cx,ax ;CX<-length of line
call near ptr strstk_bck_find ;Look for it in history
; buffer. Note that if it is a
; null string, the sentinel at
; top of the stack is not found
; which is at it should be.
jc @remember_10 ;Not in stack
call near ptr strstk_kill ;If found delete it from stack
@remember_10:
call near ptr strstk_settop ;Point to sentinel at top of stack
call near ptr strstk_kill ;Delete it
mov dx,offset DGROUP:linebuf ;String to be remembered
mov ax,lastchar ;Length of string
sub ax,dx ;AX(AL)<-length of string
mov cl,1 ;Force the push
call near ptr strstk_push ;ignore success/fail status
xor ax,ax ;Zero length sentinel
mov cl,1
call near ptr strstk_push ;Push it
ret
remember endp
;+
;
; FUNCTION : hist_fwd_match, hist_bck_match
;
; Looks fwd/back thru the history buffer starting from the current
; history location looking for a line whose first n chracters match
; the n characters before the current position in the line buffer.
;
; Parameters:
; None.
;
; Returns:
; CF = 0 if match found
; 1 if no match
;
; Registers destroyed:
;-
hist_match proc near
hist_fwd_match LABEL near
mov dx,offset DGROUP:strstk_fwd_match
jmp short @hist_match_10
hist_bck_match label near
mov dx,offset DGROUP:strstk_bck_match
@hist_match_10:
mov bx,hist_ptr ;Descriptor address
mov ax,offset DGROUP:linebuf ;start of pattern
mov cx,dot ;Current position in linebuffer
sub cx,ax ;Number of chars to match
push cx ;Save
push ax
call dx ;Will set CF if no match, else sets
; 'current' to matched string
pushf ;Remember flags
jc @hist_match_20 ;No match
call near ptr hist_copy ;Copy and display the history line
;Now reset it to original position
@hist_match_20:
popf ;Restore flags
pop ax ;Line address
pop cx ;Restore count
pushf ;Save flags
add ax,cx ;AX->dot
mov dot,ax
popf ;Restore flags
jnc @hist_match_99 ;If match was found, exit
mov ax,lastchar ;AX->end-of-line
call erase_to_dot ;Else delete remaining chars in the
; line (chars between AX and dot)
stc ;Indicate no match
@hist_match_99:
ret
hist_match endp
;+
; FUNCTION : execute_auto_recall
;
; This function looks backward through the history buffer for a
; line with a prefix that matches the characters to the left of
; the dot. The search begins with the CURRENT history line. ie.
; if the current history line has a matching prefix, the current
; pointer is not changed. If no match is found, the history stack
; is reset.
;
; Parameters:
; None.
;
; Returns:
; CF = 0 if match found
; 1 if no match
; Register(s) destroyed:
; AX,BX,CX,DX
;-
execute_auto_recall proc near
mov bx,hist_ptr ;BX->current history stack descriptor
mov ax,offset DGROUP:linebuf ;AX->pattern
mov cx,dot
sub cx,ax ;CX<-length of pattern
call near ptr strstk_prefix ;Current history line matches?
jne @execute_auto_recall_50 ;No
clc ;Yes, current line matches
jmp short @execute_auto_recall_99
@execute_auto_recall_50:
call near ptr hist_bck_match ;Search backward
jnc @execute_auto_recall_99 ;Found a match
; No match, reset history stack pointer
mov bx,hist_ptr ;BX->current history stack descriptor
call near ptr hist_top ;Reset history stack
stc ;Indicate no match
@execute_auto_recall_99:
ret
execute_auto_recall endp
CSEG ENDS
END