CMDLINE.A86
资源名称:drdossrc.zip [点击查看]
上传用户:xiaogehua
上传日期:2007-01-08
资源大小:1183k
文件大小:32k
源码类别:
操作系统开发
开发平台:
Asm
- ; 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
- ;
- ; On Entry: AL First byte of Character
- ;
- ; On Exit: AX Complete Character Code
- ; CX Character Size Bytes
- ; RL_KANJI and RLF_KANJI set correctly
- ;
- save_kanji:
- and RL_FLAGS,not RLF_KANJI
- mov RL_KANJI,ax ; Save the Character
- call char_type ; Is this the first byte of a
- test ah,CHAR_KANJI ; two byte Kanji character
- mov cx,1 ; Character size in bytes
- jz save_k10 ; No
- or RL_FLAGS,RLF_KANJI ; Set internal Flag
- call get_char ; Get the high byte and save
- mov byte ptr RL_KANJI+1,al ; in the local variable
- mov ax,RL_KANJI ; Get the complete character
- mov cx,2 ; Character size in bytes
- save_k10:
- ret
- eject
- ;
- ; The following group of functions modify the flags which control
- ; the command line editor.
- ;
- toggle_ins:
- xor RL_FLAGS,RLF_INS ; Toggle the OverWrite/Insert
- ret ; Flag
- toggle_search:
- and RL_FLAGS,not RLF_MATCH ; clear match bit
- xor RL_FLAGS,RLF_SEARCH ; Toggle the Search on/off flag
- ret
- eject
- ;
- ; This group of functions moves the cursor along the display
- ; as well as updating the local variables.
- ;
- goto_bol:
- test si,si ; Move the cursor to the begining of
- jz goto_b10 ; the displayed line
- mov di,si ; Set the buffer index to the
- xor si,si ; start of the line and the current
- call calc_chars ; location
- call bs_out
- xor si,si
- mov di,RL_BUFOFF
- goto_b10:
- ret
- next_char:
- cmp si,dx
- jnz next_c05 ; Treat this as "F1" when we at the
- jmp copy_char ; end of the line
- next_c05:
- mov al,es:[di] ; Get the Offset of the next character
- mov cx,1 ; the character itself and assume
- call char_type ; it is 1 byte long
- test ah,CHAR_KANJI ! jz next_c10
- inc cx
- next_c10:
- xchg si,di ; Get the string offset in SI
- call put_string ; display the character and
- xchg si,di ; restore the register contents
- add si,cx
- add di,cx
- ret
- prev_char:
- test si,si ; begining of line ?
- jz prev_w30
- 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_c10:
- call char_info ; Get the character information
- cmp si,di ; Stop when we get to the current
- je prev_w20 ; character location
- mov dx,si ; Save current location
- jmps prev_c10 ; and repeat
- prev_w20:
- sub si,dx ; Calculate character length
- push si ; save for update
- sub di,RL_BUFOFF ; Convert Offset to Index
- neg si ! add si,di ; Set the buffer index to the current
- call calc_chars ; location and the previous character
- call bs_out ; BackSpace over character
- pop cx ; Restore the character size
- pop di ! pop si ! pop dx
- sub si,cx ; Update the Index and Pointer
- sub di,cx ; variables.
- prev_w30:
- ret
- eject
- ;
- ; This group of functions deletes characters or groups of characters
- ; from the buffer.
- ;
- delf_char:
- cmp si,dx ; any chars to our right ?
- jb deln_char ; yes, delete them first
- jmp skip_one_char
- ; ret ; discard next saved char
- del_eol:
- mov cx,dx ! sub cx,si ; Calculate the number of bytes to
- jcxz del_eol10 ; delete and jump to DELN_WORD if
- add cx,di ; non zero. Convert to an offset
- jmps deln_w10 ; and jmp to common code.
- del_eol10:
- ret
- delp_char:
- or si,si ! jz del_eol10 ; Ignore if the user is at the start
- call back_one_char ; of the line otherwise move back one
- call prev_char ; character in the line buffer
- deln_char:
- cmp dx,si ! jz del_eol10
- mov al,es:[di] ; Get the Offset of the next character
- lea cx,1[di] ; the character itself and assume
- call char_type ; it is 1 byte long
- test ah,CHAR_KANJI ! jz deln_w10
- inc cx
- ; jmps deln_w10
- ;
- ; The 3 delete functions come together at this point with the standard
- ; register format Plus CX is the offset of the first character not to
- ; be deleted.
- ;
- deln_w10:
- push cx ; Save Delete Offset
- xchg di,dx ; Determine the no of characters
- call calc_chars ; displayed to the end of the line
- xchg di,dx
- mov bx,cx ; Save the Column count
- pop ax ; restore the delete offset
- push bx ! push bx ; Save the count twice
- push si ! push di
- mov cx,dx ! sub cx,si ; No of chars from old EOL
- mov si,ax ; Get the Source Offset
- sub ax,di ; calculate its length.
- sub dx,ax ; Update the string length
- sub cx,ax ; Number of chars to copy
- push ds ; Move the contents of the
- push es ! pop ds ; string down in memory and
- rep movsb ; then update the screen image
- pop ds
- pop si ! pop di ; Get the current buffer offset
- ; Restore SWAPPED SI <-> DI
- mov cx,dx ; Calculate the length of the
- sub cx,di ; string and print it alll
- call put_string
- xchg si,di ; Restore SI and DI
- jcxz deln_w20
- xchg di,dx ; Calculate the number of columns
- call calc_chars ; displayed
- xchg di,dx
- deln_w20:
- pop bx ; Restore the original line length
- sub bx,cx ; and calculate the number of spaces
- mov cx,bx ; required to overwrite the data
- call space_out
- pop cx ; Finally move the cursor back to
- jmp bs_out ; its correct place
- ;
- ; Delete the contents of the complete line
- ;
- del_line:
- mov RL_SAVPOS,0 ; Reset the buffer index
- test dx,dx
- jz del_l10
- call goto_bol ; Jump to the begining of the line
- mov di,dx ; calculate the number of display
- call calc_chars ; columns it currently takes up
- call space_out ; Overwrite with spaces
- call bs_out ; Move back to the start of the line
- xor si,si ; and update all the initial variables
- mov dx,si
- mov di,RL_BUFOFF
- del_l10:
- ret
- eject
- ;
- ; The following routines manipulate the SAVE Buffer data. Which
- ; is initialised on entry to this function.
- ;
- ; SKIP_ONE_CHAR increments the Save Buffer control variables and
- ; returns the number of bytes skipped in CX.
- ;
- ; On Entry: Standard Registers
- ;
- ; On Exit: AX Next Character in Buffer
- ; CX Character Size (Bytes)
- ;
- skip_one_char:
- xor cx,cx
- mov bx,RL_SAVPOS ; Update the Save Buffer variables
- cmp bx,RL_SAVMAX ; Check the current save buffer is
- jae soc_20 ; valid and has not been exhausted.
- ; Otherwise increment the RL_SAVPOS
- mov bx,offset savbuf ; pointer by one character. This
- add bx,RL_SAVPOS ; means that the RL_SAVPOS can be
- mov al,ds:[bx] ; incremented by 1 or 2 depending on
- call char_type ; the contents of the buffer
- test ah,CHAR_KANJI
- jz soc_10
- mov ah,ds:1[bx]
- inc cx
- soc_10:
- inc cx
- soc_20:
- add RL_SAVPOS,cx
- ret
- ;
- ;
- ; BACK_ONE_CHAR decrements the Save Buffer control variables and
- ; returns the number of bytes skipped in CX.
- ;
- ; On Entry: Standard Registers
- ;
- ; On Exit: RL_SAVPOS points to previous buffer char
- ; AX,BX,CX,DX Unknown
- ;
- back_one_char:
- push dx
- mov bx,offset savbuf ; Get the Buffer address
- mov cx,bx ! add cx,RL_SAVPOS ; CX is the Current location
- mov dx,bx ; DX is last matching character
- boc_10:
- cmp bx,cx ; Have we reached the current Char
- jz boc_20 ; Yes exit and update buffer
- mov dx,bx ; Update last character location
- mov al,ds:[bx] ; incremented by 1 or 2 depending on
- call char_type ; the contents of the buffer
- inc bx
- test ah,CHAR_KANJI ; Increment pointer by 2 for a Kanji
- jz boc_10 ; character
- inc bx
- jmps boc_10
- boc_20:
- sub dx,offset savbuf ; Calculate the character Index
- mov RL_SAVPOS,dx ; and save in RL_SAVPOS
- pop dx
- ret
- copy_char:
- cmp dx,si ; If at end of line copy characters
- jz copy_c5
- call next_char ; Otherwise just move by 1
- jmp copy_c10
- copy_c5:
- call skip_one_char ; Calculate Bytes to copy
- jcxz copy_c10 ; Skip Update in no characters skipped
- sub RL_SAVPOS,cx ; Restore the Buffer Position
- jmps copy_a10 ; and copy the data
- copy_c10:
- ret
- copy_till_char:
- cmp dx,si ; Copy out if at end of line
- jnz move_till_char
- call skip_till_char ; Returns index to the next char
- sub RL_SAVPOS,cx
- jmps copy_a10
- move_till_char:
- mov RL_SAVPOS,si ; Start search from the current
- call skip_till_char ; position
- jcxz no_move ; CX=0 - dont move
- move_along:
- push cx
- call next_char ; Shuttle along the line until
- pop cx ; we reach the character
- loop move_along
- no_move:
- ret
- copy_all:
- mov cx,RL_SAVMAX ; Calculate the number of bytes to
- sub cx,RL_SAVPOS ; copy from the buffer.
- copy_a10:
- cmp cx,0 ; do we have nothing to copy
- jle copy_a30 ; (or less than nothing..)
- push RL_FLAGS ; Save State flags and prevent
- or RL_FLAGS,RLF_INS ; SAVPOS being modified
- copy_a20:
- push cx
- and RL_FLAGS,not RLF_KANJI
- call skip_one_char ; Return the next character and its
- cmp cx,1
- jz copy_a25 ; size in bytes
- mov RL_KANJI,ax ; Save the Kanji Character and
- or RL_FLAGS,RLF_KANJI ; set the control flag
- pop bx
- dec bx
- push bx ; Decrement the Loop Count
- copy_a25:
- call intsave_char ; Save the character
- pop cx ; and repeat till all bytes have
- loop copy_a20 ; been copied
- pop RL_FLAGS ; Restore State Flags
- copy_a30:
- ret
- skip_till_char:
- call get_char ; Get the first character
- call save_kanji ; Setup RL_KANJI etc.
- push dx
- call skip_one_char ; don't match on 1st char
- mov dx,cx ; remember we've skipped 1st char
- jcxz stc_40 ; buffer exhausted
- stc_10:
- call skip_one_char ; Get the Next Character
- jcxz stc_40 ; Buffer exhausted
- add dx,cx ; Update the Total Byte Count
- cmp cx,2 ! jz stc_20 ; Was this a Kanji Character
- test RL_FLAGS,RLF_KANJI ; No but are we looking for one ?
- jnz stc_10 ; Yes so get the next character
- cmp al,byte ptr RL_KANJI ; Have we got a matching character ?
- jnz stc_10 ; No so look again
- jmps stc_30 ; Return Sucess
- stc_20: ; Kanji Character in Buffer
- test RL_FLAGS,RLF_KANJI ; Are we looking for a Kanji Char
- jz stc_10 ; No so try again
- cmp ax,RL_KANJI ; Check the character and repeat
- jnz stc_10 ; if they donot match
- stc_30: ; Character Match
- sub dx,cx ; Correct the Total Byte Count
- sub RL_SAVPOS,cx ; point to the matching char
- xchg cx,dx ; and return the Match Count
- pop dx
- ret
- stc_40: ; No Match
- sub RL_SAVPOS,dx ; Restore RL_SAVPOS to orginal value
- xor cx,cx ; and return 0000 characters skipped
- pop dx
- ret
- ;
- ; Update the Save buffer with the contents of the users
- ; line buffer.
- ;
- ; On Entry: ES:DI -> Current location in Buffer
- ; DX No. of bytes in buffer
- ;
- ; On Exit: Update RL_SAVMAX, RL_SAVPOS, RL_SAVBUF
- ;
- save_line:
- xor ax,ax
- mov RL_SAVPOS,ax
- mov RL_SAVMAX,ax
- mov cx,dx ; Current Line Length
- jcxz save_l10
- cmp cx,savbuf_size ; clip the amount saved
- jb save_l5 ; to be a maximum of
- mov cx,savbuf_size ; the save buffer size
- save_l5:
- mov RL_SAVMAX,cx ; Set the Save Data Length
- push ds ! push es
- push si ! push di
- push ds ! pop es
- lds si,RL_BUFPTR
- mov di,offset savbuf
- rep movsb ; save the data
- pop di ! pop si
- pop es ! pop ds
- save_l10:
- ; ret
- ignore_char:
- ret
- mem_line: ;; JFL save from beginning of line
- call save_line
- jmp goto_bol
- ; ret
- eof_char: ;; JFL make F6 return a CTL Z
- mov al,01Ah
- mov cx,1
- jmp intsave_char
- ; ret
- ctlat_char: ;; JFL make F7 return a CTL @
- mov al,0h
- mov cx,1
- jmp intsave_char
- ; ret
- eject
- ;
- ; CHAR_TYPE get the next character from the buffer ES:SI and returns
- ; its type in AH using the equates CHAR_????. The character is returned
- ; in AL.
- ;
- ;
- ;
- char_type:
- mov ah,CHAR_SPACE or CHAR_STD ; WhiteSpace
- cmp al,' ' ! jz char_t100
- mov ah,CHAR_TAB ; Tab Character
- cmp al,TAB ! jz char_t100
- mov ah,CHAR_ALPHAN or CHAR_STD
- cmp al,CTLU ! jz char_t100 ; Control-U and Control-T are treated
- cmp al,CTLT ! jz char_t100 ; as normal characters
- mov ah,CHAR_CTL ; Control Character
- cmp al,' ' ! jb char_t100
- mov ah,CHAR_ALPHAN or CHAR_STD
- cmp al,'0' ! jb char_t90 ; Return SYMBOL
- cmp al,'9' ! jbe char_t100 ; Return AlphaNumeric
- cmp al,'A' ! jb char_t90 ; Return Symbol
- cmp al,'Z' ! jbe char_t100 ; Return AlphaNumeric
- cmp al,'a' ! jb char_t90 ; Return Symbol
- cmp al,'z' ! jbe char_t100 ; Return AlphaNumeric
- cmp al,80h ! jb char_t90 ; Return Symbol
- mov ah, CHAR_KANJI ; assume character is 16 bits
- call dbcs_lead ; is byte a DBCS lead?
- je char_t100 ; yes - done
- char_t90:
- mov ah,CHAR_OTHER or CHAR_STD ; no - Normal Character Symbol
- char_t100:
- ret
- ;
- ; CHAR_INFO will return various information about the character
- ; at ES:SI
- ;
- ; On Entry: ES:SI Character Pointer
- ; BX Current Column No.
- ; CX Byte Scan Count
- ;
- ; On Exit: ES:SI Points to the next Character
- ; BX Updates Column No.
- ; CX Updates Byte Scan Count
- ; AH Character type Flags
- ; AL First byte of Character
- char_info:
- lods es:al
- call char_type ; Test the character type and assume
- inc bx ; it will take 1 Screen location
- test ah,CHAR_ONECOL
- jnz char_i20
- inc bx ; Now check for the Control Characters
- test ah,CHAR_CTL ; which take up 2 cols
- jnz char_i20
- test ah,CHAR_KANJI ; If this was the first byte of a
- jz char_i10 ; KANJI character then skip the
- inc si ! dec cx ; next byte
- jmps char_i20
- char_i10:
- push ax ; Save AX and calculate the number
- dec bx ! dec bx ; of screen locations that this TAB
- mov ax,bx ; character will use based on the fact
- and ax,7 ; BX contains the current column
- neg ax ! add ax,8
- add bx,ax
- pop ax
- char_i20:
- ret
- eject
- ;
- ; CALC_CHARS calculates the number of character locations used
- ; on the screen to display a particular sub-string of the current
- ; buffer. This routine takes account of the Kanji, Control and TAB
- ; characters.
- ;
- ; On Entry: SI Start Buffer Index
- ; DI End Buffer Index
- ;
- ; On Exit: CX Count
- ;
- calc_chars:
- push bx
- push si ! push di
- mov bx,RL_INICOL ; Get the initial Column
- sub di,si ; DI = Sub-string length bytes
- mov cx,si ; Use the Start Index for the
- mov si,RL_BUFOFF ; initial count and scan from the
- jcxz calc_c20 ; start of the buffer
- calc_c10:
- call char_info
- loop calc_c10
- calc_c20:
- mov cx,di ; Sub-String Length
- mov di,bx ; Current Column position
- calc_c30:
- call char_info
- loop calc_c30
- sub bx,di
- mov cx,bx
- pop di ! pop si
- pop bx
- ret
- eject
- ;
- ; The following functions are purely Low level character output
- ; functions.
- ;
- space_out: ; Write CX Space characters to the
- mov al,' ' ; Output handle
- jmps block_out
- bs_out:
- mov al,CTLH ; Write CX BackSpace characters to
- ;; jmps block_out ; Output Handle
- block_out:
- jcxz block_o20
- push cx
- block_o10:
- call write_char ; output this character
- loop block_o10
- pop cx
- block_o20:
- ret
- ;
- ; Display CX characters from the string at ES:SI
- ;
- put_string:
- jcxz puts_s20
- push cx ! push si
- put_s10:
- push cx
- lods es:al
- call put_char
- pop cx
- loop put_s10
- pop si ! pop cx
- puts_s20:
- ret
- ;
- ; Display the character in AL
- ;
- put_char:
- cmp al,' ' ! jae write_char ; skip if it's printable
- cmp al,CTLT! je write_char ; Control-T and Control-U are treated
- cmp al,CTLU! je write_char ; like normal Characters.
- cmp al,TAB ! je write_char ; skip if it's TAB
- or al,040h ; Convert Character to Uppercase
- push ax ; save it
- mov al,'^' ; display the character
- call write_char ; in ^X format
- pop ax
- write_char:
- push es
- push dx
- push cx
- push si
- push di
- push ax ; char on stack
- mov bx,RL_OUTPUT ; Output AL to the OUTPUT Handle
- push ss ! pop es ; ES:DX -> Character Buffer
- mov si,sp ; buffer offset
- mov cx,1 ; character count
- call cooked_write ; Write Character
- pop ax
- pop di
- pop si
- pop cx
- pop dx
- pop es
- ret
- ;
- ; Read 1 a character from RL_INPUT saving all the vital registers
- ; from corruption. If the first character is the ESCAPE character
- ; set AH to TRUE and read the next byte. Otherwise AH is FALSE
- ;
- get_char:
- push ds
- push es
- push dx
- push si
- push di
- call get_dseg ; point at pcmode data
- lds si,con_device ; DS:SI -> current console device
- test ds:DH_ATTRIB[si],DA_IOCTL ; test bit 14: IOCTL bit
- jz get_c05 ; error if IOCTL not supported
- sub sp,RH_SIZE ; reserve this many words on the stack
- mov bx,sp ; SS:BX -> request packet
- push ss ! pop es ; ES:BX -> request packet
- lea dx,RL_FLAGS ; point at flags
- mov es:RH_CMD[bx],CMD_OUTPUT_IOCTL
- mov es:RH_LEN[bx],RH4_LEN
- mov es:RH4_BUFOFF[bx],dx ; set up for a normal
- mov es:RH4_BUFSEG[bx],ss ; IOCTL read/write
- mov es:RH4_COUNT[bx],WORD
- call device_driver ; execute the command
- add sp,RH_SIZE ; reclaim the stack
- get_c05:
- call get_dseg ; point at pcmode data
- mov bx,RL_INPUT ; BX = input stream
- call cmdline_read ; get a character
- mov ah,FALSE ; Assume this is NOT the Escape
- cmp al,esc_char ; character and set high byte of the
- jnz get_c10 ; match word to FALSE
- call raw_read ; read the second byte of the escape
- mov ah,ESC_CODE ; sequence, setting high byte to ESC
- get_c10:
- pop di
- pop si
- pop dx
- pop es
- pop ds
- ret
- PCM_RODATA CSEG WORD
- EDIT_CNTRL equ cs:word ptr 0[bx] ; Character and Esc Flag
- EDIT_FUNC equ cs:word ptr 2[bx] ; Edit Function Address
- EDIT_LEN equ 4 ; Edit Table Entry Size
- esc_char db 0 ; Command Line Editor Escape Character
- edit_size dw (offset edit_end - edit_table)/EDIT_LEN
- edit_table db CR ! db NESC_CODE ! dw ret_string
- db LF ! db NESC_CODE ! dw ignore_char
- db CTLH ! db NESC_CODE ! dw delp_char
- db DEL ! db NESC_CODE ! dw delf_char
- db ESC ! db NESC_CODE ! dw del_line
- db ';' ! db ESC_CODE ! dw copy_char ; Function 1
- db '<' ! db ESC_CODE ! dw copy_till_char ; Function 2
- db '=' ! db ESC_CODE ! dw copy_all ; Function 3
- db '>' ! db ESC_CODE ! dw skip_till_char ; Function 4
- db '?' ! db ESC_CODE ! dw mem_line ; Function 5
- db '@' ! db ESC_CODE ! dw eof_char ; Function 6
- db 'A' ! db ESC_CODE ! dw ctlat_char ; Function 7
- db 'B' ! db ESC_CODE or DISABLE ! dw match_cmd ; Function 8
- db 'R' ! db ESC_CODE ! dw toggle_ins ; Insert
- db 'S' ! db ESC_CODE ! dw delf_char ; Delete
- db 'K' ! db ESC_CODE or DISABLE ! dw prev_char ; Left Arrow
- db 'M' ! db ESC_CODE or DISABLE ! dw next_char ; Right Arrow
- ; When advanced editing is disabled the match for Left/Right arrows will fall
- ; through to here
- db 'K' ! db ESC_CODE ! dw delp_char ; Left Arrow - compat
- db 'M' ! db ESC_CODE ! dw copy_char ; Right Arrow - compat
- ;
- ; Extended functions from here on
- ;
- db 'C' ! db ESC_CODE or DISABLE ! dw del_cur_history_buffer ; Func 9
- db 'D' ! db ESC_CODE or DISABLE ! dw del_history_buffers ; Func 10
- db 'G' ! db ESC_CODE or DISABLE ! dw goto_bol ; Home
- db 'O' ! db ESC_CODE or DISABLE ! dw goto_eol ; End
- db 't' ! db ESC_CODE or DISABLE ! dw next_word ; Control Right Arrow
- db 's' ! db ESC_CODE or DISABLE ! dw prev_word ; Control Left Arrow
- db CTLV ! db NESC_CODE or DISABLE ! dw toggle_ins
- db CTLQ ! db NESC_CODE or DISABLE ! dw goto_bol
- db CTLW ! db NESC_CODE or DISABLE ! dw goto_eol
- db CTLR ! db NESC_CODE or DISABLE ! dw match_cmd
- db CTLD ! db NESC_CODE or DISABLE ! dw next_char
- db CTLS ! db NESC_CODE or DISABLE ! dw prev_char
- db CTLF ! db NESC_CODE or DISABLE ! dw next_word
- db CTLA ! db NESC_CODE or DISABLE ! dw prev_word
- db CTLG ! db NESC_CODE or DISABLE ! dw deln_char
- db CTLT ! db NESC_CODE or DISABLE ! dw deln_word
- db CTLY ! db NESC_CODE or DISABLE ! dw del_line
- db CTLB ! db NESC_CODE or DISABLE ! dw del_bol
- db CTLK ! db NESC_CODE or DISABLE ! dw del_eol
- db 'I' ! db ESC_CODE or DISABLE ! dw ignore_char ; PageUP
- db 'Q' ! db ESC_CODE or DISABLE ! dw ignore_char ; PageDown
- db 'H' ! db ESC_CODE or DISABLE ! dw prev_cmd ; Up Arrow
- db 'P' ! db ESC_CODE or DISABLE ! dw next_cmd ; Down Arrow
- db CTLE ! db NESC_CODE or DISABLE ! dw prev_cmd
- db CTLX ! db NESC_CODE or DISABLE ! dw next_cmd
- db CTLUB ! db NESC_CODE or DISABLE ! dw toggle_search ; Default search mode
- edit_end rb 0
- PCMODE_DATA DSEG WORD
- extrn con_device:dword ; Current Console Device
- extrn column:byte ; Console Cursor Location
- savbuf_size equ 128
- extrn savbuf:byte ; fixed location in DOS data area
- extrn cle_state:word ; command line editing state
- end