home *** CD-ROM | disk | FTP | other *** search
/ Frostbyte's 1980s DOS Shareware Collection / floppyshareware.zip / floppyshareware / GLEN / CMD201A.ZIP / EDIT.ASM < prev    next >
Assembly Source File  |  1990-09-03  |  24KB  |  970 lines

  1. ; EDIT.ASM
  2. ; (c) 1989, 1990 Ashok P. Nadkarni
  3. ;
  4. ; This module contains the line editing functions of CMDEDIT.
  5.  
  6.     PUBLIC    get_kbd_line
  7.     PUBLIC    auto_recall
  8.     PUBLIC    expand_fnkey
  9.  
  10.     INCLUDE common.inc
  11.     INCLUDE ascii.inc
  12.     INCLUDE    BIOS.INC
  13.     INCLUDE    DOS.INC
  14.     INCLUDE    GENERAL.INC
  15.  
  16.  
  17. CSEG    SEGMENT    PARA PUBLIC 'CODE'
  18. CSEG    ENDS
  19.  
  20. DGROUP    GROUP    CSEG
  21.  
  22.     ASSUME    CS:DGROUP, DS:DGROUP, SS:DGROUP, ES:DGROUP
  23.  
  24. CSEG    SEGMENT    PARA PUBLIC 'CODE'
  25.  
  26.     EXTRN    linebuf:BYTE
  27.     EXTRN    lastchar:WORD
  28.     EXTRN    caller_cursor:WORD
  29.     EXTRN    dot:WORD
  30.     EXTRN    edit_mode:BYTE
  31.     EXTRN    omode_cursor:WORD
  32.     EXTRN    sym_stk:WORD
  33.     EXTRN    LINEBUF_END:ABS
  34.  
  35.  
  36. tempchar db    ?            ;Temporary storage
  37. auto_recall    db    0        ;By default no auto recall
  38. auto_recall_on    db    ?        ;1 if auto-recall in effect,
  39. ;                     else 0
  40. continue_recall db    ?        ;auto-recall state variable
  41. fnkey_tab    db    'S','F',0    ;Used to look for function key
  42. ;                     definitions. 
  43. fnkey_exec_char db    '@'        ;If the last character a fn key
  44. ;                     definition is this, the key is
  45. ;                     executed immediately
  46.  
  47. ; Must be IDENTICAL to the string in CMDCONF.C including the
  48. ; terminating '\0' byte. This must be followed immediately by ctrl_key_defs.
  49. cmdedit_keymap_id db    'CMDEDIT key map',0
  50. ; ctrl_key_redefs is used to allow the cmdconf program to remap the control
  51. ; keys. Each entry corresponds to a control key. It must immediately follow
  52. ; cmdedit_keymap_id.
  53. ctrl_key_redefs LABEL WORD
  54. x    =    0
  55.     REPT    32                ;32 control keys
  56.     DW    x
  57. x    =    x + 1
  58.     ENDM
  59.  
  60.  
  61.     EXTRN    disp_line:PROC
  62.     EXTRN    hist_back:PROC
  63.     EXTRN    hist_fwd:PROC
  64.     EXTRN    hist_bck_match:PROC
  65.     EXTRN    hist_fwd_match:PROC
  66.     EXTRN    remember:PROC
  67.     EXTRN    execute_auto_recall:PROC
  68.     EXTRN    insert_at_dot:PROC
  69.     EXTRN    erase_to_dot:PROC
  70.     EXTRN    isalphnum:PROC
  71.     EXTRN    set_disp_marks:PROC
  72.     EXTRN    bell:PROC
  73.     EXTRN    line_to_scr:PROC
  74.     EXTRN    isspace:PROC
  75.     EXTRN    xlate_lower:PROC
  76.     EXTRN    expand_var:PROC
  77.     EXTRN    ismacsym:PROC
  78.     EXTRN    get_symbol:PROC
  79.     
  80. ;number of command keys
  81. NUM_CMD_KEYS    EQU    (cmd_key_jumps-cmd_key_table)/2
  82.  
  83. ;+
  84. ; FUNCTION : get_kbd_line
  85. ;
  86. ;    Gets a line from the user and stores it in linebuf. The length
  87. ;    of the line is stored in global linelen. The name is a misnomer
  88. ;    because the line is from standard input, not necessarily from
  89. ;    the keyboard.
  90. ;
  91. ; Parameters:
  92. ;    None.
  93. ;
  94. ; Returns:
  95. ;    Nothing.
  96. ; Register(s) destroyed:
  97. ;-
  98.  
  99. get_kbd_line    proc    near
  100.     @save    si,di
  101.     mov    al,auto_recall
  102.     mov    auto_recall_on,al    ;Indicate if auto-recall is enabled
  103.     mov    continue_recall,1    ;Init auto-recall memory
  104.  
  105. ; Main editing loop
  106. @get_kbd_line_10:
  107.     mov    al,continue_recall
  108.     and    auto_recall_on,al    ;Indicate if we should keep
  109. ;                     auto-recalling
  110.     mov    continue_recall,0    ;Reset the flag. It will be set
  111. ;                     for the default actions keys.
  112.     call    near ptr disp_line    ;Show current line
  113.     call    near ptr getkey        ;get next key from the user
  114.     mov    si,ax            ;si holds the character
  115.     cmp    ax,32            ;Control character ?
  116.     jge    @get_kbd_line_15    ;No, then check if fn key
  117.     mov    di,si            ;DI used to calculate
  118.     add    di,di            ;  offset into table
  119.     mov    ax,ctrl_key_redefs[di]    ;Mapping of key
  120.     mov    si,ax
  121.     cmp    ax,32            ;Control char ?
  122.     jge    @get_kbd_line_15    ;No, then check if fn key
  123.     mov    di,si            ;DI used to calculate
  124.     add    di,di            ;  offset into table
  125.     jmp    ctrl_key_table[di]    ;Branch according to control char
  126. @get_kbd_line_15:            ;Check if function key
  127.     cmp    ax,256+59        ;>= F1 ?
  128.     jb    @get_kbd_line_20    ;No, then check next table
  129.     cmp    ax,256+68        ;<= F10
  130.     jg    @get_kbd_line_20    ;Not fn key
  131.     jmp    @fn_key            ;Handle the function key
  132. @get_kbd_line_20:
  133.     cmp    ax,256+84        ;>= Shift-F1 ?
  134.     jb    @get_kbd_line_25    ;No, then check next table
  135.     cmp    ax,256+93        ;<= Shift-F10
  136.     jg    @get_kbd_line_25    ;
  137.     jmp    @sfn_key        ;Handle the shifted function key
  138. @get_kbd_line_25:
  139.     mov    cx,NUM_CMD_KEYS        ;size and...
  140.     mov    bx,offset DGROUP:cmd_key_table    ;beginning of jump table
  141. @get_kbd_line_30:            ;Loop begin
  142.     cmp    ax,cs:[bx]        ;Is this the key ?
  143.     je    @get_kbd_line_40    ;Hurrah, found
  144.     inc    bx            ;point to next key
  145.     inc    bx
  146.     loop    @get_kbd_line_30    ;If more keys, repeat
  147.     jmp    short @default_action    ;key not in table
  148. @get_kbd_line_40:            ;Jump to location associated with
  149.     jmp    word ptr cs:[bx+(2*NUM_CMD_KEYS)]    ;key
  150.  
  151. @quote:                    ;Insert next char
  152. ;                     without interpreting it
  153.     call    near ptr  getkey
  154.  
  155. @default_action:            ;Insert the character (in AX)
  156.     call    near ptr store_char
  157.     jc    @get_kbd_line_10    ;No room for char, keep looping
  158.     mov    al,auto_recall_on    ;Are we auto-recalling ?
  159.     or    al,al
  160.     jz    @get_kbd_line_10    ;No
  161.     call    near ptr execute_auto_recall
  162.     jc    @get_kbd_line_10    ;If carry set, no matching
  163. ;                     string in history buffer
  164.     mov    continue_recall,1    ;Else indicate auto-recall is
  165. ;                     still to go on
  166.     jmp    short @get_kbd_line_10
  167.  
  168.  
  169. @char_left:                ;Cursor one char left
  170.     call    near ptr char_left    ;char_left will return to top
  171.     jmp    @get_kbd_line_10
  172. ;                     of editing loop
  173.  
  174. @char_right:                ;Cursor one char right
  175.     call    near ptr char_right    ;char_right will return to top
  176.     jmp    @get_kbd_line_10
  177. ;                     of editing loop
  178.  
  179. @word_left:                ;Cursor one word left
  180.     call    near ptr word_left
  181.     jmp    @get_kbd_line_10
  182.  
  183. @word_right:                ;Cursor one word right
  184.     call    near ptr word_right
  185.     jmp    @get_kbd_line_10
  186.  
  187. @bol:                    ;Beginning of line
  188.     call    near ptr go_bol
  189.     jmp    @get_kbd_line_10
  190.  
  191.  
  192. @eol:                    ;End of line
  193.     call    near ptr go_eol
  194.     jmp    @get_kbd_line_10
  195.  
  196.  
  197. @prev_line:                ;Get previous history line
  198.     mov    ax,offset DGROUP:hist_back
  199. @history_line:
  200.     call    ax
  201.     mov    ax,lastchar
  202.     mov    dot,ax            ;Leave cursor at end of line
  203. @history_search:
  204.     jnc    @history_line_done    ;Line found
  205.     call    near ptr bell        ;No line
  206. @history_line_done:
  207.     jmp    @get_kbd_line_10
  208.  
  209. @next_line:                ;Get next history line
  210.     mov    ax,offset DGROUP:hist_fwd
  211.     jmp    short @history_line
  212.  
  213. @search_back:                ;Search back thru history buffer
  214.     mov    ax,offset DGROUP:hist_bck_match
  215. @search:
  216.     mov    di,dot            ;Save current dot
  217.     call    ax
  218.     mov    dot,di            ;Restore it
  219.     jmp    short @history_search
  220.  
  221. @search_forw:                ;Search forward thru history buffer
  222.     mov    ax,offset DGROUP:hist_fwd_match
  223.     jmp    short @search
  224.  
  225.  
  226. @filename:                ;Try to find a matching filename
  227.     call    near ptr match_file
  228.     cmp    auto_recall_on,1    ;Autorecall ongoing?
  229.     je    short @del_eol        ;Yes, then delete to end of line
  230.     jmp    @get_kbd_line_10
  231.  
  232. @del_left:                ;Delete char before cursor
  233.     mov    ax,offset dgroup:char_left
  234.     jmp    short @delete
  235.  
  236. @del_right:                ;Delete char at cursor
  237.     mov    ax,offset dgroup:char_right
  238.     jmp    short @delete
  239.  
  240.  
  241. @del_prev_word:                ;Delete upto word beginning
  242.     mov    ax,offset dgroup:word_left
  243.     jmp    short @delete
  244.  
  245. @del_next_word:                ;Delete to start of next word
  246.     mov    ax,offset dgroup:word_right
  247.     jmp    short @delete
  248.  
  249. @del_bol:                ;Delete to beginning of line
  250.     mov    ax,offset dgroup:go_bol
  251.     jmp    short @delete
  252.  
  253.  
  254. @toggle_insert:
  255.     mov    ax,1
  256.     xor    al,edit_mode        ;Toggle edit mode
  257.     mov    edit_mode,al
  258.     xchg    ax,bx
  259.     add    bx,bx            ;Word offset
  260.     mov    cx,omode_cursor[bx]    ;cx<-cursor shape
  261.     mov    ah,01h            ;Set cursor size function
  262.     IF    TOGGLE_CURSOR
  263.     int    10h            ;BIOS 
  264.     ENDIF
  265.     jmp    @get_kbd_line_10    ;Repeat editing loop
  266.  
  267. @abort_and_store:            ;Erases current line but remembers
  268. ;                     it in the history buffer
  269.     call    near ptr remember
  270. ;    Fall through to erase line
  271. @erase_line:
  272.     call    near ptr go_bol        ;Move dot to beginning of line
  273. ;    fall thru to delete to end of line
  274.  
  275. @del_eol:                ;Delete to end of line
  276.     mov    ax,offset dgroup:go_eol
  277.  
  278. @delete:                ;General purpose delete
  279.     mov    si,dot            ;Remember the dot
  280.     call    ax            ;Move dot to new position
  281.     xchg    si,ax
  282.     call    near ptr erase_to_dot    ;Delete characters between ax and dot
  283.     jmp    @get_kbd_line_10
  284.  
  285. @autorecall:
  286.     xor    auto_recall,1        ;Toggle auto recall mode
  287.     jmp    @get_kbd_line_10
  288.  
  289. @vars:
  290. ; Expand the variables on the line.
  291.     call    near ptr expand_var
  292.     jmp    @get_kbd_line_10    ;Ignore return status from expand_var
  293.  
  294.  
  295. @inline_back:
  296. @inline_forw:
  297. @ignore:
  298.     jmp    @get_kbd_line_10    ;Ignore the character
  299.  
  300.  
  301. ctrl_key_table    LABEL    WORD
  302.     dw    @ignore        ;NUL or ^@
  303.     dw    @bol        ;^A
  304.     dw    @char_left    ;^B
  305.     dw    @ignore        ;^C
  306.     dw    @del_right    ;^D
  307.     dw    @eol        ;^E
  308.     dw    @char_right    ;^F
  309.     dw    @abort_and_store ;^G
  310.     dw    @del_left    ;^H
  311.     dw    @filename    ;^I
  312.     dw    @vars        ;^J might have to be @ignore in order for input 
  313. ;                 redirection to work properly but try for
  314. ;                 var expansion anyway.
  315.     dw    @del_eol    ;^K
  316.     dw    @del_prev_word    ;^L
  317.     dw    @done_editing    ;^M
  318.     dw    @next_line    ;^N
  319.     dw    @del_eol_exec    ;^O
  320.     dw    @ignore        ;^P - don't use, filtered by get key call ?
  321.     dw    @quote        ;^Q
  322.     dw    @search_back    ;^R
  323.     dw    @ignore        ;^S - don't use, does not work properly
  324.     dw    @ignore        ;^T
  325.     dw    @prev_line    ;^U
  326.     dw    @search_forw    ;^V
  327.     dw    @del_next_word    ;^W
  328.     dw    @del_bol    ;^X
  329.     dw    @autorecall    ;^Y
  330.     dw    @default_action    ;^Z
  331.     dw    @erase_line    ;^[ or ESC
  332.     dw    @inline_back    ;^\
  333.     dw    @inline_forw    ;^]
  334.     dw    @done_wipeout    ;^^
  335.     dw    @ignore        ;^_
  336.  
  337. cmd_key_table:                ;table of command keys
  338.     dw    127    ;DEL
  339.     dw    327    ;HOME
  340.     dw    328    ;UP
  341.     dw    331    ;LEFT
  342.     dw    333    ;RIGHT
  343.     dw    335    ;END
  344.     dw    336    ;DOWN
  345.     dw    338    ;INS
  346.     dw    339    ;KDEL
  347.     dw    371    ;CTLLEFT
  348.     dw    372    ;CTLRIGHT
  349. cmd_key_jumps:
  350.     dw    @del_left    ;DEL
  351.     dw    @bol        ;HOME
  352.     dw    @search_back    ;UP
  353.     dw    @char_left    ;LEFT
  354.     dw    @char_right    ;RIGHT
  355.     dw    @eol        ;END
  356.     dw    @search_forw    ;DOWN
  357.     dw    @toggle_insert    ;INS
  358.     dw    @del_right    ;KDEL
  359.     dw    @word_left    ;CTLLEFT
  360.     dw    @word_right    ;CTLRIGHT
  361.  
  362.  
  363. @sfn_key:
  364. ; A shifted function key has been struck.
  365. ; (Treat same as an unshifted function key).
  366. @fn_key:
  367. ; A function key has been struck.
  368.     call    near ptr expand_fnkey
  369.     jc    @fn_key_20            ;Error or no expansion
  370.     or    dx,dx                ;Line to be executed
  371. ;                         immediately ?
  372.     je    short @done_editing_2        ;Yes, all done
  373. @fn_key_20:
  374.     jmp    @get_kbd_line_10        ;else keep editing
  375.  
  376. @del_eol_exec:                ;Deletes characters from the dot
  377. ;                     to end of the line and then
  378. ;                     executes the line
  379.     mov    si,dot            ;Remember the dot
  380.     call    go_eol
  381.     xchg    si,ax
  382.     call    near ptr erase_to_dot
  383.     jmp    short @done_editing
  384.  
  385.  
  386. @done_wipeout:
  387. ; The line is executed. However it is not stored in the history buffer and
  388. ; is also removed from the screen (this is a little klugy).
  389.     mov    ax,offset DGROUP:linebuf
  390.     mov    dot,ax
  391.     mov    dx,lastchar
  392.     mov    lastchar,ax            ;Temporarily pretend line
  393. ;                         is empty
  394.     xchg    ax,dx
  395.     push    ax
  396.     call    near ptr set_disp_marks
  397.     call    disp_line
  398.     pop    ax
  399.     mov    lastchar,ax            ;Restore line length
  400.     jmp    short @get_kbd_line_90
  401.  
  402. @done_editing:
  403.     call    near ptr remember    ;Store in history buffer
  404. ;                     Picks up line from global linebuf
  405. @done_editing_2:
  406.     call    near ptr disp_line    ;Necessry for @del_eol_exec,
  407. ;                     might as well do for others
  408.     mov    ax,lastchar
  409.     mov    dot,ax            ;Set dot to end of line
  410.     call    near ptr line_to_scr    ;Set cursor beyond last character
  411.  
  412. @get_kbd_line_90:
  413.     @DispCh CR            ;Do a carraige return because
  414. ;                     some applications like EDLIN
  415. ;                     only do a LF to go to next line
  416. ;    @DispCh LF            ;Go onto next line
  417. ;    all done
  418. @get_kbd_line_99:
  419.     @restore
  420.     ret
  421. get_kbd_line endp
  422.  
  423.  
  424.  
  425. getkey proc near
  426.     @GetKey    0
  427.     mov    ah,0
  428.     or    al,al
  429.     jne    @114        ;not '\0'
  430.     mov    ah,0Bh
  431.     int    21h        ;check if key available
  432.     or    al,al
  433.     jz    @113        ;no character available
  434.     @GetKey    0
  435.     mov    ah,1
  436.     jmp    short @114
  437. @113:
  438.     xor    ax,ax
  439. @114:
  440.     ret
  441. getkey    endp
  442.  
  443.  
  444.  
  445. ;+
  446. ; FUNCTION : expand_fnkey
  447. ;
  448. ;    Inserts the expansion corresponding to a symbol key into the
  449. ;    linebuffer. If the buffer is too small, only as many characters as
  450. ;    possible are inserted and the function returns an error. The
  451. ;    function also returns an error if the symbols is not defined. The
  452. ;    function also updates the displayed line. The function also checks
  453. ;    if the line is to be executed immediately or not, based on the last
  454. ;    character of the fn key expansion.
  455. ;
  456. ; Parameters:
  457. ;    AX    = function key character, must be between (256+59)-(256+68)
  458. ;          function keys and (256+84)-(256+93) for shifted functin keys.
  459. ;
  460. ; Returns:
  461. ;    CF    = 0 if no error, else 1
  462. ;          If CF is 1, then AX is 0 if symbol not found or non-zero
  463. ;          if symbol found but no room in line.
  464. ;    AX    = 1 if symbol was present 
  465. ;          0 if symbol was not found.
  466. ;    DX    = 0 if the line is to be executed immediately
  467. ;          non-0 otherwise
  468. ;          DX is only valid if CF=0 and AX=1
  469. ; Register(s) destroyed:
  470. ;     <TBA>
  471. ;-
  472. expand_fnkey proc near
  473.     @save    si,di
  474.     push    bp
  475.     mov    bp,sp
  476.     sub    sp,LINEBUF_SIZE
  477. exp_buf    equ <byte ptr [bp-LINEBUF_SIZE]>
  478.  
  479.     mov    si,offset DGROUP:fnkey_tab    ;SI->'SFn'
  480.     mov    dx,3                ;DX<-length of string
  481.     mov    di,si
  482.     sub    ax,256+59
  483.     cmp    ax,10                ;Is it a function key
  484.     jnb    @expand_fnkey_10        ;No, shifted function key
  485.     inc    si                ;SI->'Fn'
  486.     dec    dx                ;length of string is 2
  487.     jmp    short @expand_fnkey_15
  488. @expand_fnkey_10:
  489.     sub    ax,84-59
  490. @expand_fnkey_15:
  491.     cmp    ax,9                ;F10 must appear as F0
  492.     jne    @expand_fnkey_20
  493.     mov    al,'0'-'1'
  494. @expand_fnkey_20:
  495.     add    al,'1'
  496.     mov    2[di],al            ;Store in 'SFn' string
  497. ; OK now try and expand the symbol.
  498. ;                         SI->symbol
  499.     mov    ax,LINEBUF_SIZE
  500.     xchg    ax,dx                ;AX<-length of synbol
  501. ;                         DX<-length of expansion buffer
  502.     lea    di,exp_buf
  503.     call    near ptr get_symbol        ;Params SI,AX,DI,DX
  504.     jc    @expand_fnkey_99        ;No symbol (buffer too
  505. ;                         small case not possible).
  506. ;                         AX will be 0 for this case.
  507. ; OK now we have the symbol expansion, so try insert it into the linebuffer.
  508. ;    AX contains length of expansion
  509.     mov    si,di                ;SI->expansion
  510.     add    di,ax
  511.     dec    di                ;DI->last char of expansion
  512.     xor    dx,dx
  513.     mov    dl,byte ptr [di]        
  514.     sub    dl,fnkey_exec_char        ;Is this line to be
  515. ;                         immediately executed
  516.     jne    @expand_fnkey_80        ;No
  517.     dec    ax                ;The last char of expansion
  518. ;                         is a special char. Do not
  519. ;                         include it in the insert
  520. ;                         string 
  521. @expand_fnkey_80:
  522.     push    dx
  523.     call    near ptr insert_at_dot        ;Params SI,AX
  524. ;    pushf                    ;Save CF
  525. ;    call    disp_line
  526. ;    popf                    ;Restore CF
  527.     mov    ax,1                ;AX<-exit code
  528.     pop    dx                ;DX is 0 if line is to be
  529. ;                         executed immediately
  530. @expand_fnkey_99:
  531.     mov    sp,bp
  532.     pop    bp
  533.     @restore
  534.     ret
  535.  
  536. expand_fnkey endp
  537.  
  538.  
  539. ;+
  540. ; FUNCTION : store_char
  541. ;
  542. ;    Stores    the character in AX into the line buffer if max line
  543. ;    length will not be exceeded. Characters may be inserted or
  544. ;    overwrite chars in the buffer depending on the edit mode and whether
  545. ;    auto-recall is on.
  546. ;
  547. ; Parameters:
  548. ;    AX    = character
  549. ;
  550. ; Returns:
  551. ;    CF    = 0 if no error, else 1
  552. ; Register(s) destroyed:
  553. ;     <TBA>
  554. ;-
  555. store_char proc near
  556.     @save    si
  557.     cmp    ax,256            ;char >= 256
  558.     jnb    @store_char_90        ;Ignore if so
  559.     cmp    edit_mode,0        ;1 if insert mode
  560.     je    @store_char_20        ;Jump if overtype mode
  561.     cmp    auto_recall_on,1    ;Is auto-recall on ?
  562.     je    @store_char_20        ;Yes, behave as if in overtype mode
  563.     mov    si,offset dgroup:tempchar ;temporary storage
  564.     mov    [si],al            ;Store char
  565.     mov    ax,1            ;Length of string
  566.     call    near ptr insert_at_dot    ;Insert the character
  567.     jnc    @store_char_99        ;No problemo
  568.     jmp    short @store_char_90    ;No room in buffer
  569. @store_char_20:
  570.     mov    si,dot            ;Current position in line
  571.     cmp    si,LINEBUF_END        ;At line end?
  572.     jae    @store_char_90
  573. ;    Enough room for a char
  574.     mov    [si],al            ;Store the char
  575.     mov    dx,si            ;DX->changed character
  576.     mov    ax,si
  577.     inc    ax            ;AX->char after change
  578.     mov    dot,ax            ;Store it as new dot position
  579.     cmp    si,lastchar        ;Was it end of line ?
  580.     jb    @store_char_30
  581.     mov    lastchar,ax        ;Store new end of line
  582. @store_char_30:
  583.     call    near ptr set_disp_marks    ;ax,dx parameters
  584.     clc                ;Indicate no error
  585.     jmp    short @store_char_99
  586. @store_char_90:
  587.     call    near ptr bell
  588.     stc                ;Indicate error
  589. @store_char_99:
  590.     @restore
  591.     ret
  592. store_char endp
  593.  
  594.  
  595. ;+
  596. ; FUNCTION : word_left
  597. ;
  598. ;    Move one word left.
  599. ;
  600. ; Parameters:
  601. ;    Globals linebuf and dot.
  602. ;
  603. ; Returns:
  604. ;    CF = 1 if dot was at beginning of the line already
  605. ;         0 otherwise.
  606. ; Register(s) destroyed:
  607. ;-
  608. word_left proc near
  609. @word_left_10:
  610.     call    near ptr char_left    ;Move one char left
  611.     jc    @word_left_99        ;Already at beginning of line
  612. @word_left_12:
  613.     ;Loop to backup over non-alphanum
  614.     call    near ptr isalphnum    ;AL alphanumeric?
  615.     jnc    @word_left_15        ;Yes
  616.     call    near ptr char_left    ;One char left.
  617.                     ;AL<-char at dot
  618.     jnc    @word_left_12        ;Not at beginning of line
  619. @word_left_15:                ;Now backup to beginning of word
  620. ;    At this point, dot is always at a alphabetic char or beginning
  621. ;    of the line
  622.     call    near ptr char_left
  623.     jc    @word_left_98        ;Were already at beginning of line
  624.     call    near ptr isalphnum    ;Alphanumeric?
  625.     jnc    @word_left_15        ;Yes, loop back
  626.                     ;Found non-alphanumeric char
  627.     call    near ptr char_right    ;move over one
  628. @word_left_98:
  629.     clc                ;Clear carry flag
  630. @word_left_99:
  631.     ret
  632. word_left endp
  633.  
  634.  
  635.  
  636. ;+
  637. ; FUNCTION : word_right
  638. ;
  639. ;    Move one word right.
  640. ;
  641. ; Parameters:
  642. ;    Globals linebuf and dot.
  643. ;
  644. ; Returns:
  645. ;    Nothing.
  646. ; Register(s) destroyed:
  647. ;-
  648. word_right proc near
  649. @word_right_10:                ;Loop fwd over alphanumerics
  650.     call    near ptr char_right    ;One char right
  651.                     ;AL<-char at dot
  652.     jc    @word_right_99        ;Already at end of line
  653.     call    near ptr isalphnum    ;Is AL alphanumeric ?
  654.     jnc    @word_right_10        ;Yes, loop back
  655. @word_right_15:                ;Now move to beginning of word
  656.     call    near ptr char_right
  657.     jc    @word_right_99        ;Already at end of line
  658.     call    near ptr isalphnum    ;Alphanumeric?
  659.     jc    @word_right_15        ;Not alphanum char, loop back
  660. @word_right_99:
  661.     ret
  662. word_right endp
  663.  
  664.  
  665.  
  666.  
  667. ;+
  668. ; FUNCTION : char_left
  669. ;
  670. ;    Moves the 'dot' one character to the left unless
  671. ;    already at the beginning of the line.
  672. ;
  673. ; Parameters:
  674. ;    Global    dot is current position in the line.
  675. ;
  676. ; Returns:
  677. ;    AL    = char at new dot position.
  678. ;    CF    = 1 if OLD dot was at beginning of line
  679. ;          0 otherwise.
  680. ; Register(s) destroyed:
  681. ;-
  682. char_left proc    near
  683.     @save    si
  684.     mov    ax,dot            ;Current position in line
  685.     cmp    ax,offset dgroup:linebuf
  686.     jne    @char_left_5
  687.     stc                ;Dot already at beginning of line
  688.     jmp    short @char_left_99
  689. @char_left_5:
  690.     dec    ax            ;Move dot left
  691.     mov    dot,ax
  692. @char_left_99:
  693.     xchg    ax,si
  694.     lodsb                ;AL<-char at dot
  695.     @restore
  696.     ret
  697. char_left endp
  698.  
  699.  
  700.  
  701.  
  702.  
  703.  
  704.  
  705. ;+
  706. ; FUNCTION : char_right
  707. ;
  708. ;    Moves the 'dot' one character to the right unless
  709. ;    already at the end of the line.
  710. ;
  711. ; Parameters:
  712. ;    Global    dot is current position in the line.
  713. ;
  714. ; Returns:
  715. ;    AL    = char at new dot position. Undefined if new dot is at
  716. ;          the end of the line.
  717. ;    CF    = 1 if OLD dot was already at end of the line.
  718. ;          0 otherwise.
  719. ; Register(s) destroyed:
  720. ;-
  721. char_right proc    near
  722.     @save    si
  723.     mov    si,dot            ;Current position in line
  724.     mov    ax,lastchar        ;AX->Beyond last char
  725.     dec    ax            ;AX->last char in line
  726.     cmp    ax,si            ;Dot at end ?
  727.     jc    @char_right_99        ;Already at line end
  728.     inc    si            ;Move dot right, CF not affected
  729.     mov    dot,si
  730.     lodsb                ;AL<-char at dot, (undefined if
  731. ;                     dot is now at end of line).
  732. ;    CF    already clear
  733. @char_right_99:
  734.     @restore
  735.     ret
  736. char_right endp
  737.  
  738.  
  739.  
  740. ;+
  741. ; FUNCTION : go_bol
  742. ;
  743. ;    Sets    dot to pint to the beginning of the line
  744. ;
  745. ; Register(s) destroyed: None.
  746. ;-
  747. go_bol    proc    near
  748.     mov    dot,offset dgroup:linebuf
  749.     ret
  750. go_bol    endp
  751.  
  752.  
  753.  
  754. ;+
  755. ; FUNCTION : go_eol
  756. ;
  757. ;    Sets    dot to pint to the end of the line
  758. ;
  759. ; Register(s) destroyed: AX.
  760. ;-
  761. go_eol    proc    near
  762.     mov    ax,lastchar
  763.     mov    dot,ax
  764.     ret
  765. go_eol    endp
  766.  
  767.  
  768.  
  769.  
  770. ;+
  771. ; FUNCTION : match_file
  772. ;
  773. ;    match_file tries to expand the filename to the left of the
  774. ;    cursor. If there are several matching files, the longest common
  775. ;    prefix is placed on the line.
  776. ;
  777. ; Parameters:
  778. ;    None.
  779. ;
  780. ; Returns:
  781. ;    Nothing.
  782. ; Register(s) destroyed:
  783. ;-
  784. match_file proc    near
  785.     @save    si,di
  786.     push    bp
  787.     mov    bp,sp
  788.     sub    sp,64+44+2+2+2+2+2+2    ;Locals
  789. pname        equ    64        ;Storage for entire filename with path
  790. ffblk        equ    pname+44
  791. ffblk_attr     equ    ffblk-15h    ;Attr byte within ffblk
  792. ffblk_name     equ    ffblk-1Eh    ;filename within ffblk
  793. fname        equ    ffblk+2        ;Points to start of filename in name
  794. oldDTAseg     equ    fname+2
  795. oldDTAoff     equ    oldDTAseg+2
  796. lineptr        equ    oldDTAoff+2    ;Pointer to location in linebuf    
  797. remaining    equ    lineptr+2    ;Remembers remaining space in path
  798. breakstate    equ    remaining+2    ;Remembers break state
  799.  
  800.     mov    ax,3300h        ;Get current break state
  801.     int    21h            ;DL<-current break state
  802.     mov    byte ptr [bp-breakstate],dl ;Remember it
  803.     xor    dl,dl
  804.     mov    ax,3301h        ;Disable break check during
  805. ;                     disk i/O
  806.     int    21h
  807.     lea    di,[bp-pname]        ;OK 'cause SS==DS
  808.     mov    si,dot            ;Current line position
  809.     mov    cx,63            ;Max length of path
  810. @match_file_10:
  811.     cmp    si,offset dgroup:linebuf
  812.     je    @match_file_51        ;Beginning of line and filename
  813.     dec    si
  814.     mov    al,[si]            ;AL<-next char
  815. @match_file_25:
  816.     call    near ptr isspace
  817.     je    @match_file_50        ;Beginning of filename
  818. @match_file_45:                ;Check for next char if
  819. ;                     pathname not too long
  820.     loop    @match_file_10
  821.     jmp    @match_file_99        ;Pathname too long, just exit
  822. @match_file_50:
  823.     inc    si
  824. @match_file_51:
  825. ;    Copy    filename into ASCIIZ buffer
  826. ;    SI->first char of filename in path buffer
  827.     xor    dx,dx            ;Flags
  828.     mov    ax,63
  829.     sub    ax,cx            ;Length of name
  830.     mov    [bp-remaining],cx    ;remember num bytes left in
  831. ;                     path buffer
  832.     xchg    ax,cx            ;CX<-length of name
  833.     mov    [bp-lineptr],si        ;Save start of path name in linebuf
  834.     mov    [bp-fname],di        ;Remember start of filename in
  835. ;                     path buffer as well (assumed)
  836.     or    cx,cx            ;Too far for jcxz
  837.     jne    @match_file_55
  838.     jmp    @match_file_99        ;No name, just exit
  839. @match_file_55:
  840.     lodsb                ;AL<-next char
  841.     stosb                ;Store it
  842.     cmp    al,'.'
  843.     jne    @match_file_56
  844.     or    dl,1            ;Set flag to remember file type '.'
  845.     jmp    short @match_file_65    ;Check out next character
  846. @match_file_56:
  847.     cmp    al,'\'            ;Directory separator?
  848.     jne    @match_file_59
  849. @match_file_57:
  850.     mov    [bp-fname],di        ;Update start of filename in
  851. ;                     path buffer
  852. @match_file_58:
  853.     and    dl,0FEh            ;Forget file type flag
  854.     jmp    short @match_file_65
  855. @match_file_59:
  856.     cmp    al,'/'            ;Same thing
  857.     je    @match_file_57
  858.     cmp    al,':'            ;Disk?
  859.     jne    @match_file_65
  860.     and    dl,0FEh            ;Forget file type (shouldn't really 
  861. ;                     occur)
  862.     mov    [bp-fname],di        ;Update start of filename in
  863. ;                     path buffer
  864.  
  865. @match_file_65:
  866.     loop    @match_file_55
  867.  
  868.     mov    cx,[bp-remaining]    ;CX<-remaining space
  869.     jcxz    @match_file_52        ;Only space for terminator
  870.     mov    al,'*'
  871.     stosb                ;Attach a '*'
  872.     cmp    cl,3            ;Enough space for ".*"
  873.     jb    @match_file_52
  874.     and    dl,1            ;Saw a file type ?
  875.     jne    @match_file_52        ;Yes, go attach terminator
  876.     mov    [di],2A2Eh        ;Attach a ".*"
  877.     inc    di
  878.     inc    di
  879. @match_file_52:
  880.     xor    al,al            ;AL<-0
  881.     stosb                ;Terminating 0
  882.  
  883. ;    name    contains the filename
  884.     push    es
  885.     @GetDTA                ;Get and save old DTA
  886.     mov    [bp-oldDTAseg],es
  887.     mov    [bp-oldDTAoff],bx
  888.     pop    es
  889. ;
  890.     lea    dx,[bp-ffblk]
  891.     @SetDTA    dx            ;Set DTA to our DTA
  892.  
  893.     lea    dx,[bp-pname]        ;dx->ASCII name
  894.     @GetFirst dx,16            ;Include subdirs in search
  895.     jnc    @match_file_70        ;No error
  896.     call    near ptr bell        ;No files found
  897.     jmp    @match_file_90        ;Restore DTA and exit 
  898.  
  899.  
  900. @match_file_70:                ;At least one file found
  901.     mov    di,[bp-fname]        ;DI->filename portion
  902.     lea    si,[bp-ffblk_name]    ;Name returned by GetFirst
  903. @match_file_71:                ;Copy the file name
  904.     lodsb
  905.     stosb
  906.     or    al,al
  907.     jne    @match_file_71
  908.  
  909.     mov    al,SPACE        ;If file, add a space
  910.     test    byte ptr [bp-ffblk_attr],16 ;Subdirectory?
  911.     je    @match_file_72        ;No
  912.     mov    al,'\'            ;If subdir, add a backslash
  913. @match_file_72:
  914.     mov    byte ptr [di-1],al    ;Add a space or a '\'
  915.     mov    byte ptr [di],0
  916.  
  917. ;    Now hunt for more files. For each file found, keep the longest 
  918. ;    prefix in common so far.
  919.  
  920.     @GetNext            ;Get the next file name
  921.     jc    @match_file_80        ;No more files
  922.  
  923.     mov    di,[bp-fname]        ;DI->start of file name
  924.     lea    si,[bp-ffblk_name]    ;Name returned by GetNext
  925.     mov    cx,13            ;Max Length of field
  926.     repe    cmpsb            ;Compare strings
  927.     mov    byte ptr [di-1],0    ;Terminating null
  928.     jmp    short @match_file_72    ;Try for more files
  929.  
  930. @match_file_80:
  931. ;    Found one or more files, copy the longest common prefix
  932. ;    into the line buffer
  933.     mov    ax,[bp-lineptr]        ;AX->start of chars to be deleted
  934.     call    near ptr erase_to_dot    ;Delete characters between dot
  935. ;                     and start of name
  936.     lea    si,[bp-pname]        ;SI->name to be copied
  937.     mov    di,si
  938.     xor    al,al
  939.     mov    cx,64
  940.     repne    scasb            ;Hunt for terminating null
  941.     mov    ax,63
  942.     sub    ax,cx            ;AX<-length of string
  943. ; SI->string, AX is length
  944.     push    ax
  945.     call    near ptr xlate_lower    ;Convert to lowercase
  946.     pop    ax    
  947.     call    near ptr insert_at_dot    ;SI->source, AX == length
  948.  
  949. @match_file_90:
  950.     push    ds
  951.     mov    ds,[bp-oldDTAseg]
  952.     mov    dx,[bp-oldDTAoff]
  953.     @SetDTA    dx            ;Restore DTA
  954.     pop    ds
  955. @match_file_99:
  956. ; Restore previous state of break checking
  957.     mov    dl,byte ptr [bp-breakstate]
  958.     mov    ax,3301h
  959.     int    21h
  960.     mov    sp,bp
  961.     pop    bp
  962.     @restore
  963.     ret
  964. match_file endp
  965.  
  966.  
  967.  
  968. CSEG    ENDS
  969.  
  970.     END