CMDLINE.A86
上传用户:xiaogehua
上传日期:2007-01-08
资源大小:1183k
文件大小:32k
源码类别:

操作系统开发

开发平台:

Asm

  1. ;    File              : $CMDLINE.A86$
  2. ;
  3. ;    Description       :
  4. ;
  5. ;    Original Author   : DIGITAL RESEARCH
  6. ;
  7. ;    Last Edited By    : $CALDERA$
  8. ;
  9. ;-----------------------------------------------------------------------;
  10. ;    Copyright Work of Caldera, Inc. All Rights Reserved.
  11. ;      
  12. ;    THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
  13. ;    PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
  14. ;    ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
  15. ;    WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
  16. ;    THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
  17. ;    HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
  18. ;    AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
  19. ;    AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
  20. ;    COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
  21. ;    CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
  22. ;    TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
  23. ;    CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
  24. ;    AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
  25. ;    CIVIL LIABILITY.
  26. ;-----------------------------------------------------------------------;
  27. ;
  28. ;    *** Current Edit History ***
  29. ;    *** End of Current Edit History ***
  30. ;
  31. ;    $Log$
  32. ;    CMDLINE.A86 1.8 93/03/25 15:06:03
  33. ;    tweak console block output
  34. ;    ENDLOG
  35. ;
  36. ;  DOSPLUS Command Line Editor Routines
  37. ;
  38. include pcmode.equ
  39. include i:msdos.equ
  40. include i:char.def
  41. include i:cmdline.equ
  42. include i:reqhdr.equ
  43. include i:driver.equ
  44. PCM_CODE CSEG BYTE
  45. public read_line, edit_size
  46. extrn dbcs_lead:near
  47. extrn cmdline_read:near
  48. extrn raw_read:near
  49. extrn cooked_write:near
  50. extrn get_dseg:near
  51. extrn device_driver:near
  52. ; WARNING - the following routines are to support history buffers
  53. ; As these are optional we muset NEVER call these routines unless
  54. ; the HISTORY_ON bit is set in @hist_flag.
  55. extrn init_history:near
  56. extrn save_history:near
  57. extrn prev_cmd:near
  58. extrn next_cmd:near
  59. extrn match_cmd:near
  60. extrn search_cmd:near
  61. extrn match_word:near
  62. extrn del_cur_history_buffer:near
  63. extrn del_history_buffers:near
  64. extrn goto_eol:near
  65. extrn next_word:near
  66. extrn prev_word:near
  67. extrn del_bol:near
  68. extrn deln_word:near
  69. ; The following are public for HISTORY.PCM
  70. public next_char, save_line
  71. public space_out, bs_out, put_string
  72. public goto_bol
  73. public del_eol, del_line
  74. public char_info
  75. public prev_w20
  76. public deln_w10
  77. ; READ_LINE will read an editted line from the handle passed in BX
  78. ; into a buffer with the following format:-
  79. ;
  80. ; BYTE Maximum String Length
  81. ; BYTE Current String Length
  82. ; BYTE(s) String Buffer
  83. ;
  84. ; On Entry:-
  85. ; BX Input Handle
  86. ; CX Output Handle
  87. ; ES:DX Buffer Address
  88. ;
  89. ; On Exit:-
  90. ; String input by user
  91. ;
  92. ; The following conventions apply for the READ_LINE function
  93. ;
  94. ; ES Buffer segment
  95. ; SI Current cursor location in buffer (Index)
  96. ; DX Last Character in Buffer (Index)
  97. ;
  98. DISABLE equ 80h ; Disable when advanced editing is off.
  99. DISABLE_MASK equ 8000h
  100. ESC_CODE equ 01h ; Scan code must be preceeded by escape byte.
  101. NESC_CODE equ 00h ; No lead zero needed.
  102. read_line:
  103. push bp ; Save the Stack Frame Pointer
  104. mov bp,sp ; Intialise it to the top of the
  105. sub sp,RL_LENGTH ; READ_LINE control block and reserve
  106. ; control block
  107. mov RL_INPUT,bx ; Initialize the INPUT Handle
  108. mov RL_OUTPUT,cx ; the OUTPUT Handle
  109. inc dx ! inc dx ; Skip max and Returned Length
  110. mov RL_BUFOFF,dx ; and save the buffer offset
  111. mov RL_BUFSEG,es ;  and segment
  112. xor ax,ax ; now we zero
  113. mov RL_SAVPOS,ax ;  both position in it
  114. mov RL_SAVMAX,ax ;  and it's size
  115. mov al,column
  116. mov RL_INICOL,ax ; save initial column
  117. mov ax,cle_state ; use to set initial editing state
  118. and ax,not (RLF_MATCH+RLF_DIRTY+RLF_RECALLED)
  119. mov RL_FLAGS,ax ; save in flags
  120. test ax,RLF_ENHANCED
  121.  jz read_line10
  122. call init_history ;  setup the history buffers
  123. jmps read_line20
  124. read_line10:
  125. and RL_FLAGS,not RLF_INS ; clear insert mode
  126. read_line20:
  127. mov di,dx ; di -> buffer
  128. xor bx,bx
  129. or bl,es:byte ptr -2[di] ; Get the Maximum number of chars
  130. mov RL_MAXLEN,bx ; and save for later
  131.  jnz read_line30 ; make sure some chars are requested
  132. jmps ret_string10 ; if no chars just return
  133. ret_string:
  134. pop ax ; Remove local return address
  135. mov ax,RL_FLAGS ; get command line editor state
  136. mov cle_state,ax ;  save state for next time
  137. mov di,RL_BUFOFF ; Get the buffer Offset
  138. mov es:byte ptr -1[di],dl ; Return the number of characters
  139. push dx ; Save length of entry
  140. add di,dx ; Point to the end of the buffer
  141. mov al,CR
  142. stosb ; Save CR
  143. call write_char ; Print a CR and return to the user
  144. pop dx
  145. test RL_FLAGS,RLF_ENHANCED ; Do not add to history if in
  146.  jz ret_string10 ; compatibility mode
  147. call save_history ; Save state of history buffer
  148. ret_string10:
  149. mov sp,bp ; Remove READ_LINE control Block
  150. pop bp ; Restore BP and return to the caller
  151. ret
  152. read_line30:
  153. xor si,si ; Currently at start of buffer
  154. mov dx,si ; with an empty buffer.
  155. xor bx,bx
  156. or bl,es:byte ptr -1[di] ; Check if the buffer contains any
  157.  jz read_line40 ; data which is terminated by a CR
  158. cmp es:byte ptr [bx+di],CR
  159.  jnz read_line40
  160. mov dx,bx
  161. read_line40:
  162. call save_line ; Update Save Buffer variables
  163. mov dx,si
  164. ;
  165. ; This is out main command loop - we get a character and try to match it
  166. ; with a command in our edit_table. If History is on we look at commands
  167. ; with the DISABLED bit set ie. enhanced commands.
  168. ; It a match isn't found we insert the character in the buffer, and optionally
  169. ; try to match with previous lines in the history buffer.
  170. ;
  171. read_line_loop:
  172. and RL_FLAGS,not RLF_KANJI ; initial flags
  173. call get_char ; read the first character (AH Esc Flg)
  174. mov cx,edit_size ; now scan the control table looking
  175. mov bx,offset edit_table ;  for a match
  176. read_ll_next_cmd:
  177. and ax,not DISABLE_MASK ; assume normal function
  178. test  RL_FLAGS,RLF_ENHANCED ; compatibilty required? then it
  179.  jz  read_ll10 ;  has to be a normal function
  180. test EDIT_CNTRL,DISABLE_MASK ; history enabled, so we make
  181.  jz read_ll10 ;  our code match DISABLE mask
  182. or ax,DISABLE_MASK ;  of table entry
  183. read_ll10:
  184. cmp ax,EDIT_CNTRL ; check for a match (Escape Flag
  185.  je read_ll_found_cmd ;  and the character)
  186. add bx,EDIT_LEN ; Add the entry length
  187. loop read_ll_next_cmd ; and scan the whole table
  188. ; We have failed to find a command so insert char in buffer
  189. test ah,ESC_CODE ; Ignore non-matched escaped keys
  190.  jnz read_line_loop
  191. call save_char ; not an command so save the character
  192. or RL_FLAGS,RLF_DIRTY ;  and remember we have something new
  193. ; Are we in search mode ?
  194. test  RL_FLAGS,RLF_ENHANCED ; Compatibilty required?  
  195.  jz  read_line_loop
  196. test RL_FLAGS,RLF_SEARCH+RLF_MATCH
  197.  jz read_line_loop ; is searching/matching on ?
  198. push si ; save current offset
  199. call search_cmd
  200. pop ax ; this is our target offset
  201. read_ll20:
  202. cmp ax,si ; are we there yet ?
  203.  jae read_line_loop
  204. push ax ; no, keep rewinding cursor
  205. call prev_char ;  until we reach position
  206. pop ax ;  before we tried to match
  207. jmps read_ll20
  208. read_ll_found_cmd: ; get the address of the corresponding
  209. mov cx,EDIT_FUNC ;  function from the table
  210. call cx ;  execute the correct function
  211. jmps read_line_loop ;  and go back for next character
  212. eject
  213. ;
  214. ; the SAVE_CHAR routine will write the character in AL into 
  215. ; the buffer in memory and then update the screen image. The
  216. ; RLF_INS flag is used to determine if INSERT is active.
  217. ;
  218. save_c10:
  219. ret
  220. save_char:
  221. cmp ah,TRUE ; Ignore any un-matched escape 
  222. jz save_c10 ; sequences
  223. call save_kanji ; Test if AL is a Kanji Character
  224. ; and setup up the parameter blocks
  225. ; for the INTSAVE_CHAR routine
  226. ;
  227. ; INTSAVE_CHAR is the internal entry point to the Character Save
  228. ; routine. It assumes the following:-
  229. ;
  230. ; On Entry:- AX(AL)     Contains the character
  231. ; CX     the new character length in bytes
  232. ; RLF_KANJI   Flag is set for a Kanji Character
  233. ; RL_KANJI    Contains the kanji charater
  234. ;
  235. intsave_char:
  236. mov bx,cx
  237. test RL_FLAGS,RLF_INS ; Overwrite the character in the
  238.  jnz save_c50 ; buffer currently
  239. add bx,si ; Add the current index to the character
  240. cmp bx,RL_MAXLEN ; size and compare against the buffer len
  241.  jae bell_char ; Full ? Yes Ring dat Bell !
  242. cmp dx,si ; Are we at the end of the line
  243.  jnz intsave_c10 ; No so check character types
  244. push ax ! push cx
  245. call skip_one_char ; Skip the coresponding character in
  246. pop cx ! pop ax ; the save buffer
  247. jmps simple_save
  248. intsave_c10:
  249. push ax ; Save the Input Character
  250. call char_type ; Get the character type
  251. mov bx,ax ; and save in BX
  252. mov al,es:[di] ; get the byte to be replaced
  253. call char_type ; and get its type
  254. and ah,CHAR_SIZE ; Mask the Character SIZE attributes
  255. and bh,CHAR_SIZE ; and check both storage and display
  256. ; sizes are the same for old and new
  257. cmp ah,bh ; and do simple save if the character
  258. pop ax ; Restore the input character to AX(AL)
  259.  jnz save_c30 ; type match
  260. sub dx,cx ; Character overwritten so prevent
  261. ; Max Index being incremented
  262. simple_save:
  263. add si,cx ; Assume at the EOL
  264. add dx,cx
  265. stosb ; Save the character typed
  266. test RL_FLAGS,RLF_KANJI ; is this a Kanji character
  267.  jz simple_s10 ; No so just output 1 character
  268. call put_char ; and echo it to the user
  269. mov al,byte ptr RL_KANJI+1 ; Get the high byte of the Kanji
  270. stosb ; character save and then display it.
  271. simple_s10:
  272. jmp put_char
  273. ; ret
  274. ;
  275. ; The SAVE_C30 function supports the Complex overwrite conditions
  276. ; where the size of the character in memory or on the display do not
  277. ; match with those of the present incumbent. eg a SPACE character
  278. ; overwriting a TAB or a KANJI character overwriting a SPACE.
  279. ;
  280. ; To minimize the complexity of the code the character to be 
  281. ; overwritten is deleted and the new character then inserted.
  282. ; This is not an optimal solution but drastically reduces the
  283. ; amount of code required.
  284. ;
  285. save_c30:
  286. push ax ! push cx
  287. call deln_char
  288. pop cx ! pop ax
  289. cmp dx,si
  290.  jz simple_save
  291. or RL_FLAGS,RLF_INS
  292. call save_c50
  293. and RL_FLAGS,not RLF_INS
  294. ret
  295. bell_char:
  296. mov al,BELL
  297. jmp write_char
  298. ;
  299. ; This code is called when INSERT mode is active and a 
  300. ; character (possibly Kanji) is to be inserted in the buffer
  301. ;
  302. ; On Entry:- CX     the new character length in bytes
  303. ;
  304. save_c50:
  305. mov bx,cx ; Save new character length
  306. add cx,dx ; Add the current max to the character
  307. cmp cx,RL_MAXLEN ; size and compare against the buffer len
  308.  jae bell_char ; Full ? Yes Ring dat Bell !
  309. mov cx,bx ; Restore Character Length
  310. cmp dx,si ; If we are at the end of the line
  311.  je simple_save ; Use the simple save code
  312. ;
  313. ; Create space in the current buffer for the new character
  314. ;
  315. push ds
  316. push si ! push di
  317. mov cx,dx ! sub cx,si ; CX -> Number of bytes to move
  318. mov di,dx ! add di,RL_BUFOFF ; DI -> End of Destination Offset
  319. add di,bx ! dec di ;    -> + Insert Char len - 1
  320. mov si,di ! sub si,bx ; SI -> DI - Insert Char Len
  321. push es ! pop ds ; DS == ES
  322. std ; Make the right amount of space in
  323. rep movsb ; the buffer
  324. cld
  325. pop di ! pop si
  326. pop ds
  327. add dx,bx ; Update the Buffer Length
  328. stosb ; Save the New character
  329. test RL_FLAGS,RLF_KANJI ; Check if this was a Kanji Character
  330.  jz save_c60 ; No
  331. xchg al,ah ! stosb ; Yes Save high byte
  332. save_c60:
  333. mov cx,dx ! sub cx,si ; Display the updated string
  334. add si,bx ! push si ; Save the Updated Index
  335. mov si,di ! sub si,bx ; Get the offset of the new char
  336. call put_string ; in the buffer and display all
  337. pop si ; Restore the new index
  338. xchg di,dx ; and calculate the number of BS
  339. call calc_chars ; characters required to get back
  340. xchg di,dx
  341. jmp bs_out
  342. ;
  343. ; On Entry: AL First byte of Character
  344. ;
  345. ; On Exit: AX Complete Character Code
  346. ; CX Character Size Bytes
  347. ; RL_KANJI and RLF_KANJI set correctly
  348. ;
  349. save_kanji:
  350. and RL_FLAGS,not RLF_KANJI
  351. mov RL_KANJI,ax ; Save the Character
  352. call char_type ; Is this the first byte of a 
  353. test ah,CHAR_KANJI ; two byte Kanji character
  354. mov cx,1 ; Character size in bytes
  355.  jz save_k10 ; No
  356. or RL_FLAGS,RLF_KANJI ; Set internal Flag
  357. call get_char ; Get the high byte and save
  358. mov byte ptr RL_KANJI+1,al ; in the local variable
  359. mov ax,RL_KANJI ; Get the complete character
  360. mov cx,2 ; Character size in bytes
  361. save_k10:
  362. ret
  363. eject
  364. ;
  365. ; The following group of functions modify the flags which control
  366. ; the command line editor.
  367. ;
  368. toggle_ins:
  369. xor RL_FLAGS,RLF_INS ; Toggle the OverWrite/Insert
  370. ret ; Flag
  371. toggle_search:
  372. and RL_FLAGS,not RLF_MATCH ; clear match bit
  373. xor RL_FLAGS,RLF_SEARCH ; Toggle the Search on/off flag
  374. ret
  375. eject
  376. ;
  377. ; This group of functions moves the cursor along the display
  378. ; as well as updating the local variables.
  379. ;
  380. goto_bol:
  381. test si,si ; Move the cursor to the begining of
  382.  jz goto_b10 ; the displayed line
  383. mov di,si ; Set the buffer index to the
  384. xor si,si ; start of the line and the current 
  385. call calc_chars ; location
  386. call bs_out
  387. xor si,si
  388. mov di,RL_BUFOFF
  389. goto_b10:
  390. ret
  391. next_char:
  392. cmp si,dx
  393.  jnz next_c05 ; Treat this as "F1" when we at the
  394. jmp copy_char ; end of the line
  395. next_c05:
  396. mov al,es:[di] ; Get the Offset of the next character
  397. mov cx,1 ; the character itself and assume
  398. call char_type ; it is 1 byte long
  399. test ah,CHAR_KANJI ! jz next_c10
  400. inc cx
  401. next_c10:
  402. xchg si,di ; Get the string offset in SI
  403. call put_string ; display the character and
  404. xchg si,di ; restore the register contents
  405. add si,cx
  406. add di,cx
  407. ret
  408. prev_char:
  409. test si,si ; begining of line ?
  410.  jz prev_w30
  411. push dx ! push si ! push di
  412. mov si,RL_BUFOFF ; Scan from the begining of the buffer
  413. mov dx,si ; keeping the last match in DX
  414. prev_c10:
  415. call char_info ; Get the character information
  416. cmp si,di ; Stop when we get to the current
  417.  je prev_w20 ; character location
  418. mov dx,si ; Save current location
  419. jmps prev_c10 ; and repeat
  420. prev_w20:
  421. sub si,dx ; Calculate character length
  422. push si ; save for update
  423. sub di,RL_BUFOFF ; Convert Offset to Index
  424. neg si ! add si,di ; Set the buffer index to the current
  425. call calc_chars ; location and the previous character
  426. call bs_out ; BackSpace over character
  427. pop cx ; Restore the character size
  428. pop di ! pop si ! pop dx
  429. sub si,cx ; Update the Index and Pointer
  430. sub di,cx ; variables.
  431. prev_w30:
  432. ret
  433. eject
  434. ;
  435. ; This group of functions deletes characters or groups of characters
  436. ; from the buffer.
  437. ;
  438. delf_char:              
  439. cmp si,dx ; any chars to our right ?
  440.  jb deln_char ;  yes, delete them first
  441.     jmp skip_one_char      
  442. ; ret ;  discard next saved char
  443. del_eol:
  444. mov cx,dx ! sub cx,si ; Calculate the number of bytes to 
  445. jcxz del_eol10 ; delete and jump to DELN_WORD if
  446. add cx,di ; non zero. Convert to an offset
  447. jmps deln_w10 ; and jmp to common code.
  448. del_eol10:
  449. ret
  450. delp_char:
  451. or si,si ! jz del_eol10 ; Ignore if the user is at the start 
  452. call back_one_char ; of the line otherwise move back one
  453. call prev_char ; character in the line buffer
  454. deln_char:
  455. cmp dx,si ! jz del_eol10
  456. mov al,es:[di] ; Get the Offset of the next character
  457. lea cx,1[di] ; the character itself and assume
  458. call char_type ; it is 1 byte long
  459. test ah,CHAR_KANJI ! jz deln_w10
  460. inc cx
  461. ; jmps deln_w10
  462. ;
  463. ; The 3 delete functions come together at this point with the standard
  464. ; register format Plus CX is the offset of the first character not to
  465. ; be deleted.
  466. ;
  467. deln_w10:
  468. push cx ; Save Delete Offset
  469. xchg di,dx ; Determine the no of characters
  470. call calc_chars ; displayed to the end of the line
  471. xchg di,dx
  472. mov bx,cx ; Save the Column count
  473. pop ax ; restore the delete offset
  474. push bx ! push bx ; Save the count twice
  475. push si ! push di
  476. mov cx,dx ! sub cx,si ; No of chars from old EOL
  477. mov si,ax ; Get the Source Offset
  478. sub ax,di ; calculate its length.
  479. sub dx,ax ; Update the string length
  480. sub cx,ax ; Number of chars to copy
  481. push ds ; Move the contents of the
  482. push es ! pop ds ; string down in memory and
  483. rep movsb ; then update the screen image
  484. pop ds
  485. pop si ! pop di ; Get the current buffer offset
  486. ; Restore SWAPPED SI <-> DI
  487. mov cx,dx ; Calculate the length of the
  488. sub cx,di ; string and print it alll
  489. call put_string
  490. xchg si,di ; Restore SI and DI
  491.  jcxz deln_w20
  492. xchg di,dx ; Calculate the number of columns
  493. call calc_chars ; displayed
  494. xchg di,dx
  495. deln_w20:
  496. pop bx ; Restore the original line length
  497. sub bx,cx ; and calculate the number of spaces
  498. mov cx,bx ; required to overwrite the data
  499. call space_out
  500. pop cx ; Finally move the cursor back to
  501. jmp bs_out ; its correct place 
  502. ;
  503. ; Delete the contents of the complete line
  504. ;
  505. del_line:
  506. mov RL_SAVPOS,0 ; Reset the buffer index
  507. test dx,dx
  508.  jz del_l10
  509. call goto_bol ; Jump to the begining of the line
  510. mov di,dx ; calculate the number of display
  511. call calc_chars ; columns it currently takes up
  512. call space_out ; Overwrite with spaces
  513. call bs_out ; Move back to the start of the line
  514. xor si,si ; and update all the initial variables
  515. mov dx,si
  516. mov di,RL_BUFOFF
  517. del_l10:
  518. ret
  519. eject
  520. ;
  521. ; The following routines manipulate the SAVE Buffer data. Which
  522. ; is initialised on entry to this function.
  523. ;
  524. ; SKIP_ONE_CHAR increments the Save Buffer control variables and
  525. ; returns the number of bytes skipped in CX.
  526. ;
  527. ; On Entry: Standard Registers
  528. ;
  529. ; On Exit: AX  Next Character in Buffer
  530. ; CX Character Size (Bytes)
  531. ;
  532. skip_one_char:
  533. xor cx,cx
  534. mov bx,RL_SAVPOS ; Update the Save Buffer variables
  535. cmp bx,RL_SAVMAX ; Check the current save buffer is
  536.  jae soc_20 ; valid and has not been exhausted.
  537. ; Otherwise increment the RL_SAVPOS
  538. mov bx,offset savbuf ; pointer by one character. This 
  539. add bx,RL_SAVPOS ; means that the RL_SAVPOS can be 
  540. mov al,ds:[bx] ; incremented by 1 or 2 depending on 
  541. call char_type ; the contents of the buffer
  542. test ah,CHAR_KANJI
  543.  jz soc_10
  544. mov ah,ds:1[bx]
  545. inc cx
  546. soc_10:
  547. inc cx
  548. soc_20:
  549. add RL_SAVPOS,cx
  550. ret
  551. ;
  552. ;
  553. ; BACK_ONE_CHAR decrements the Save Buffer control variables and
  554. ; returns the number of bytes skipped in CX.
  555. ;
  556. ; On Entry: Standard Registers
  557. ;
  558. ; On Exit: RL_SAVPOS points to previous buffer char
  559. ; AX,BX,CX,DX Unknown
  560. ;
  561. back_one_char:
  562. push dx
  563. mov bx,offset savbuf ; Get the Buffer address
  564. mov cx,bx ! add cx,RL_SAVPOS ; CX is the Current location
  565. mov dx,bx ; DX is last matching character
  566. boc_10:
  567. cmp bx,cx ; Have we reached the current Char
  568.  jz boc_20 ; Yes exit and update buffer
  569. mov dx,bx ; Update last character location
  570. mov al,ds:[bx] ; incremented by 1 or 2 depending on 
  571. call char_type ; the contents of the buffer
  572. inc bx
  573. test ah,CHAR_KANJI ; Increment pointer by 2 for a Kanji
  574.  jz boc_10 ; character
  575. inc bx
  576. jmps boc_10
  577. boc_20:
  578. sub dx,offset savbuf ; Calculate the character Index
  579. mov RL_SAVPOS,dx ; and save in RL_SAVPOS
  580. pop dx
  581. ret
  582. copy_char:
  583. cmp dx,si ; If at end of line copy characters 
  584. jz copy_c5
  585. call next_char ; Otherwise just move by 1
  586. jmp copy_c10
  587. copy_c5:
  588. call skip_one_char ; Calculate Bytes to copy
  589. jcxz copy_c10 ; Skip Update in no characters skipped
  590. sub RL_SAVPOS,cx ; Restore the Buffer Position
  591. jmps copy_a10 ; and copy the data
  592. copy_c10:
  593. ret
  594. copy_till_char:
  595. cmp dx,si ; Copy out if at end of line
  596. jnz move_till_char
  597. call skip_till_char ; Returns index to the next char
  598. sub RL_SAVPOS,cx
  599. jmps copy_a10
  600. move_till_char:
  601. mov RL_SAVPOS,si ; Start search from the current
  602. call skip_till_char ; position
  603. jcxz no_move ; CX=0 - dont move
  604. move_along:
  605. push cx
  606. call next_char ; Shuttle along the line until
  607. pop cx ; we reach the character
  608. loop move_along
  609. no_move:
  610. ret
  611. copy_all:
  612. mov cx,RL_SAVMAX ; Calculate the number of bytes to
  613. sub cx,RL_SAVPOS ; copy from the buffer.
  614. copy_a10:
  615. cmp cx,0 ; do we have nothing to copy
  616.  jle copy_a30 ; (or less than nothing..)
  617. push RL_FLAGS ; Save State flags and prevent
  618. or RL_FLAGS,RLF_INS ; SAVPOS being modified
  619. copy_a20:
  620. push cx
  621. and RL_FLAGS,not RLF_KANJI
  622. call skip_one_char ; Return the next character and its 
  623. cmp  cx,1 
  624. jz  copy_a25 ; size in bytes
  625. mov RL_KANJI,ax ; Save the Kanji Character and
  626. or RL_FLAGS,RLF_KANJI ; set the control flag
  627. pop  bx
  628. dec  bx
  629. push  bx ; Decrement the Loop Count
  630. copy_a25:
  631. call intsave_char ; Save the character
  632. pop cx ; and repeat till all bytes have
  633. loop copy_a20 ; been copied
  634. pop RL_FLAGS ; Restore State Flags
  635. copy_a30:
  636. ret
  637. skip_till_char:
  638. call get_char ; Get the first character
  639. call save_kanji ; Setup RL_KANJI etc.
  640. push dx
  641. call skip_one_char ; don't match on 1st char
  642. mov dx,cx ; remember we've skipped 1st char
  643.  jcxz stc_40 ; buffer exhausted
  644. stc_10:
  645. call skip_one_char ; Get the Next Character
  646. jcxz stc_40 ; Buffer exhausted
  647. add dx,cx ; Update the Total Byte Count
  648. cmp cx,2 ! jz stc_20 ; Was this a Kanji Character
  649. test RL_FLAGS,RLF_KANJI ; No but are we looking for one ?
  650. jnz stc_10 ; Yes so get the next character
  651. cmp al,byte ptr RL_KANJI ; Have we got a matching character ?
  652. jnz stc_10 ; No so look again
  653. jmps stc_30 ; Return Sucess 
  654. stc_20: ; Kanji Character in Buffer
  655. test RL_FLAGS,RLF_KANJI ; Are we looking for a Kanji Char
  656. jz stc_10 ; No so try again
  657. cmp ax,RL_KANJI ; Check the character and repeat
  658. jnz stc_10 ; if they donot match
  659. stc_30: ; Character Match
  660. sub dx,cx ; Correct the Total Byte Count
  661. sub RL_SAVPOS,cx ; point to the matching char
  662. xchg cx,dx ; and return the Match Count
  663. pop dx
  664. ret
  665. stc_40: ; No Match
  666. sub RL_SAVPOS,dx ; Restore RL_SAVPOS to orginal value
  667. xor cx,cx ; and return 0000 characters skipped
  668. pop dx
  669. ret
  670. ;
  671. ; Update the Save buffer with the contents of the users
  672. ; line buffer.
  673. ;
  674. ; On Entry: ES:DI -> Current location in Buffer
  675. ; DX  No. of bytes in buffer
  676. ;
  677. ; On Exit: Update RL_SAVMAX, RL_SAVPOS, RL_SAVBUF
  678. ;
  679. save_line:
  680. xor ax,ax
  681. mov RL_SAVPOS,ax
  682. mov RL_SAVMAX,ax
  683. mov cx,dx ; Current Line Length
  684.  jcxz save_l10
  685. cmp cx,savbuf_size ; clip the amount saved
  686.  jb save_l5 ; to be a maximum of
  687. mov cx,savbuf_size ; the save buffer size
  688. save_l5:
  689. mov RL_SAVMAX,cx ; Set the Save Data Length
  690. push ds ! push es
  691. push si ! push di
  692. push ds ! pop es
  693. lds si,RL_BUFPTR
  694. mov di,offset savbuf
  695. rep movsb ; save the data
  696. pop di ! pop si
  697. pop es ! pop ds
  698. save_l10:
  699. ; ret
  700. ignore_char:
  701. ret
  702. mem_line: ;; JFL save from beginning of line 
  703. call save_line
  704. jmp goto_bol
  705. ; ret
  706. eof_char: ;; JFL make F6 return a CTL Z
  707. mov al,01Ah
  708. mov cx,1
  709. jmp intsave_char
  710. ; ret
  711. ctlat_char: ;; JFL make F7 return a CTL @
  712. mov al,0h
  713. mov cx,1
  714. jmp intsave_char
  715. ; ret
  716. eject
  717. ;
  718. ; CHAR_TYPE get the next character from the buffer ES:SI and returns
  719. ; its type in AH using the equates CHAR_????. The character is returned
  720. ; in AL.
  721. ;
  722. ;
  723. ;
  724. char_type:
  725. mov ah,CHAR_SPACE or CHAR_STD ; WhiteSpace
  726. cmp al,' ' ! jz char_t100
  727. mov ah,CHAR_TAB ; Tab Character
  728. cmp al,TAB ! jz char_t100
  729. mov ah,CHAR_ALPHAN or CHAR_STD
  730. cmp al,CTLU ! jz char_t100 ; Control-U and Control-T are treated
  731. cmp al,CTLT ! jz char_t100 ; as normal characters
  732. mov ah,CHAR_CTL ; Control Character
  733. cmp al,' ' ! jb char_t100
  734. mov ah,CHAR_ALPHAN or CHAR_STD
  735. cmp al,'0' ! jb  char_t90 ; Return SYMBOL
  736. cmp al,'9' ! jbe char_t100 ; Return AlphaNumeric
  737. cmp al,'A' ! jb  char_t90 ; Return Symbol
  738. cmp al,'Z' ! jbe char_t100 ; Return AlphaNumeric
  739. cmp al,'a' ! jb  char_t90 ; Return Symbol
  740. cmp al,'z' ! jbe char_t100 ; Return AlphaNumeric
  741. cmp al,80h ! jb  char_t90 ; Return Symbol
  742. mov ah, CHAR_KANJI ; assume character is 16 bits
  743. call dbcs_lead ; is byte a DBCS lead?
  744. je char_t100 ;  yes - done
  745. char_t90:
  746. mov ah,CHAR_OTHER or CHAR_STD ; no - Normal Character Symbol
  747. char_t100:
  748. ret
  749. ;
  750. ; CHAR_INFO will return various information about the character
  751. ; at ES:SI
  752. ;
  753. ; On Entry: ES:SI Character Pointer
  754. ; BX Current Column No.
  755. ; CX Byte Scan Count
  756. ;
  757. ; On Exit: ES:SI Points to the next Character
  758. ; BX Updates Column No.
  759. ; CX Updates Byte Scan Count
  760. ; AH Character type Flags
  761. ; AL First byte of Character
  762. char_info:
  763. lods es:al
  764. call char_type ; Test the character type and assume
  765. inc bx ; it will take 1 Screen location
  766. test ah,CHAR_ONECOL
  767. jnz char_i20
  768. inc bx ; Now check for the Control Characters
  769. test ah,CHAR_CTL ; which take up 2 cols
  770. jnz char_i20
  771. test ah,CHAR_KANJI ; If this was the first byte of a 
  772. jz char_i10 ; KANJI character then skip the
  773. inc si ! dec cx ; next byte
  774. jmps char_i20
  775. char_i10:
  776. push ax ; Save AX and calculate the number
  777. dec bx ! dec bx ; of screen locations that this TAB
  778. mov ax,bx ; character will use based on the fact
  779. and  ax,7 ; BX contains the current column
  780. neg ax ! add ax,8
  781. add bx,ax
  782. pop ax
  783. char_i20:
  784. ret
  785. eject
  786. ;
  787. ; CALC_CHARS calculates the number of character locations used
  788. ; on the screen to display a particular sub-string of the current
  789. ; buffer. This routine takes account of the Kanji, Control and TAB
  790. ; characters.
  791. ;
  792. ; On Entry: SI Start Buffer Index
  793. ; DI End Buffer Index
  794. ;
  795. ; On Exit: CX Count
  796. ;
  797. calc_chars:
  798. push bx
  799. push si ! push di
  800. mov bx,RL_INICOL ; Get the initial Column
  801. sub di,si ; DI = Sub-string length bytes
  802. mov cx,si ; Use the Start Index for the
  803. mov si,RL_BUFOFF ; initial count and scan from the
  804. jcxz calc_c20 ; start of the buffer
  805. calc_c10:
  806. call char_info
  807. loop calc_c10
  808. calc_c20:
  809. mov cx,di ; Sub-String Length
  810. mov di,bx ; Current Column position
  811. calc_c30:
  812. call char_info
  813. loop calc_c30
  814. sub bx,di
  815. mov cx,bx
  816. pop di ! pop si
  817. pop bx
  818. ret
  819. eject
  820. ;
  821. ; The following functions are purely Low level character output
  822. ; functions.
  823. ;
  824. space_out: ; Write CX Space characters to the
  825. mov al,' ' ; Output handle
  826. jmps block_out
  827. bs_out:
  828. mov al,CTLH ; Write CX BackSpace characters to
  829. ;; jmps block_out ; Output Handle
  830. block_out:
  831.  jcxz block_o20
  832. push cx
  833. block_o10:
  834. call write_char ; output this character
  835. loop block_o10
  836. pop cx
  837. block_o20:
  838. ret
  839. ;
  840. ; Display CX characters from the string at ES:SI
  841. ;
  842. put_string:
  843. jcxz puts_s20
  844. push cx ! push si
  845. put_s10:
  846. push cx
  847. lods es:al
  848. call put_char
  849. pop cx
  850. loop put_s10
  851. pop si ! pop cx
  852. puts_s20:
  853. ret
  854. ;
  855. ; Display the character in AL
  856. ;
  857. put_char:
  858. cmp al,' ' ! jae write_char ; skip if it's printable
  859. cmp al,CTLT! je write_char ; Control-T and Control-U are treated
  860. cmp al,CTLU! je write_char ; like normal Characters.
  861. cmp al,TAB ! je write_char ; skip if it's TAB
  862. or al,040h ; Convert Character to Uppercase
  863. push ax ; save it
  864. mov al,'^' ; display the character
  865. call write_char ;  in ^X format
  866. pop ax
  867. write_char:
  868. push es
  869. push dx
  870. push cx
  871. push si
  872. push di
  873. push ax ; char on stack
  874. mov bx,RL_OUTPUT ; Output AL to the OUTPUT Handle
  875. push ss ! pop es ; ES:DX -> Character Buffer
  876. mov si,sp ; buffer offset
  877. mov cx,1 ; character count
  878. call cooked_write ; Write Character
  879. pop ax
  880. pop di
  881. pop si
  882. pop cx
  883. pop dx
  884. pop es
  885. ret
  886. ;
  887. ; Read 1 a character from RL_INPUT saving all the vital registers
  888. ; from corruption. If the first character is the ESCAPE character
  889. ; set AH to TRUE and read the next byte. Otherwise AH is FALSE
  890. ;
  891. get_char:
  892. push ds
  893. push es
  894. push dx
  895. push si
  896. push di
  897. call get_dseg ; point at pcmode data
  898. lds si,con_device ; DS:SI -> current console device
  899. test ds:DH_ATTRIB[si],DA_IOCTL ; test bit 14: IOCTL bit
  900.  jz get_c05 ; error if IOCTL not supported
  901. sub sp,RH_SIZE ; reserve this many words on the stack
  902. mov bx,sp ; SS:BX -> request packet
  903. push ss ! pop es ; ES:BX -> request packet
  904. lea dx,RL_FLAGS ; point at flags
  905. mov es:RH_CMD[bx],CMD_OUTPUT_IOCTL
  906. mov es:RH_LEN[bx],RH4_LEN
  907. mov es:RH4_BUFOFF[bx],dx ; set up for a normal
  908. mov es:RH4_BUFSEG[bx],ss ;  IOCTL read/write
  909. mov es:RH4_COUNT[bx],WORD
  910. call device_driver ; execute the command
  911. add sp,RH_SIZE ; reclaim the stack
  912. get_c05:
  913. call get_dseg ; point at pcmode data
  914. mov bx,RL_INPUT ; BX = input stream
  915. call cmdline_read ; get a character
  916. mov ah,FALSE ; Assume this is NOT the Escape 
  917. cmp al,esc_char ; character and set high byte of the
  918.  jnz get_c10 ; match word to FALSE
  919. call raw_read ; read the second byte of the escape
  920. mov ah,ESC_CODE ;  sequence, setting high byte to ESC
  921. get_c10:
  922. pop di
  923. pop si
  924. pop dx
  925. pop es
  926. pop ds
  927. ret
  928. PCM_RODATA CSEG WORD
  929. EDIT_CNTRL equ cs:word ptr 0[bx] ; Character and Esc Flag
  930. EDIT_FUNC equ cs:word ptr 2[bx] ; Edit Function Address
  931. EDIT_LEN equ 4 ; Edit Table Entry Size
  932. esc_char db 0 ; Command Line Editor Escape Character
  933. edit_size dw (offset edit_end - edit_table)/EDIT_LEN
  934. edit_table db CR ! db NESC_CODE ! dw ret_string
  935. db LF ! db NESC_CODE ! dw ignore_char
  936. db CTLH ! db NESC_CODE ! dw delp_char
  937. db DEL ! db NESC_CODE ! dw delf_char
  938. db ESC ! db NESC_CODE ! dw del_line
  939. db ';'  ! db ESC_CODE  ! dw copy_char ; Function 1
  940. db '<'  ! db ESC_CODE  ! dw copy_till_char ; Function 2
  941. db '='  ! db ESC_CODE  ! dw copy_all ; Function 3
  942. db '>'  ! db ESC_CODE  ! dw skip_till_char ; Function 4
  943. db '?'  ! db ESC_CODE  ! dw mem_line ; Function 5
  944. db '@'  ! db ESC_CODE  ! dw eof_char ; Function 6
  945. db 'A'  ! db ESC_CODE  ! dw ctlat_char ; Function 7
  946. db 'B' ! db ESC_CODE or DISABLE ! dw match_cmd ; Function 8
  947. db 'R'  ! db ESC_CODE  ! dw toggle_ins ; Insert
  948. db 'S'  ! db ESC_CODE  ! dw delf_char ; Delete
  949. db 'K'  ! db ESC_CODE or DISABLE  ! dw prev_char ; Left Arrow 
  950. db 'M'  ! db ESC_CODE or DISABLE  ! dw next_char ; Right Arrow
  951. ; When advanced editing is disabled the match for Left/Right arrows will fall
  952. ; through to here
  953. db 'K'  ! db ESC_CODE  ! dw delp_char ; Left Arrow - compat
  954. db 'M'  ! db ESC_CODE  ! dw copy_char ; Right Arrow - compat
  955. ;
  956. ; Extended functions from here on
  957. ;
  958. db 'C'  ! db ESC_CODE or DISABLE ! dw del_cur_history_buffer ; Func 9
  959. db 'D'  ! db ESC_CODE or DISABLE ! dw del_history_buffers ; Func 10
  960. db 'G'  ! db ESC_CODE or DISABLE  ! dw goto_bol ; Home
  961. db 'O'  ! db ESC_CODE or DISABLE  ! dw goto_eol ; End
  962. db 't'  ! db ESC_CODE or DISABLE  ! dw next_word ; Control Right Arrow
  963. db 's'  ! db ESC_CODE or DISABLE  ! dw prev_word ; Control Left Arrow
  964. db CTLV ! db NESC_CODE or DISABLE ! dw toggle_ins
  965. db CTLQ ! db NESC_CODE or DISABLE ! dw goto_bol
  966. db CTLW ! db NESC_CODE or DISABLE ! dw goto_eol
  967. db CTLR ! db NESC_CODE or DISABLE ! dw match_cmd
  968. db CTLD ! db NESC_CODE or DISABLE ! dw next_char
  969. db CTLS ! db NESC_CODE or DISABLE ! dw prev_char
  970. db CTLF ! db NESC_CODE or DISABLE ! dw next_word
  971. db CTLA ! db NESC_CODE or DISABLE ! dw prev_word
  972. db CTLG ! db NESC_CODE or DISABLE ! dw deln_char
  973. db CTLT ! db NESC_CODE or DISABLE ! dw deln_word
  974. db CTLY ! db NESC_CODE or DISABLE ! dw del_line
  975. db CTLB ! db NESC_CODE or DISABLE ! dw del_bol
  976. db CTLK ! db NESC_CODE or DISABLE ! dw del_eol
  977. db 'I'  ! db ESC_CODE or DISABLE  ! dw ignore_char ; PageUP
  978. db 'Q'  ! db ESC_CODE or DISABLE  ! dw ignore_char ; PageDown
  979. db 'H'  ! db ESC_CODE or DISABLE  ! dw prev_cmd  ; Up Arrow
  980. db 'P'  ! db ESC_CODE or DISABLE  ! dw next_cmd ; Down Arrow
  981. db CTLE ! db NESC_CODE or DISABLE ! dw prev_cmd
  982. db CTLX ! db NESC_CODE or DISABLE ! dw next_cmd
  983. db CTLUB ! db NESC_CODE or DISABLE ! dw toggle_search ; Default search mode
  984. edit_end rb 0
  985. PCMODE_DATA DSEG WORD
  986. extrn con_device:dword ; Current Console Device
  987. extrn column:byte  ; Console Cursor Location
  988. savbuf_size equ 128
  989. extrn savbuf:byte ; fixed location in DOS data area
  990. extrn cle_state:word ; command line editing state
  991. end