📄 cmdline.a86
字号:
; File : $CMDLINE.A86$
;
; Description :
;
; Original Author : DIGITAL RESEARCH
;
; Last Edited By : $CALDERA$
;
;-----------------------------------------------------------------------;
; Copyright Work of Caldera, Inc. All Rights Reserved.
;
; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
; CIVIL LIABILITY.
;-----------------------------------------------------------------------;
;
; *** Current Edit History ***
; *** End of Current Edit History ***
;
; $Log$
; CMDLINE.A86 1.8 93/03/25 15:06:03
; tweak console block output
; ENDLOG
;
; DOSPLUS Command Line Editor Routines
;
include pcmode.equ
include i:msdos.equ
include i:char.def
include i:cmdline.equ
include i:reqhdr.equ
include i:driver.equ
PCM_CODE CSEG BYTE
public read_line, edit_size
extrn dbcs_lead:near
extrn cmdline_read:near
extrn raw_read:near
extrn cooked_write:near
extrn get_dseg:near
extrn device_driver:near
; WARNING - the following routines are to support history buffers
; As these are optional we muset NEVER call these routines unless
; the HISTORY_ON bit is set in @hist_flag.
extrn init_history:near
extrn save_history:near
extrn prev_cmd:near
extrn next_cmd:near
extrn match_cmd:near
extrn search_cmd:near
extrn match_word:near
extrn del_cur_history_buffer:near
extrn del_history_buffers:near
extrn goto_eol:near
extrn next_word:near
extrn prev_word:near
extrn del_bol:near
extrn deln_word:near
; The following are public for HISTORY.PCM
public next_char, save_line
public space_out, bs_out, put_string
public goto_bol
public del_eol, del_line
public char_info
public prev_w20
public deln_w10
; READ_LINE will read an editted line from the handle passed in BX
; into a buffer with the following format:-
;
; BYTE Maximum String Length
; BYTE Current String Length
; BYTE(s) String Buffer
;
; On Entry:-
; BX Input Handle
; CX Output Handle
; ES:DX Buffer Address
;
; On Exit:-
; String input by user
;
; The following conventions apply for the READ_LINE function
;
; ES Buffer segment
; SI Current cursor location in buffer (Index)
; DX Last Character in Buffer (Index)
;
DISABLE equ 80h ; Disable when advanced editing is off.
DISABLE_MASK equ 8000h
ESC_CODE equ 01h ; Scan code must be preceeded by escape byte.
NESC_CODE equ 00h ; No lead zero needed.
read_line:
push bp ; Save the Stack Frame Pointer
mov bp,sp ; Intialise it to the top of the
sub sp,RL_LENGTH ; READ_LINE control block and reserve
; control block
mov RL_INPUT,bx ; Initialize the INPUT Handle
mov RL_OUTPUT,cx ; the OUTPUT Handle
inc dx ! inc dx ; Skip max and Returned Length
mov RL_BUFOFF,dx ; and save the buffer offset
mov RL_BUFSEG,es ; and segment
xor ax,ax ; now we zero
mov RL_SAVPOS,ax ; both position in it
mov RL_SAVMAX,ax ; and it's size
mov al,column
mov RL_INICOL,ax ; save initial column
mov ax,cle_state ; use to set initial editing state
and ax,not (RLF_MATCH+RLF_DIRTY+RLF_RECALLED)
mov RL_FLAGS,ax ; save in flags
test ax,RLF_ENHANCED
jz read_line10
call init_history ; setup the history buffers
jmps read_line20
read_line10:
and RL_FLAGS,not RLF_INS ; clear insert mode
read_line20:
mov di,dx ; di -> buffer
xor bx,bx
or bl,es:byte ptr -2[di] ; Get the Maximum number of chars
mov RL_MAXLEN,bx ; and save for later
jnz read_line30 ; make sure some chars are requested
jmps ret_string10 ; if no chars just return
ret_string:
pop ax ; Remove local return address
mov ax,RL_FLAGS ; get command line editor state
mov cle_state,ax ; save state for next time
mov di,RL_BUFOFF ; Get the buffer Offset
mov es:byte ptr -1[di],dl ; Return the number of characters
push dx ; Save length of entry
add di,dx ; Point to the end of the buffer
mov al,CR
stosb ; Save CR
call write_char ; Print a CR and return to the user
pop dx
test RL_FLAGS,RLF_ENHANCED ; Do not add to history if in
jz ret_string10 ; compatibility mode
call save_history ; Save state of history buffer
ret_string10:
mov sp,bp ; Remove READ_LINE control Block
pop bp ; Restore BP and return to the caller
ret
read_line30:
xor si,si ; Currently at start of buffer
mov dx,si ; with an empty buffer.
xor bx,bx
or bl,es:byte ptr -1[di] ; Check if the buffer contains any
jz read_line40 ; data which is terminated by a CR
cmp es:byte ptr [bx+di],CR
jnz read_line40
mov dx,bx
read_line40:
call save_line ; Update Save Buffer variables
mov dx,si
;
; This is out main command loop - we get a character and try to match it
; with a command in our edit_table. If History is on we look at commands
; with the DISABLED bit set ie. enhanced commands.
; It a match isn't found we insert the character in the buffer, and optionally
; try to match with previous lines in the history buffer.
;
read_line_loop:
and RL_FLAGS,not RLF_KANJI ; initial flags
call get_char ; read the first character (AH Esc Flg)
mov cx,edit_size ; now scan the control table looking
mov bx,offset edit_table ; for a match
read_ll_next_cmd:
and ax,not DISABLE_MASK ; assume normal function
test RL_FLAGS,RLF_ENHANCED ; compatibilty required? then it
jz read_ll10 ; has to be a normal function
test EDIT_CNTRL,DISABLE_MASK ; history enabled, so we make
jz read_ll10 ; our code match DISABLE mask
or ax,DISABLE_MASK ; of table entry
read_ll10:
cmp ax,EDIT_CNTRL ; check for a match (Escape Flag
je read_ll_found_cmd ; and the character)
add bx,EDIT_LEN ; Add the entry length
loop read_ll_next_cmd ; and scan the whole table
; We have failed to find a command so insert char in buffer
test ah,ESC_CODE ; Ignore non-matched escaped keys
jnz read_line_loop
call save_char ; not an command so save the character
or RL_FLAGS,RLF_DIRTY ; and remember we have something new
; Are we in search mode ?
test RL_FLAGS,RLF_ENHANCED ; Compatibilty required?
jz read_line_loop
test RL_FLAGS,RLF_SEARCH+RLF_MATCH
jz read_line_loop ; is searching/matching on ?
push si ; save current offset
call search_cmd
pop ax ; this is our target offset
read_ll20:
cmp ax,si ; are we there yet ?
jae read_line_loop
push ax ; no, keep rewinding cursor
call prev_char ; until we reach position
pop ax ; before we tried to match
jmps read_ll20
read_ll_found_cmd: ; get the address of the corresponding
mov cx,EDIT_FUNC ; function from the table
call cx ; execute the correct function
jmps read_line_loop ; and go back for next character
eject
;
; the SAVE_CHAR routine will write the character in AL into
; the buffer in memory and then update the screen image. The
; RLF_INS flag is used to determine if INSERT is active.
;
save_c10:
ret
save_char:
cmp ah,TRUE ; Ignore any un-matched escape
jz save_c10 ; sequences
call save_kanji ; Test if AL is a Kanji Character
; and setup up the parameter blocks
; for the INTSAVE_CHAR routine
;
; INTSAVE_CHAR is the internal entry point to the Character Save
; routine. It assumes the following:-
;
; On Entry:- AX(AL) Contains the character
; CX the new character length in bytes
; RLF_KANJI Flag is set for a Kanji Character
; RL_KANJI Contains the kanji charater
;
intsave_char:
mov bx,cx
test RL_FLAGS,RLF_INS ; Overwrite the character in the
jnz save_c50 ; buffer currently
add bx,si ; Add the current index to the character
cmp bx,RL_MAXLEN ; size and compare against the buffer len
jae bell_char ; Full ? Yes Ring dat Bell !
cmp dx,si ; Are we at the end of the line
jnz intsave_c10 ; No so check character types
push ax ! push cx
call skip_one_char ; Skip the coresponding character in
pop cx ! pop ax ; the save buffer
jmps simple_save
intsave_c10:
push ax ; Save the Input Character
call char_type ; Get the character type
mov bx,ax ; and save in BX
mov al,es:[di] ; get the byte to be replaced
call char_type ; and get its type
and ah,CHAR_SIZE ; Mask the Character SIZE attributes
and bh,CHAR_SIZE ; and check both storage and display
; sizes are the same for old and new
cmp ah,bh ; and do simple save if the character
pop ax ; Restore the input character to AX(AL)
jnz save_c30 ; type match
sub dx,cx ; Character overwritten so prevent
; Max Index being incremented
simple_save:
add si,cx ; Assume at the EOL
add dx,cx
stosb ; Save the character typed
test RL_FLAGS,RLF_KANJI ; is this a Kanji character
jz simple_s10 ; No so just output 1 character
call put_char ; and echo it to the user
mov al,byte ptr RL_KANJI+1 ; Get the high byte of the Kanji
stosb ; character save and then display it.
simple_s10:
jmp put_char
; ret
;
; The SAVE_C30 function supports the Complex overwrite conditions
; where the size of the character in memory or on the display do not
; match with those of the present incumbent. eg a SPACE character
; overwriting a TAB or a KANJI character overwriting a SPACE.
;
; To minimize the complexity of the code the character to be
; overwritten is deleted and the new character then inserted.
; This is not an optimal solution but drastically reduces the
; amount of code required.
;
save_c30:
push ax ! push cx
call deln_char
pop cx ! pop ax
cmp dx,si
jz simple_save
or RL_FLAGS,RLF_INS
call save_c50
and RL_FLAGS,not RLF_INS
ret
bell_char:
mov al,BELL
jmp write_char
;
; This code is called when INSERT mode is active and a
; character (possibly Kanji) is to be inserted in the buffer
;
; On Entry:- CX the new character length in bytes
;
save_c50:
mov bx,cx ; Save new character length
add cx,dx ; Add the current max to the character
cmp cx,RL_MAXLEN ; size and compare against the buffer len
jae bell_char ; Full ? Yes Ring dat Bell !
mov cx,bx ; Restore Character Length
cmp dx,si ; If we are at the end of the line
je simple_save ; Use the simple save code
;
; Create space in the current buffer for the new character
;
push ds
push si ! push di
mov cx,dx ! sub cx,si ; CX -> Number of bytes to move
mov di,dx ! add di,RL_BUFOFF ; DI -> End of Destination Offset
add di,bx ! dec di ; -> + Insert Char len - 1
mov si,di ! sub si,bx ; SI -> DI - Insert Char Len
push es ! pop ds ; DS == ES
std ; Make the right amount of space in
rep movsb ; the buffer
cld
pop di ! pop si
pop ds
add dx,bx ; Update the Buffer Length
stosb ; Save the New character
test RL_FLAGS,RLF_KANJI ; Check if this was a Kanji Character
jz save_c60 ; No
xchg al,ah ! stosb ; Yes Save high byte
save_c60:
mov cx,dx ! sub cx,si ; Display the updated string
add si,bx ! push si ; Save the Updated Index
mov si,di ! sub si,bx ; Get the offset of the new char
call put_string ; in the buffer and display all
pop si ; Restore the new index
xchg di,dx ; and calculate the number of BS
call calc_chars ; characters required to get back
xchg di,dx
jmp bs_out
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -