📄 history.a86
字号:
found_cmd:
call copy_from_hist ; Copy from history to user buffer
pop di
pop si
; jmp goto_eol ; Display new line.
goto_eol: ; Move the cursor to the end of the
mov cx,dx ! sub cx,si ; displayed line
jcxz goto_e10 ; Already at the EOL
add si,RL_BUFOFF ; Get the Offset in the buffer
call put_string ; Output the sub_string
add di,cx ; Update the local variables
mov si,dx ; and return
goto_e10:
ret
; DI-> Current entry in history buffer
;
copy_from_hist:
or RL_FLAGS,RLF_RECALLED ; remember we have recalled something
and RL_FLAGS,not RLF_DIRTY ; this entry is already in buffers
mov RL_HIST_RECL,di ; update pointer for next time
call find_next_null ; how big is this entry ?
mov cx,di
mov si,RL_HIST_RECL
sub cx,si ; (CX-SI)=No of bytes to copy
cmp cx,RL_MAXLEN ; is the line bigger than our buffer ?
jb copy_from_hist1 ; if so we want to clip it
mov cx,RL_MAXLEN ; to the maximum possible value
copy_from_hist1:
mov dx,cx
push ds
mov ds,RL_HIST_SEG
mov di,RL_BUFOFF
rep movsb ; copy to line buffer
pop ds
call save_line ; save the line
mov cx,RL_SAVMAX ; we can't copy any more
mov RL_SAVPOS,cx
ret
; Some primitives for history buffer handling:
;
; find_free_hist Find the next free entry in the history buffer
; find_next_null Finds the end of the current entry
; find_prev_hist Finds the start of the previous entry
; find_next_hist Finds the start of the next entry
; find_current_hist Finds the start of current entry
;
; Make DI-> next entry of sufficient length for the current cmd buffer
; If we can't fit at the end zero the remainder of the buffer then wrap
; back to the start.
;
find_free_hist:
mov di,RL_HIST_SAVE ; Point at current last entry
push di ; Will DX bytes fit?
add di,dx
cmp di,RL_HIST_SIZE ; Did we run out of buffer?
pop di
jb find_free_hist20
xor ax,ax ; doesn't fit, so zero to end of buffer
find_free_hist10:
push es
mov es,RL_HIST_SEG
stosb ; keep on zeroing
pop es
cmp di,RL_HIST_SIZE
jb find_free_hist10
xor di,di ; wrap back to start of history buffer
find_free_hist20:
ret
; Entry DI-> entry in the history buffer
; Make DI-> next NULL in the history buffer ( end of current entry )
;
find_next_null:
mov cx,RL_HIST_SIZE
sub cx,di ; Calc no of bytes left
xor ax,ax ; Look for next terminator
push es
mov es,RL_HIST_SEG
repnz scasb
dec di ; point at the NUL
pop es
ret
; Entry DI-> entry in the history buffer
; Make DI-> previous entry in the history buffer
; Preserve CX
find_prev_hist:
call find_current_hist ; handle any wrapping
mov ax,di ; AX = entry we want previous for
find_prev_hist10:
push ax ; save current offset
push di ; save initial offset
xchg ax,di ; find next from here until
call find_next_hist ; we get back where we started
xchg ax,di ; AX = current offset
pop di ; recover initial value
pop bx ; recover previous offset
cmp ax,di ; have we wrapped yet ?
je find_prev_hist20 ; yes, BX = previous entry
ja find_prev_hist10 ; we are above target so continue
cmp bx,di ; we are below target - if previous
jae find_prev_hist10 ; was above target we are OK
cmp ax,bx ; if new below previous then we
jnb find_prev_hist10 ; have ERROR wrap, so stop
find_prev_hist20:
mov di,bx ; DI -> Previous entry
ret
find_next_hist:
call find_current_hist ; handle any wrapping
call find_next_null ; point to end of current entry
; jmp find_current_hist ; handle any wrapping
find_current_hist:
; This routine is complicated by the need to handle switchers, where
; our buffers and pointers may get out of step
push es
xor ax,ax
mov es,RL_HIST_SEG ; now work backwards to start of line
find_current_hist10:
cmp di,1 ; are we at the start of the buffer
jb find_current_hist30 ; then don't wrap
std
scasb ; is previous char a NUL ?
cld ; (it should be!)
jne find_current_hist10
inc di ; ES:DI -> 1st char of line
find_current_hist20:
mov cx,RL_HIST_SIZE
sub cx,di ; CX= Remaining no: of bytes in buffer
jbe find_current_hist30
repe scasb ; skip over zero's
jne find_current_hist40
find_current_hist30:
mov di,1 ; wrap to start of buffer
find_current_hist40:
dec di
pop es
ret
del_history_buffers:
;-------------------
; Delete contents of both history buffers
;
mov ax,histbuf1 ; Segment of 1st history buffer
mov cx,histsiz1 ; End of 1st history buffer
call zap_buffer
mov ax,histbuf2 ; Segment of 2nd history buffer
mov cx,histsiz2 ; End of 2nd history buffer
jmps zap_buffer
del_cur_history_buffer:
;----------------------
; Delete contents of the current history buffer
;
mov ax,RL_HIST_SEG ; zero the current buffer
mov cx,RL_HIST_SIZE
zap_buffer:
push es ; zero fill CX bytes at AX:0
push di
mov es,ax
xor ax,ax
mov RL_HIST_RECL,ax
mov RL_HIST_SAVE,ax
xor di,di
rep stosb ; zero fill the buffer
pop di
pop es
call del_line ; then delete current line
jmp save_line
next_word:
mov cx,dx ; Calculate the number of bytes
sub cx,si ; left to scan
jcxz next_w10 ; Skip if at the EOL
push si ; Save the current Index
mov si,di ; Scan from the current location
call match_word ; Get the next word boundary
mov cx,si
sub cx,di ; Calculate the string length
mov si,di ; to be displayed from the current
call put_string ; location and output the data
pop si
add si,cx ; Update the Index and Offset pointers
add di,cx
next_w10:
ret
;
; MATCH_WORD scans the buffer at ES:SI for word boundaries
; and returns to the calling routine whenever it detects such
; a boundary.
;
; On Entry: ES:SI Buffer Address
; CX Maximum No of bytes to Scan
;
; On Exit: ES:SI Next Word Boundary
;
match_word:
call char_info
test ah,CHAR_ALPHAN or CHAR_KANJI
loopnz match_word ; scan the rest of the current word
jcxz match_w30 ; end of word or kanji ?
push dx
match_w10:
mov dx,si
call char_info
test ah,CHAR_ALPHAN or CHAR_KANJI
loopz match_w10
jz match_w20
sub si,dx ; Correct the count in CX
add cx,si ; and return the location of the
mov si,dx ; word boundary
match_w20:
pop dx
match_w30:
ret
prev_word:
mov cx,si ! jcxz match_w30 ; Initialize the count
push dx ! push si ! push di
mov si,RL_BUFOFF ; Scan from the begining of the buffer
mov dx,si ; keeping the last match in DX
prev_w10:
call match_word ; Find the next word boundary
jcxz prev_w15 ; Stop when we get to the current offset
mov dx,si ; Save current location
jmps prev_w10 ; and repeat
prev_w15:
jmp prev_w20
del_bol: ; Delete to the begining of the line
or si,si ! jz del_bol10 ; Ignore if at the begining
or dx,dx ! jz del_bol10 ; Or the line is empty
push di ; Save the current index
call goto_bol ; Move to the start of the line
pop cx ; Restore the current offset
jmp deln_w10 ; and jump to common code
del_bol10:
ret
deln_word:
mov cx,dx ; Calculate the number of bytes
sub cx,si ; left to scan
jcxz del_bol10 ; Skip if at the EOL
push si ; Save the current Index
mov si,di ; Scan from the current location
call match_word ; Get the next word boundary
mov cx,si
pop si
jmp deln_w10
PCMODE_DATA DSEG WORD
extrn @hist_flg:byte ; To select between histbufs 1 or 2
GLOBAL_DATA dseg word
extrn histbuf1:word, histsiz1:word, histbuf2:word, histsiz2:word
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -