home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / pcmagazi / 1989 / 22 / alias.asm next >
Assembly Source File  |  1989-09-28  |  80KB  |  2,563 lines

  1.         page    66,132
  2. ;============================================================================
  3. ; ALIAS.COM adds a command line stack, a command line editor, and
  4. ; an alias function to COMMAND.COM.  Syntax is:
  5. ;
  6. ;    ALIAS [alias [command]] [/F filename] [/S nn] [/U]
  7. ;             [/B] [/E] [/D] [/L] [/U] [/*] [//]
  8. ;
  9. ; where /B = Set size of buffer for future alias commands
  10. ;       /D = Disable alias translation
  11. ;       /E = Enable alias translation
  12. ;       /F = Filename of file with list of commands
  13. ;       /L = List aliases currently in list
  14. ;       /M = Set minimum command length to save
  15. ;       /S = Size of command line stack where "nn" is the number of commands
  16. ;            to save
  17. ;       /U = Uninstall the program
  18. ;       /* or // = Comment. Ignore remainder of the line.
  19. ;
  20. ;
  21. ; Revision History:
  22. ;
  23. ;     Version 1.0    Initial Release        PC Magazine Vol 8 Num 22
  24. ;
  25. ;============================================================================
  26.  
  27.         code    segment
  28.         assume    cs:code
  29.  
  30.         org    2ch
  31. env_segment    dw    ?            ;Word containing the segment
  32.                         ;  of the program's env. block.
  33.         org    80h
  34. command_tail    db    ?            ;Offset of the command tail.
  35.  
  36.         org    100h
  37.  
  38. main:        jmp    initialize
  39. program        db    13,10,"ALIAS 1.0 "
  40. copyright    db    "(c) 1989 Ziff Communications Co.",10,13
  41. authors        db    "PC Magazine ",254," Doug Boling and Jeff Prosise"
  42.         db    10,13,"$",1Ah
  43.  
  44. cmdcom_psp    dw    0            ;Segment of COMMAND.COM PSP
  45. master_env    dw    0            ;Segment of master environment
  46.  
  47. cef_pointer    dd    ?            ;Pointer to critical err flag
  48. dos_version    dw    0            ;DOS Version number
  49.  
  50. chk_alias    db    1            ;Alias enable flag.
  51. aliaslist_ptr    dd    ?                     ;Pointer to alias list.
  52. aliaslist_size    dw    0f600h            ;Pointer to end of list seg
  53. work_buff_ptr    dw    ?            ;Pointer to alias working buff
  54.  
  55. cmdstack_base    dw    ?
  56. cmdstack_size    dw    16            ;Size of command stack.
  57. minlength    db    1            ;Minimum len of cmd to stack
  58.  
  59. mystack_ptr    dw    offset end_of_resident + 512 ;Ptr to internal stack
  60. saved_ss    dw    ?
  61. saved_sp    dw    ?
  62. int21h        dd    -1            ;Int 21 vector (DOS)
  63. int2fh        dd    -1            ;Int 2f vector (DOS MULTIPLEX)
  64.  
  65. multiplex_id    db    0dbh            ;Program ID for multiplex int
  66.  
  67. points        dw    ?            ;Scan lines per character
  68. columns        db    ?            ;Number of screen columns
  69. cursor_mode    dw    ?            ;Cursor mode
  70. bufferptr    db    ?            ;Input buffer pointer
  71. next_ptr    dw    0            ;Address where next command
  72.                         ;  will be stored
  73. cmd_ptr        dw    0            ;Address of current command
  74.                         ;  in command stack
  75. insert_flag    db    0            ;0 = insert off, 1 = on
  76. exkeys        db    71,72,75,77,79,80    ;Extended keycode list
  77.         db    82,83,115,116,117
  78. exkeys_end    =    $
  79.  
  80. ex_entry    dw    offset ctrl_end        ;Jump table for extended
  81.         dw    offset ctrl_right    ;  keycodes
  82.         dw    offset ctrl_left
  83.         dw    offset delete
  84.         dw    offset toggle_ins
  85.         dw    offset next_cmd
  86.         dw    offset eol
  87.         dw    offset move_right
  88.         dw    offset move_left
  89.         dw    offset prev_cmd
  90.         dw    offset home
  91.  
  92. ;============================================================================
  93. ; DOSINT processes calls to interrupt 21h
  94. ;============================================================================
  95. dosint        proc    far
  96.         assume    cs:code,ds:nothing,es:nothing
  97.          cmp    ah,0ah            ;Check for char input
  98.          je    dosint_1            ;If so, continue
  99. goto_dos:
  100.         jmp    cs:[int21h]             ;else pass the call to DOS
  101. ;
  102. ;Compare the active PSP with COMMAND.COM PSP.
  103. ;
  104. dosint_1:
  105.         push    ax            ;Save registers
  106.         push    bx
  107.         mov    ah,51h            ;Get active PSP segment
  108.         cmp    word ptr cs:[dos_version],310h
  109.         jb    early_dos
  110.         pushf
  111.         call    cs:[int21h]
  112.         jmp    short chkpsp1
  113. early_dos:
  114.         push    es            ;If before DOS 3.1, set
  115.         les    bx,cs:[cef_pointer]    ;  critical error flag to
  116.         inc    byte ptr es:[bx]    ;  force DOS to use the aux
  117.         pushf                           ;  stack.
  118.         call    cs:[int21h]        ;Get active PSP segment
  119.         mov    ax,bx
  120.         les    bx,cs:[cef_pointer]    ;Reset critical error flag
  121.         dec    byte ptr es:[bx]
  122.         mov    bx,ax
  123.         pop    es
  124. chkpsp1:
  125.         cmp    bx,cs:[cmdcom_psp]
  126.         je    dosint_2
  127.         pop    bx            ;Else, cleanup and goto DOS
  128.         pop    ax
  129.         jmp    short goto_dos
  130. dosint_2:
  131.         cld                ;Set direction flag
  132.         mov    cs:[saved_ss],ss    ;Save SS:SP
  133.         mov    cs:[saved_sp],sp
  134.         cli
  135.         push    cs                      ;Move to internal stack
  136.         pop    ss
  137.         mov    sp,cs:[mystack_ptr]
  138.         sti
  139.         push    bp                      ;Save remaining registers.
  140.         mov    bp,sp            ;Set up stack access
  141.         push    cx
  142.         push    dx
  143.         push    di
  144.         push    si
  145.         push    ds
  146.         push    es
  147. ;
  148. ;The call is from COMMAND.COM. Invoke line editor.
  149. ;
  150.         push    dx
  151.         call    cmd_input
  152.         pop    dx
  153.         cmp    cs:[cmdstack_size],0
  154.         je    dosint_3
  155.         call    cmd_record
  156. ;
  157. ;Check for alias before returning to COMMAND.COM
  158. ;
  159. dosint_3:
  160.         cmp    cs:[chk_alias],0         ;See if alias translation
  161.         je    dosint_exit          ;  is enabled.
  162.         mov    si,[bp-4]        ;Get pointer to input buffer
  163.         inc     si
  164.         xor    cx,cx
  165.         or     cl,ds:[si]        ;Get length of buffer
  166.         je    dosint_exit        ;If buffer empty, exit.
  167.         inc    si            ;Point to 1st char in buffer
  168.         mov    ax,cs
  169.         mov    es,ax            ;Set ES to installed code.
  170.         call    searchalias        ;See if an alias is found.
  171.         jc    dosint_exit        ;No, exit.
  172. ;
  173. ;If alias found, copy it from alias list to internal buffer.
  174. ;
  175.         mov     si,di            ;Load SI with alias pointer
  176.         mov    ax,es
  177.         mov    ds,ax            ;Point DS to alias list seg
  178.         xor    cx,cx
  179.         mov    cl,ds:[si+3]        ;Get size of alias
  180.         call    getalias        ;Get alias from list
  181. ;
  182. ;Append remainder of command line to alias if no cmd line parameters were used.
  183. ;
  184.         or    dx,dx            ;See if any command line
  185.         jne    dosint_6        ;  parameters were used.
  186.         push    si            ;Save pointer to buffer.
  187.         push    ds
  188.         mov    di,si
  189.         add    di,cx            ;Point DI to end of alias
  190.         mov    dx,cx            ;Save length of alias
  191.         mov    si,[bp-4]        ;Point DS:SI to command.com
  192.         mov    ds,[bp-10]        ;  data buffer.
  193.         xor    cx,cx
  194.         inc    si
  195.         mov    cl,[si]            ;Get length of command line.
  196.         cmp    ah,cl            ;See if enough space in
  197.         ja    dosint_4        ;  internal buffer. If not
  198.         mov    cl,ah            ;  copy only until buff full.
  199. dosint_4:
  200.         inc    si
  201.         mov    bl,1             ;Skip past alias.
  202.         call    scan4char
  203.         jc    dosint_5
  204.         dec    si            ;Back up 1 char
  205.         inc    cx
  206.         add    dx,cx            ;Add length of command line.
  207.         rep    movsb            ;Copy command line
  208. dosint_5:
  209.         mov    cx,dx            ;Restore length of command
  210.         pop    ds            ;Restore pointer
  211.         pop    si
  212. ;
  213. ;Copy alias from internal buffer to COMMAND.COM data buffer.
  214. ;
  215. dosint_6:
  216.         mov    di,[bp-4]        ;Point ES:DI to command.com
  217.         mov    es,[bp-10]        ;  data buffer.
  218.         mov    al,es:[di]        ;Get size of data buffer
  219.         dec    al            ;If alias longer than buffer,
  220.         cmp    al,cl            ;  copy only the enough
  221.         ja     dosint_7        ;  characters to fill the
  222.         xor    cx,cx            ;  buffer.
  223.         mov     cl,al
  224. dosint_7:
  225.         inc    di            ;Move DI past length bytes
  226.         mov    es:[di],cl        ;Save length of command
  227.         inc    di
  228.         rep    movsb            ;Copy alias.
  229.         mov    byte ptr es:[di],13     ;Append carriage return
  230. dosint_exit:
  231.         mov    cx,cs:[cursor_mode]    ;Set default cursor
  232.         mov    ah,1
  233.         int    10h
  234.         pop    es
  235.         pop    ds
  236.         pop    si
  237.         pop    di
  238.         pop    dx
  239.         pop    cx
  240.         pop    bp
  241.             cli
  242.         mov    ss,cs:[saved_ss]    ;Restore stack pointer
  243.         mov    sp,cs:[saved_sp]
  244.         pop    bx
  245.         pop    ax
  246.         iret                ;Return to COMMAND.COM
  247. dosint        endp
  248.  
  249. ;-----------------------------------------------------------------------------
  250. ; GETALIAS Copies an alias from the alias list while substituting any
  251. ;          environment variables and command line parameters.
  252. ; Entry:  DS:SI - pointer to alias
  253. ; Exit:   DS:SI - pointer to buffer containing translated alias.
  254. ;            AH - free space in buffer
  255. ;            CX - length of the alias
  256. ;-----------------------------------------------------------------------------
  257. getalias    proc    near
  258.         mov    di,work_buff_ptr    ;Point DI to internal buffer
  259.         xor    ax,ax               ;Point to command by adding
  260.         mov    al,ds:[si+2]        ;  the size of the alias to
  261.         add    si,ax               ;  pointer to the entry.
  262.         add    si,4            ;Move past list data.
  263.         mov    ah,126            ;AH contains max size of buff
  264.         xor    dx,dx            ;Clear flag for line params
  265. alias_1:
  266.         lodsb                ;Get byte from alias
  267.         cmp    al,"%"            ;See if special character
  268.         je     alias_3            ;Yes, process special char.
  269. alias_2:
  270.         stosb                ;Store byte from alias
  271.         dec    ah            ;Dec buffer size counter
  272.         jz    alias_6            ;If internal buffer full, done
  273.         loop    alias_1
  274.         jmp    short alias_6        ;If at end of alias, done
  275. ;
  276. ;A percent sign has been found indicating a 'soft' parameter.
  277. ;
  278. alias_3:
  279.         mov    al,ds:[si]        ;Get character after %
  280.         cmp    al,"%"            ;If double %, include in one
  281.         je    alias_4            ;  % in alias.
  282.                 mov    bh,al              ;Copy and check to see if
  283.         sub    bh,"0"            ;  the next char is a number.
  284.         jb    alias_5         ;  If so, assume a line
  285.         cmp    bh,9                    ;  parameter.
  286.         ja    alias_5
  287.          call    sublineparam        ;Substitute a line paramter
  288.         inc    dx
  289. alias_4:
  290.         inc     si            ;Move SI past number or
  291.         dec    cx            ;  trailing % sign.
  292.         loop    alias_1
  293.         jmp    short alias_6        ;If at end of alias, done
  294. alias_5:
  295.          call    subenvvar        ;Substitute an environment var
  296.         loop    alias_1
  297. alias_6:
  298.         mov    si,work_buff_ptr    ;Point SI to internal buffer
  299.         mov    cx,di            ;Compute size of completed
  300.         sub    cx,si                     ;  alias.
  301.         ret
  302. getalias    endp
  303.  
  304. ;-----------------------------------------------------------------------------
  305. ; SUBLINEPARAM substitutes a parameter from the command line into the alias.
  306. ; Entry:  DS:SI - pointer to alias
  307. ;         ES:DI - pointer to buffer to copy the line parameter
  308. ;            AH - remaining space in the internal buffer
  309. ;            BH - binary number of the line parameter
  310. ;            CX - length of the alias
  311. ; Exit:   ES:DI - pointer to byte after the parameter in the buffer
  312. ;         DS:SI - pointer to the character after the line parameter number
  313. ;            CX - remaining length of the alias
  314. ;-----------------------------------------------------------------------------
  315. sublineparam    proc    near
  316.         push    cx
  317.         push    si
  318.         push    ds
  319.         mov    si,[bp-4]        ;Get pointer to command.com
  320.         mov    ds,[bp-10]        ;  data buffer.
  321.         xor    cx,cx
  322.         mov    cl,ds:[si+1]        ;Get number of chars in buffer.
  323.         inc    si            ;Point to the first byte of
  324.         inc    si            ;  data.
  325. sublineparam_1:
  326.         or    bh,bh            ;Check count of param to find.
  327.         jz    sublineparam_2
  328.         mov    bl,1
  329.         call    scan4char        ;Find next space
  330.         jc    sublineparam_exit
  331.         dec    bl
  332.         call    scan4char        ;Find next word
  333.         jc    sublineparam_exit
  334.         dec    bh            ;Dec parameter count
  335.         jne    sublineparam_1        ;If not done, loop back.
  336.         dec    si            ;Backup to 1st char in word.
  337. sublineparam_2:
  338.         lodsb                ;Get character from parameter
  339.         cmp    al," "            ;If space, parameter done
  340.         jbe    sublineparam_exit
  341.         stosb
  342.         dec    ah            ;Dec buffer size counter
  343.         jnz    sublineparam_2
  344. sublineparam_exit:
  345.         pop    ds
  346.         pop    si
  347.         pop    cx
  348.         ret
  349. sublineparam    endp
  350.  
  351. ;-----------------------------------------------------------------------------
  352. ; SUBENVVAR substitutes an environment variable into alias.
  353. ; Entry:  DS:SI - pointer to variable to substitute
  354. ;         ES:DI - pointer to buffer to copy the contents of the variable
  355. ;            AH - remaining space in internal buffer
  356. ;            CX - length of alias string
  357. ; Exit:   DS:SI - pointer to the byte after the variable name
  358. ;         ES:DI - pointer to the byte after the variable contents
  359. ;            CF - set if variable not found
  360. ;-----------------------------------------------------------------------------
  361. subenvvar      proc    near
  362.         push    dx
  363.         push    ds
  364.         push    es
  365. ;
  366. ;Compute the length of the variable name.
  367. ;
  368.         mov    bx,di                    ;Save pointer to internal buff
  369.         mov    di,si                   ;Compute the length of the
  370.         mov      dx,cx                   ;  environment variable by
  371.         mov    al,"%"                  ;  searching for the trailing
  372.         repne    scasb                   ;  % sign.
  373.         sub    dx,cx            ;Compute length of variable.
  374.         dec    dx            ;Subtract % byte fron length.
  375.         push    di            ;Save ptr to end of env var.
  376. ;
  377. ;Search the Master Environment block for the variable pointed to by DS:SI
  378. ;
  379.         mov    es,cs:[master_env]    ;Get segment of master env blk
  380.         xor    di,di            ;Point ES:DI to environment.
  381.         push    cx            ;Save alias size.
  382.         push    bx            ;Save ptr to internal buffer
  383.         mov     bx,si            ;Save pointer to var name
  384. subenvvar_1:
  385.         mov    si,bx            ;Get back ptr to var name.
  386.         mov    cx,dx            ;Compare env var to var in
  387.         repe    cmpsb                   ;  alias.
  388.         je    subenvvar_2        ;Variable found, exit loop
  389.         xor    al,al            ;Find next environment var.
  390.         mov    cx,-1              ;Scan the entire segment.
  391.         repne    scasb
  392.         cmp    byte ptr es:[di],0    ;If double zero, end of env
  393.         jne    subenvvar_1        ;  block. else, loop back.
  394.         pop    di                      ;Restore DI and exit
  395.         jmp    short subenvvar_exit
  396. ;
  397. ;Environment variable found. Substitute into alias.
  398. ;
  399. subenvvar_2:
  400.         mov    si,es            ;DS:SI points to env string
  401.         mov    ds,si            ;ES:DI points to internal buff
  402.         mov     si,cs
  403.         mov    es,si
  404.         mov    si,di            ;Copy pointer to var contents.
  405.         pop    di               ;Restore ptr to internal buff
  406. subenvvar_3:
  407.         lodsb                ;Move environment pointer past
  408.         cmp    al,"="            ;  the equals sign.
  409.         jne    subenvvar_3
  410. subenvvar_4:
  411.         lodsb                ;Move pointer to first
  412.         cmp    al," "            ;  non-space character.
  413.         jb    subenvvar_4
  414. subenvvar_5:
  415.         or    al,al            ;See if at the end of variable
  416.         je    subenvvar_exit
  417.         stosb                ;Save character in command
  418.         lodsb                ;Get next character
  419.         dec    ah            ;Dec buffer size count.
  420.         jne    subenvvar_5        ;If buffer not full, continue
  421. subenvvar_exit:
  422.         pop    cx            ;Restore alias length
  423.         pop    si            ;Restore alias pointer
  424.         pop    es            ;Restore segment registers
  425.         pop    ds
  426.         pop    dx
  427.         ret
  428. subenvvar    endp
  429.  
  430. ;-----------------------------------------------------------------------------
  431. ; SUBKEY searches the alias list for a key substitution
  432. ; Entry:  AL - extended key code
  433. ; Exit:   CF - clear if key found, set if not found
  434. ;         DX - offset address of matching entry in alias list (if CF = 0)
  435. ;         CX - length of matching entry (if CF = 0)
  436. ;-----------------------------------------------------------------------------
  437. subkey        proc    near
  438.         push    bx
  439.         push    di
  440.         push    si
  441.         push    ds
  442.         push    es
  443.                 xor    ah,ah            ;Indicate extended code.
  444.         les    di,cs:[aliaslist_ptr]    ;Get pointer to alias list.
  445. subkey_1:
  446.         mov    dx,es:[di]        ;Get next entry offset
  447.         cmp    dx,-1            ;See if at the end of the list
  448.         je    subkey_notfound
  449.         cmp    es:[di+4],ax        ;Check for key code.
  450.         je    subkey_found        ;If found, exit loop
  451. subkey_2:
  452.         add    di,dx             ;Else, point to next entry.
  453.         jmp    short subkey_1
  454. ;
  455. ;Copy alias into internal buffer.
  456. ;
  457. subkey_found:
  458.         mov     si,di            ;Load SI with alias pointer
  459.         mov    ax,es
  460.         mov    ds,ax            ;Point DS to alias list seg
  461.         xor    cx,cx
  462.         mov    cl,ds:[si+3]        ;Get size of alias
  463.         call    getalias        ;Get alias from list
  464.         mov    dx,si            ;Copy pointer to buffer
  465.         clc                ;Set key found flag
  466. subkey_exit:
  467.         pop    es
  468.         pop    ds
  469.         pop    si
  470.         pop    di
  471.         pop    bx
  472.         ret
  473. subkey_notfound:
  474.         stc                ;Set key not found flag
  475.         jmp    subkey_exit
  476. subkey        endp
  477.  
  478. ;-----------------------------------------------------------------------------
  479. ; SEARCHALIAS searches the alias list for a matching alias.
  480. ; Entry:  DS:SI - pointer to alias
  481. ;            ES - segment of installed code
  482. ;            CX - length input buffer
  483. ; Exit:      CF - clear if alias found
  484. ;         ES:DI - pointer to matching entry in alias list, if CF is clear
  485. ;-----------------------------------------------------------------------------
  486. searchalias    proc    near
  487.         push    bx            ;Save registers
  488.         push    cx
  489.         push    si
  490.         xor    bx,bx
  491. searchalias_1:
  492.         lodsb                           ;Compute the length of the
  493.         or     al,al                   ;  length of the alias by
  494.         je    searchalias_2             ;  finding the next space.
  495.         cmp    al," "                  ;Allow zero byte in alias
  496.         jbe    searchalias_3           ;  for function key labels.
  497. searchalias_2:
  498.         inc    bx
  499.          loop    searchalias_1
  500. searchalias_3:
  501.         pop    si
  502.         les    di,es:[aliaslist_ptr]    ;Get pointer to alias list.
  503.         mov    cx,bx            ;Get length of alias
  504. searchalias_4:
  505.         mov    bx,es:[di]
  506.         cmp    bx,-1            ;See if at the end of the list
  507.         je    searchalias_notfound
  508.         cmp    es:[di+2],cl        ;Compare lengths
  509.         jne    searchalias_5
  510.         push    cx            ;Save size and starting
  511.         push    di                      ;  pointers.
  512.         push    si
  513.         add    di,4            ;Point to start of alias field.
  514.         repe    cmpsb            ;Compare alias to input string
  515.         pop    si
  516.         pop    di
  517.         pop    cx
  518.         je    searchalias_6        ;If found, exit loop
  519. searchalias_5:
  520.         add    di,bx            ;Else, point to next entry.
  521.         jmp    short searchalias_4
  522. searchalias_6:
  523.         clc                ;Set alias found flag
  524. searchalias_exit:
  525.         pop    cx
  526.         pop    bx
  527.         ret
  528. searchalias_notfound:
  529.         stc
  530.         jmp    short searchalias_exit
  531. searchalias    endp
  532.  
  533. ;-----------------------------------------------------------------------------
  534. ; SCAN4CHAR scans a string to find the first character.
  535. ; Entry:  SI - pointer to ASCII string
  536. ;         BL - 0 = find next char, 1 = find next space
  537. ;         CX - file length
  538. ; Exit:   AL - first nonspace character
  539. ;         CF - set if carriage return found
  540. ;-----------------------------------------------------------------------------
  541. scan4char      proc near
  542.         assume    ds:nothing,es:nothing
  543. scan4loop:
  544.         jcxz    scan4_eol        ;See if at the end of the file.
  545.         lodsb
  546.         dec    cx                 ;Decrement file length counter.
  547.         cmp    al,13            ;Check for carriage return.
  548.         jne    scan4_1
  549. scan4_eol:
  550.         stc
  551.         jmp    short scan4_exit1
  552. scan4_1:
  553.         or    bl,bl            ;Check if searching for space
  554.         jne    scan4_2            ;  or character.
  555.         cmp    al," "            ;Check for space or other
  556.         jbe    scan4loop        ;  'white' characters.
  557.         jmp    short scan4_exit
  558. scan4_2:
  559.         cmp    al," "            ;Check for characters.
  560.         ja    scan4loop
  561. scan4_exit:
  562.         clc
  563. scan4_exit1:
  564.          ret
  565. scan4char    endp
  566.  
  567. ;----------------------------------------------------------------------------
  568. ; CMD_INPUT replaces DOS' 0Ah text input function.
  569. ;----------------------------------------------------------------------------
  570. cmd_input    proc    near
  571.         push    ds            ;Save DS
  572.         xor    ax,ax            ;Then zero it
  573.         mov    ds,ax
  574.         mov    ax,ds:[0485h]        ;Get number of scan lines
  575.         cmp    ax,cs:[points]        ;  per character and branch
  576.         je    cmd1            ;  if it hasn't changed
  577.  
  578.         mov    cs:[points],ax        ;Record new number of scan
  579.         mov    ax,ds:[0460h]        ;  lines per character and
  580.         mov    cs:[cursor_mode],ax    ;  cursor mode
  581. cmd1:
  582.         pop    ds            ;Restore DS
  583.         call    set_cursor        ;Set cursor mode
  584.  
  585.         mov    ah,15            ;Get video page and columns
  586.         int    10h
  587.         dec    ah            ;Calculate max column number
  588.         mov    cs:[columns],ah        ;Save it
  589.         mov    ax,ds            ;Point ES:DI to buffer
  590.         mov    es,ax
  591.         mov    di,dx
  592.         add    di,2
  593.         mov    si,dx            ;Point DS:SI to character count
  594.         inc    si
  595.         mov    byte ptr [si],0        ;Zero initial count
  596.         mov    cs:[bufferptr],1    ;Set initial index value
  597.         cld                ;Clear DF
  598. ;
  599. ;Wait for a keycode to appear in the keyboard buffer.
  600. ;
  601. getkey:        mov    ah,0Bh            ;Check buffer for keycode
  602.         int    21h
  603.         or    al,al            ;Anything there?
  604.         jne    getchar            ;Yes, then go get it
  605.         int    28h            ;No, then execute interrupt 28h
  606.         jmp    getkey            ;Loop back for another try
  607. ;
  608. ;Read the keycode and process it if it's not an extended code.
  609. ;
  610. getchar:
  611.         mov    ah,8            ;Read character from buffer
  612.         int    21h
  613.         or    al,al            ;Is it an extended code?
  614.         je    excode            ;Yes, then branch
  615.  
  616.         cmp    al,8            ;Backspace key?
  617.         jne    getc1            ;No, then branch
  618.         call    backspace        ;Rub out a character
  619.         jmp    getkey            ;Return to loop
  620. getc1:
  621.         cmp    al,9            ;Tab key?
  622.         jne    getc2            ;No, then branch
  623.         call    tab            ;Tab to next tab boundary
  624.         jmp    getkey            ;Return to loop
  625. getc2:
  626.         cmp    al,27            ;ESC key?
  627.         jne    getc3            ;No, then branch
  628.         call    clear_line        ;Yes, then clear input line
  629.         mov    cs:[cmd_ptr],0        ;Zero current command pointer
  630.         jmp    getkey
  631. getc3:
  632.         cmp    al,7Fh            ;Ctrl-Backspace?
  633.         jne    getc4            ;No, then branch
  634.         call    ctrl_bs            ;Yes, then delete word
  635.         jmp    getkey
  636. getc4:
  637.         cmp    al,13            ;ENTER key?
  638.         je    enter            ;Yes, then branch
  639.         call    printchar        ;No, then print the character
  640. getc5:
  641.         jmp    getkey
  642. enter:
  643.         call    eol            ;Place cursor at end-of-line
  644.         mov    byte ptr es:[di],13    ;Insert carriage return code
  645.         mov    ah,2            ;Advance to next line
  646.         mov    dl,13
  647.         int    21h
  648. get_exit:
  649.         ret
  650. ;
  651. ;Process extended keycodes.
  652. ;
  653. excode:
  654.         mov    ah,8            ;Read extended code
  655.         int    21h
  656.  
  657.                 cmp    al,3Bh            ;See if below F1
  658.         jb    excode3
  659.         cmp    al,71h            ;See if above Alt-F10
  660.         ja    excode3
  661.                 cmp    al,54h            ;See if above Shift-F1
  662.         jae    excode1
  663.         cmp    al,44h            ;See if above F10
  664.         ja    excode3
  665. excode1:
  666.         call    subkey            ;Scan alias list for match
  667.         jc    getkey            ;Exit if no match found
  668.         push    cx
  669.         push    dx
  670.         call    clear_line        ;Clear command line
  671.         pop    dx
  672.         pop    cx
  673. excode2:
  674.         push    si
  675.         mov    si,dx            ;Copy offset address into SI
  676.         mov    al,byte ptr cs:[si]    ;Get next character
  677.         pop    si
  678.         cmp    al,13            ;Exit and execute command
  679.         je    enter            ;  on carriage return
  680.         inc    dx
  681.         push    cx
  682.         push    dx
  683.         call    printchar        ;Print it
  684.         pop    dx
  685.         pop    cx
  686.         jc    getc5
  687.         loop    excode2            ;Loop until done
  688.         jmp    getkey            ;Return to input loop
  689. excode3:
  690.         push    es            ;Save buffer address
  691.         push    di
  692.         mov    cx,cs            ;Point ES:DI to list of
  693.         mov    es,cx            ;  supported keycodes
  694.         mov    di,offset exkeys
  695.         mov    cx,offset exkeys_end - offset exkeys
  696.         repne    scasb            ;Scan list
  697.         pop    di            ;Clear the stack
  698.         pop    es
  699.         jne    excode4            ;Ignore if key not found
  700.         shl    cx,1            ;Convert CX to address
  701.         add    cx,offset ex_entry
  702.         push    bx            ;Save page number in BH
  703.         mov    bx,cx            ;Get entry address from table
  704.         mov    ax,cs:[bx]
  705.         pop    bx            ;Restore BH
  706.         call    ax            ;Call handling routine
  707. excode4:
  708.         jmp    getkey            ;Return to input loop
  709. cmd_input    endp
  710.  
  711. ;------------------------------------------------------------------------------
  712. ; PREV_CMD outputs the previous command in the command stack.
  713. ;------------------------------------------------------------------------------
  714. prev_cmd    proc    near
  715.         mov    dx,cs:[cmd_ptr]        ;Get current stack index
  716.         cmp    dx,cs:[cmdstack_size]    ;Exit if at top of command
  717.         je    prev_exit        ;  stack
  718.         or    dx,dx            ;Branch if not at bottom of
  719.         jnz    prev1            ;  command stack
  720. ;
  721. ;Copy the current contents of the command line to the search buffer.
  722. ;
  723.         mov    cl,[si]            ;Get count of characters on
  724.         xor    ch,ch            ;  command line in CX
  725.         inc    cx
  726.         push    es            ;Save registers
  727.         push    di
  728.         push    si
  729.         mov    ax,cs            ;Point ES:DI to search text
  730.         mov    es,ax            ;  buffer
  731.         mov    di,offset command_tail
  732.         rep    movsb            ;Copy command line text
  733.         pop    si            ;Restore registers
  734.         pop    di
  735.         pop    es
  736. ;
  737. ;Search for the previous command and output it.
  738. ;
  739. prev1:
  740.         inc    dx            ;Increment stack index
  741.         mov    ax,cs:[next_ptr]    ;Get stack base index
  742.         sub    ax,dx            ;Calculate address of previous
  743.         cmp    ax,0            ;  command
  744.         jge    prev2
  745.         add    ax,cs:[cmdstack_size]
  746. prev2:
  747.         mov    cl,7            ;Calculate offset address of
  748.         shl    ax,cl            ;  the command
  749.         add    ax,cs:[cmdstack_base]
  750.         cmp    byte ptr cs:[command_tail],0    ;Output command if there is
  751.         je    prev3            ;  no search criterion
  752.         call    check_string        ;Compare strings
  753.         jz    prev3            ;Output command if the strings
  754.         cmp    dx,cs:[cmdstack_size]    ;  match
  755.         jne    prev1
  756.         ret                ;Exit if at top of stack
  757. prev3:
  758.         push    si            ;Save SI
  759.         mov    si,ax            ;Transfer address to SI
  760.         cmp    byte ptr cs:[si],0    ;Valid command?
  761.         pop    si            ;Restore SI
  762.         je    prev_exit        ;No, then ignore keypress
  763.         mov    cs:[cmd_ptr],dx        ;Save new command pointer
  764.         call    write_command        ;Output the command string
  765. prev_exit:
  766.         ret
  767. prev_cmd    endp
  768.  
  769. ;------------------------------------------------------------------------------
  770. ; NEXT_CMD outputs the next command in the command stack.
  771. ;------------------------------------------------------------------------------
  772. next_cmd    proc    near
  773.         mov    dx,cs:[cmd_ptr]        ;Get current stack index
  774.         or    dx,dx            ;Exit if it's zero
  775.         jz    next_exit
  776. next1:
  777.         dec    dx            ;Decrement stack index
  778.         mov    cs:[cmd_ptr],dx        ;Save command pointer
  779.         or    dx,dx            ;Clear line and exit if
  780.         jz    next3            ;  the result is zero
  781.         mov    ax,cs:[next_ptr]    ;Get stack base index
  782.         sub    ax,dx            ;Calculate address of next
  783.         cmp    ax,0            ;  command
  784.         jge    next2
  785.         add    ax,cs:[cmdstack_size]
  786. next2:
  787.         mov    cl,7            ;Calculate offset address of
  788.         shl    ax,cl            ;  command
  789.         add    ax,cs:[cmdstack_base]
  790.         cmp    byte ptr cs:[command_tail],0    ;Output command if there is
  791.         je    next4            ;  no search criterion
  792.         call    check_string        ;Compare strings
  793.         jz    next4            ;Output command if the strings
  794.         jmp    next1            ;  match
  795. next3:
  796.         call    clear_line
  797.         cmp    byte ptr cs:[command_tail],0
  798.         je    next_exit
  799.         mov    ax,offset command_tail
  800. next4:
  801.         call    write_command        ;Output the command string
  802. next_exit:
  803.         ret
  804. next_cmd    endp
  805.  
  806. ;------------------------------------------------------------------------------
  807. ; CHECK_STRING compares the string in the search buffer with another string.
  808. ; Entry:  AX - string address
  809. ; Exit:   ZF - set if strings are equivalent, clear if they are not
  810. ;------------------------------------------------------------------------------
  811. check_string    proc    near
  812.         push    ds            ;Save registers
  813.         push    si
  814.         push    es
  815.         push    di
  816.         mov    cx,cs            ;Point DS and ES to
  817.         mov    ds,cx            ;  code segment
  818.         mov    es,cx
  819.         mov    si,offset command_tail    ;Point DS:SI to text in
  820.         mov    cl,[si]            ;  search buffer
  821.         xor    ch,ch
  822.         inc    si
  823.         mov    di,ax            ;Point DI to other string
  824.         inc    di            ;
  825.         repe    cmpsb            ;Compare strings
  826.         pop    di            ;Restore registers
  827.         pop    es
  828.         pop    si
  829.         pop    ds
  830.         ret
  831. check_string    endp
  832.  
  833. ;------------------------------------------------------------------------------
  834. ; PRINT_STRING writes an ASCII string to the command line.
  835. ; Entry:  DS:SI - string address
  836. ;            CX - number of characters
  837. ;------------------------------------------------------------------------------
  838. print_string    proc    near
  839.         jcxz    ps_exit            ;Exit if no characters
  840.         push    dx
  841.         cld
  842.         mov    ah,2            ;Print the character
  843. ps1:
  844.         lodsb                ;Get a byte
  845.         mov    dl,al            ;Transfer it to DL
  846.         int    21h            ;Output character
  847.         loop    ps1            ;Loop until done
  848.         pop    dx
  849. ps_exit:
  850.         ret
  851. print_string    endp
  852.  
  853. ;------------------------------------------------------------------------------
  854. ; WRITE_COMMAND outputs a command string.
  855. ; Entry:  AX - string offset address
  856. ; Exit:   AL - character after string
  857. ;------------------------------------------------------------------------------
  858. write_command    proc    near
  859.         push    ax            ;Save address
  860.         call    clear_line        ;Clear input line
  861.         pop    ax            ;Retrieve string address
  862.         push    ds            ;Save DS and SI
  863.         push    si
  864.         push    cs            ;Point DS to string segment
  865.         pop    ds
  866.         mov    si,ax            ;Point SI to the string
  867.         mov    cl,[si]            ;Get string length
  868.         xor    ch,ch
  869.         mov    byte ptr es:[di-1],cl    ;Store string length
  870.         inc    si            ;Advance SI to string text
  871. write1:
  872.         mov    ah,2            ;Print one character
  873.         mov    dl,[si]
  874.         int    21h
  875.         movsb                ;Transfer character to buffer
  876.         inc    cs:[bufferptr]        ;Advance pointer
  877.         loop    write1            ;Loop until done
  878.         lodsb                ;Get first character after string
  879.         pop    si            ;Restore registers
  880.         pop    ds
  881.         ret
  882. write_command    endp
  883.  
  884. ;------------------------------------------------------------------------------
  885. ; TOGGLE_INS toggles the insert flag.
  886. ;------------------------------------------------------------------------------
  887. toggle_ins    proc    near
  888.         xor    cs:[insert_flag],1    ;Toggle insert flag
  889.         call    set_cursor        ;Set cursor mode
  890.         ret
  891. toggle_ins    endp
  892.  
  893. ;------------------------------------------------------------------------------
  894. ; TAB tabs to the next tab boundary.
  895. ;------------------------------------------------------------------------------
  896. tab        proc    near
  897.         mov    al,cs:[bufferptr]    ;Calculate number of
  898.         dec    al            ;  spaces to insert for
  899.         xor    ah,ah            ;  soft tab
  900.         mov    bl,8
  901.         div    bl
  902.         mov    cx,8
  903.         sub    cl,ah
  904. tab1:
  905.         push    cx            ;Print spaces
  906.         mov    al,32
  907.         call    printchar
  908.         pop    cx
  909.         jc    tab_exit
  910.         loop    tab1
  911. tab_exit:
  912.         ret
  913. tab        endp
  914.  
  915. ;------------------------------------------------------------------------------
  916. ; BACKSPACE deletes the character left of the cursor.
  917. ;------------------------------------------------------------------------------
  918. backspace    proc    near
  919.         cmp    cs:[bufferptr],1    ;At beginning of command line?
  920.         je    bs_exit            ;Yes, then ignore it
  921.         mov    cl,[si]            ;Get count
  922.         sub    cl,cs:[bufferptr]    ;Calculate distance to end-of-line
  923.         inc    cl
  924.         xor    ch,ch
  925.         push    cx            ;Save it
  926.         jcxz    bs1            ;Branch if at end-of-line
  927. ;
  928. ;Shift all characters right of the cursor in the buffer one slot left.
  929. ;
  930.         push    si            ;Save SI and DI
  931.         push    di
  932.         mov    si,di            ;Position them for shifts
  933.         dec    di
  934.         rep    movsb            ;Shift characters right of cursor
  935.         pop    di            ;Restore registers
  936.         pop    si
  937. ;
  938. ;Display the new string and update input parameters.
  939. ;
  940. bs1:
  941.         call    move_left        ;Move cursor left
  942. bs2:
  943.         pop    cx            ;Retrieve shift count
  944.         push    dx            ;Save cursor position
  945.         push    si            ;Save SI
  946.         mov    si,di            ;Point SI to new part of string
  947.         call    print_string        ;Print the new part
  948.         mov    ah,2            ;Blank the last character
  949.         mov    dl,32
  950.         int    21h
  951.         pop    si            ;Restore registers
  952.         pop    dx            ;Restore cursor address
  953.         mov    ah,2            ;Reset the cursor
  954.         int    10h
  955.         dec    byte ptr [si]        ;Decrement character count
  956. bs_exit:
  957.         ret
  958. backspace    endp
  959.  
  960. ;------------------------------------------------------------------------------
  961. ; PRINTCHAR writes a new character to the input buffer and echoes it.
  962. ; Entry:  AL - character to print
  963. ; Exit:   CF clear if character printed
  964. ;         CF set if buffer full
  965. ;------------------------------------------------------------------------------
  966. printchar    proc    near
  967.         cmp    cs:[insert_flag],0    ;Insert state on?
  968.         jne    print3            ;Yes, then branch
  969. ;
  970. ;Print a character in overstrike mode.
  971. ;
  972.         mov    cl,[si]            ;Get count
  973.         cmp    cl,cs:[bufferptr]    ;End-of-line?
  974.         jae    print2            ;No, then branch
  975.         mov    cl,[si-1]        ;Get maximum length
  976.         sub    cl,[si]            ;Subtract current length
  977.         cmp    cl,1            ;Buffer full?
  978.         je    beep            ;Yes, then branch
  979. print1:
  980.         inc    byte ptr [si]        ;Increment count
  981. print2:
  982.         stosb                ;Deposit new character
  983.         mov    ah,2            ;Then print it
  984.         mov    dl,al
  985.         int    21h
  986.         inc    cs:[bufferptr]        ;Advance buffer pointer
  987. print_exit:
  988.         clc                ;Clear CF and exit
  989.         ret
  990. beep:
  991.         mov    ax,0E07h        ;Print ASCII 7 thru BIOS
  992.         int    10h
  993.         stc
  994.         ret
  995. ;
  996. ;Print a character in insert mode.
  997. ;
  998. print3:
  999.         mov    cl,[si-1]        ;Get maximum length
  1000.         sub    cl,[si]            ;Subtract current count
  1001.         cmp    cl,1            ;Buffer full?
  1002.         je    beep            ;Yes, then branch
  1003.         mov    cl,[si]            ;Get count
  1004.         cmp    cl,cs:[bufferptr]    ;End-of-line?
  1005.         jb    print1            ;Yes, then branch
  1006.         sub    cl,cs:[bufferptr]    ;Calculate number of shifts
  1007.         inc    cl
  1008.         xor    ch,ch
  1009.         push    cx            ;Save shift count
  1010.         push    si            ;Save SI
  1011.         add    di,cx            ;Position DI to end-of-line
  1012.         mov    si,di            ;Position SI just before it
  1013.         dec    si
  1014.         std                ;Set DF for now
  1015.         rep    movsb            ;Make room for new character
  1016.         cld                ;Clear DF
  1017.         pop    si            ;Restore SI
  1018.         mov    es:[di],al        ;Deposit new character
  1019.         mov    ah,3            ;Get cursor position
  1020.         int    10h
  1021.         pop    cx            ;Retrieve shift count
  1022.         inc    cx            ;Increment it
  1023.         push    dx            ;Save cursor position
  1024.         push    si            ;Save SI
  1025.         mov    si,di            ;Point SI to current location
  1026.         call    print_string        ;Print new part of string
  1027.         pop    si            ;Restore SI and DX
  1028.         pop    dx
  1029.         mov    ah,2            ;Reset cursor position
  1030.         int    10h
  1031.         inc    byte ptr [si]        ;Add to character count
  1032.         call    move_right        ;Move cursor right
  1033.         jmp    print_exit
  1034. printchar    endp
  1035.  
  1036. ;------------------------------------------------------------------------------
  1037. ; DELETE deletes the character at the cursor.
  1038. ;------------------------------------------------------------------------------
  1039. delete        proc    near
  1040.         mov    cl,[si]            ;Get count
  1041.         cmp    cl,cs:[bufferptr]    ;End-of-line?
  1042.         jb    del2            ;Yes, then ignore keypress
  1043.         sub    cl,cs:[bufferptr]    ;Calculate number of shifts
  1044.         xor    ch,ch            ;Byte to word in CX
  1045.         push    cx            ;Save shift count
  1046.         jcxz    del1            ;Branch if no shifts
  1047.         push    si            ;Save SI and DI
  1048.         push    di
  1049.         mov    si,di            ;Position registers for shift
  1050.         inc    si
  1051.         rep    movsb            ;Shift chars right of cursor
  1052.         pop    di            ;Restore registers
  1053.         pop    si
  1054. del1:
  1055.         mov    ah,3            ;Get cursor position
  1056.         int    10h
  1057.         jmp    bs2            ;Exit thru BACKSPACE routine
  1058. del2:
  1059.         ret
  1060. delete        endp
  1061.  
  1062. ;------------------------------------------------------------------------------
  1063. ; CTRL_BS deletes the word at the cursor.
  1064. ;------------------------------------------------------------------------------
  1065. lesschars    dw    ?            ;Count of chars deleted
  1066. shiftcount    dw    ?            ;Count of chars shifted
  1067.  
  1068. ctrl_bs        proc    near
  1069.         mov    cl,[si]            ;Exit now if there is nothing
  1070.         xor    ch,ch            ;  on the command line
  1071.         or    cx,cx
  1072.         jnz    cbs1
  1073. cbs_exit:
  1074.         ret
  1075. cbs1:
  1076.         cmp    cs:[bufferptr],1    ;Exit if the cursor is at the
  1077.         je    cbs3            ;  at the end of the command
  1078.         cmp    cl,cs:[bufferptr]    ;  line or if it is under a
  1079.         jb    cbs_exit        ;  space; otherwise, move to
  1080.         cmp    byte ptr [di],32    ;  the beginning of the
  1081.         je    cbs_exit        ;  current word
  1082.         cmp    byte ptr [di-1],32
  1083.         je    cbs3
  1084. cbs2:
  1085.         push    cx            ;Save CX
  1086.         call    ctrl_left        ;Move to start of word
  1087.         pop    cx            ;Restore CX
  1088. cbs3:
  1089.         inc    cx            ;Calculate max number of
  1090.         push    cx            ;  characters to search
  1091.         mov    dl,cs:[bufferptr]    ;  looking for the next
  1092.         xor    dh,dh            ;  word or end-of-line
  1093.         sub    cx,dx
  1094.         push    di            ;Save DI
  1095. cbs4:
  1096.         inc    di            ;Search until DI addresses
  1097.         cmp    byte ptr [di],32    ;  either the first character
  1098.         je    cbs5            ;  in the next word or the
  1099.         cmp    byte ptr [di-1],32    ;  end of the command line
  1100.         je    cbs6
  1101. cbs5:
  1102.         loop    cbs4
  1103. cbs6:
  1104.         mov    dx,di            ;Save final value of DI
  1105.         pop    di            ;Restore DI
  1106.         pop    cx            ;Retrieve count
  1107.         mov    cs:[lesschars],dx    ;Calculate number of chars to
  1108.         sub    cs:[lesschars],di    ;  be deleted
  1109.         sub    cx,dx            ;Then calculate how many chars
  1110.         add    cx,si            ;  must be shifted
  1111.         mov    cs:[shiftcount],cx
  1112.         jcxz    cbs7            ;Branch if no shift
  1113.         push    si            ;Save registers
  1114.         push    di
  1115.         mov    si,dx            ;Point DS:SI to next word
  1116.         rep    movsb            ;Delete current word
  1117.         pop    di            ;Restore registers
  1118.         pop    si
  1119. cbs7:
  1120.         mov    cx,cs:[lesschars]    ;Update character counter
  1121.         sub    [si],cl            ;  in input buffer
  1122.         mov    ah,3            ;Save the current cursor
  1123.         int    10h            ;  position on the stack
  1124.         push    dx
  1125.         push    si            ;Update the text on the
  1126.         mov    si,di            ;  command line
  1127.         mov    cx,cs:[shiftcount]
  1128.         call    print_string
  1129.         pop    si
  1130.         mov    cx,cs:[lesschars]
  1131. cbs8:
  1132.         mov    ah,2            ;Print as many spaces as
  1133.         mov    dl,32            ;  there were characters
  1134.         int    21h            ;  deleted
  1135.         loop    cbs8
  1136.         pop    dx            ;Restore cursor position
  1137.         mov    ah,2            ;  and exit
  1138.         int    10h
  1139.         ret
  1140. ctrl_bs        endp
  1141.  
  1142. ;------------------------------------------------------------------------------
  1143. ; CTRL_END deletes command line text from the cursor to the end of the line.
  1144. ;------------------------------------------------------------------------------
  1145. ctrl_end    proc    near
  1146.         mov    cl,[si]            ;Exit if already at end
  1147.         cmp    cl,cs:[bufferptr]    ;  of line
  1148.         jb    ce_exit
  1149.         sub    cl,cs:[bufferptr]    ;Calculate number of chars
  1150.         xor    ch,ch            ;  to be deleted
  1151.         inc    cx
  1152.         sub    [si],cl            ;Update count in input buffer
  1153.         push    cx
  1154.         mov    ah,3            ;Get and save cursor position
  1155.         int    10h
  1156.         pop    cx
  1157.         push    dx
  1158. ce1:
  1159.         mov    ah,2            ;Print as many spaces as
  1160.         mov    dl,32            ;  there are characters
  1161.         int    21h            ;  to delete
  1162.         loop    ce1
  1163.         mov    ah,2            ;Reset cursor position and
  1164.         pop    dx            ;  exit
  1165.         int    10h
  1166. ce_exit:
  1167.         ret
  1168. ctrl_end    endp
  1169.  
  1170. ;------------------------------------------------------------------------------
  1171. ; MOVE_LEFT moves the cursor one character left.
  1172. ;------------------------------------------------------------------------------
  1173. move_left    proc    near
  1174.         cmp    cs:[bufferptr],1    ;At beginning of line?
  1175.         je    left2            ;Yes, then ignore keypress
  1176.         mov    ah,3            ;Get cursor position
  1177.         int    10h
  1178.         dec    dl            ;Decrement it by 1
  1179.         cmp    dl,0FFh
  1180.         jne    left1
  1181.         mov    dl,cs:[columns]        ;Decrement row number by 1
  1182.         dec    dh            ;  if cursor wraps around
  1183. left1:
  1184.         mov    ah,2            ;Set new position
  1185.         int    10h
  1186.         dec    di            ;Decrement pointers
  1187.         dec    cs:[bufferptr]
  1188. left2:
  1189.         ret
  1190. move_left    endp
  1191.  
  1192. ;------------------------------------------------------------------------------
  1193. ; MOVE_RIGHT moves the cursor one character right.
  1194. ;------------------------------------------------------------------------------
  1195. move_right    proc    near
  1196.         mov    cl,[si]            ;Get count
  1197.         cmp    cl,cs:[bufferptr]    ;End-of-line?
  1198.         jb    rt2            ;Yes, then ignore keypress
  1199.         mov    ah,3            ;Get cursor position
  1200.         int    10h
  1201.         inc    dl            ;Increment column number
  1202.         cmp    dl,cs:[columns]        ;Increment row number if
  1203.         jna    rt1            ;  cursor wraps around
  1204.         xor    dl,dl
  1205.         inc    dh
  1206. rt1:
  1207.         mov    ah,2            ;Position cursor
  1208.         int    10h
  1209.         inc    di            ;Advance pointers
  1210.         inc    cs:[bufferptr]
  1211. rt2:
  1212.         ret
  1213. move_right    endp
  1214.  
  1215. ;------------------------------------------------------------------------------
  1216. ; CTRL_LEFT moves the cursor one word left.
  1217. ;------------------------------------------------------------------------------
  1218. ctrl_left    proc    near
  1219.         call    move_left        ;Move one character left
  1220.         cmp    cs:[bufferptr],1    ;Beginning of line?
  1221.         je    cl_exit            ;Yes, then exit
  1222.         cmp    byte ptr es:[di],32    ;Loop back if current char
  1223.         je    ctrl_left        ;  is a space
  1224.         cmp    byte ptr es:[di-1],32    ;Loop back if char to the
  1225.         jne    ctrl_left        ;  left is not a space
  1226. cl_exit:
  1227.         ret
  1228. ctrl_left    endp
  1229.  
  1230. ;------------------------------------------------------------------------------
  1231. ; CTRL_RIGHT moves the cursor one word right.
  1232. ;------------------------------------------------------------------------------
  1233. ctrl_right    proc    near
  1234.         call    move_right        ;Move one character right
  1235.         mov    cl,[si]            ;End-of-line?
  1236.         cmp    cl,cs:[bufferptr]    ;Yes, then exit
  1237.         jb    cr_exit
  1238.         cmp    byte ptr es:[di],32    ;Loop back if current char
  1239.         je    ctrl_right        ;  is a space
  1240.         cmp    byte ptr es:[di-1],32    ;Loop back if char to the
  1241.         jne    ctrl_right        ;  left is not a space
  1242. cr_exit:
  1243.         ret
  1244. ctrl_right    endp
  1245.  
  1246. ;------------------------------------------------------------------------------
  1247. ; HOME relocates the cursor to the beginning of the command line.
  1248. ;------------------------------------------------------------------------------
  1249. home        proc    near
  1250.         mov    cl,cs:[bufferptr]    ;Get position pointer
  1251.         dec    cl            ;Calculate distance from start
  1252.         xor    ch,ch
  1253.         jcxz    home_exit        ;Exit if already there
  1254. home1:
  1255.         push    cx            ;Save count
  1256.         call    move_left        ;Move left one space
  1257.         pop    cx            ;Retrieve count
  1258.         loop    home1            ;Loop until done
  1259. home_exit:
  1260.         ret
  1261. home        endp
  1262.  
  1263. ;------------------------------------------------------------------------------
  1264. ; EOL advances the cursor to the end of the command line.
  1265. ;------------------------------------------------------------------------------
  1266. eol        proc    near
  1267.         mov    cl,[si]            ;Get count
  1268.         cmp    cl,cs:[bufferptr]    ;Already at end?
  1269.         jb    eol_exit        ;Yes, then exit
  1270.         sub    cl,cs:[bufferptr]    ;Calculate distance from end
  1271.         inc    cl
  1272.         xor    ch,ch            ;Byte to word in CX
  1273. eol1:
  1274.         push    cx            ;Advance right CX times
  1275.         call    move_right
  1276.         pop    cx
  1277.         loop    eol1
  1278. eol_exit:
  1279.         ret
  1280. eol        endp
  1281.  
  1282. ;------------------------------------------------------------------------------
  1283. ; CLEAR_LINE clears the command line.
  1284. ; Entry:  BH - current video page
  1285. ;------------------------------------------------------------------------------
  1286. clear_line    proc    near
  1287.         mov    cl,[si]            ;Get count
  1288.         xor    ch,ch
  1289.         jcxz    cline2            ;Exit if no characters
  1290.         push    cx            ;Save count
  1291.         call    home            ;Home the cursor
  1292.         mov    ah,3            ;Get cursor position
  1293.         int    10h
  1294.         pop    cx            ;Restore CX
  1295.         push    dx            ;Save cursor address
  1296.         mov    ah,2            ;Print ASCII spaces
  1297.         mov    dl,32
  1298. cline1:
  1299.         int    21h
  1300.         loop    cline1
  1301.         mov    ah,2            ;Home cursor again
  1302.         pop    dx
  1303.         int    10h
  1304.         mov    byte ptr [si],0        ;Reset count
  1305. cline2:
  1306.         ret
  1307. clear_line    endp
  1308.  
  1309. ;------------------------------------------------------------------------------
  1310. ; CMD_RECORD records the latest command in the command stack.
  1311. ; Entry:  DS:DX - input buffer address
  1312. ;------------------------------------------------------------------------------
  1313. cmd_record    proc    near
  1314.         mov    si,dx            ;Point SI to input buffer
  1315.         mov    al,[si+1]        ;Get length of input string
  1316.         cmp    al,cs:[minlength]    ;Is the length zero?
  1317.         jb    cmd_exit        ;Yes, then exit now
  1318.         inc    si            ;Advance SI to count byte
  1319.         push    cs            ;Point ES to command stack 
  1320.         pop    es            ;  segment
  1321.         mov    di,cs:[next_ptr]    ;Get command stack pointer
  1322.         mov    cl,7            ;Convert it to offset address
  1323.         shl    di,cl
  1324.         add    di,cs:[cmdstack_base]
  1325.         mov    cl,al            ;Transfer string length to CL
  1326.         inc    cl            ;Increment for count byte
  1327.         xor    ch,ch            ;Byte to word in CX
  1328.         cld                ;Clear DF
  1329.         rep    movsb            ;Copy string to command stack
  1330.         inc    cs:[next_ptr]        ;Update pointer
  1331.         mov    ax,cs:[cmdstack_size]
  1332.         cmp    cs:[next_ptr],ax    ;Wrap around if necessary
  1333.         jne    cmdrec1
  1334.         mov    cs:[next_ptr],0
  1335. cmdrec1:
  1336.         mov    cs:[cmd_ptr],0        ;Zero current command pointer
  1337. cmd_exit:
  1338.         ret
  1339. cmd_record    endp
  1340.  
  1341. ;------------------------------------------------------------------------------
  1342. ; SET_CURSOR sets the cursor mode based on the state of the insert flag.
  1343. ;------------------------------------------------------------------------------
  1344. set_cursor    proc    near
  1345.         cmp    cs:[insert_flag],0    ;Test state of insert flag
  1346.         je    setc1            ;Branch if not set
  1347.         mov    cx,cs:[cursor_mode]    ;Raise top by 2 scan lines
  1348.         sub    ch,2
  1349.         jns    setc2            ;Exit if it wraps around
  1350.         ret
  1351. setc1:
  1352.         mov    cx,cs:[cursor_mode]    ;Set default cursor
  1353. setc2:
  1354.         mov    ah,1            ;Set cursor mode
  1355.         int    10h
  1356.         ret
  1357. set_cursor    endp
  1358.  
  1359. ;============================================================================
  1360. ; MUXINT processes calls to interrupt 2Fh
  1361. ; Entry:  AH - Device ID
  1362. ; Exit:   AL - 0FFh if AH = Alias device ID. Unchanged otherwise.
  1363. ;         ES - Code segment if AH = Alias device ID. Unchanged otherwise.
  1364. ;============================================================================
  1365. muxint        proc    far
  1366.         assume    cs:code,ds:nothing,es:nothing
  1367.          cmp    ah,cs:[multiplex_id]    ;Check for program ID
  1368.         je    muxint_1        ;Its us, indicate installed.
  1369.         jmp    cs:[int2fh]             ;else pass the call on
  1370. muxint_1:
  1371.         mov    al,-1            ;Indicate Alias installed
  1372.         push    cs            ;ES = installed code segment
  1373.         pop    es
  1374.         iret
  1375. muxint        endp
  1376.  
  1377.         even                ;Align stack on word boundry
  1378. end_of_resident    =    $
  1379. ;----------------------------------------------------------------------------
  1380. ; Start of non-resident code.
  1381. ;----------------------------------------------------------------------------
  1382. final_install:
  1383.         rep    movsb            ;Copy alias list
  1384.         mov    di,cmdstack_base    ;Initialize command stack
  1385.         mov    cx,cmdstack_size    ;  area with leading zeroes
  1386.         jcxz    tsr            ;Branch if size is zero
  1387.         xor    al,al
  1388.         cld
  1389. final_loop:
  1390.         stosb
  1391.         add    di,127
  1392.         loop    final_loop
  1393. tsr:
  1394.         mov    ax,3100h        ;Terminate and stay resident
  1395.         int    21h
  1396.  
  1397. ;----------------------------------------------------------------------------
  1398. ; Non-resident data.
  1399. ;----------------------------------------------------------------------------
  1400. alrdy_installed    db    0            ;Installed flag
  1401. other_seg    dw    0            ;Segment of installed code
  1402. databuff_seg    dw    0            ;Segment of data buffer.
  1403.  
  1404. alias_buffer    dw    512            ;Extra buffer for alias list.
  1405. aliaslist_end    dw    0            ;Offset of end of the list.
  1406. alias_inlist    db    0            ;Flag used in alias list append
  1407.  
  1408. infomsg1    db    "ALIAS uninstalled$"
  1409. infomsg2    db    13,10,9,"Command stack size: $"
  1410. infomsg3    db    13,10,9,"Minimum stacked command length: $"
  1411. infomsg4    db    13,10,9,"Bytes free in alias buffer: $"
  1412. infomsg5    db    13,10,9,"Alias translation is $"
  1413. infomsg5d    db    "disabled",13,10,"$"
  1414. infomsg5e    db    "enabled",13,10,"$"
  1415. infomsg6    db    13,10,9,"FUNCTION KEY DEFINITIONS$"
  1416. infomsg7    db    13,10,9,"ALIAS DEFINITIONS$"
  1417. infomsg8    db    13,10,"For help type ALIAS ?$"
  1418.  
  1419. filemsg1    db    13,10,"Error in line $"    ;File identification message.
  1420. filemsg2    db    " of file: "
  1421. filenam_field    db    78 dup (0)        ;Name of current entry file.
  1422.  
  1423. errmsg0        db    "Need DOS 2.0 or greater$"
  1424. errmsg1        db    "ALIAS not installed$"
  1425.  
  1426. errmsg2        db    13,10,"Syntax: ALIAS [alias [command]] "
  1427.         db    "[/F filename] [/S nn] [/U]",13,10
  1428.         db    14 dup (" ")
  1429.         db    "[/B nn] [/E] [/D] [/L] [/M]",13,10,10
  1430.         db         9,"ALIAS alias command",13,10
  1431.         db         9,"ALIAS [fn] command",13,10,10
  1432.         db         9,"/B = Buffer size",13,10
  1433.         db         9,"/D = Disable alias translation",13,10
  1434.         db         9,"/E = Enable alias translation",13,10
  1435.         db         9,"/F = Filename of command file",13,10
  1436.         db         9,"/L = List aliases",13,10
  1437.         db         9,"/M = Minimum command length to stack",13,10
  1438.         db         9,"/S = Size of command stack",13,10
  1439.         db         9,"/U = Uninstall",13,10,"$"
  1440.  
  1441. errmsg3        db    "Can",39,"t uninstall$"
  1442. errmsg4        db    "Can",39,"t change parameter after installation$"
  1443. errmsg5        db    "Illegal number$"
  1444. errmsg6        db    "Can",39,"t find alias file$"
  1445. errmsg7        db    "Can",39,"t find COMMAND.COM$"
  1446. errmsg8        db    "Not enough memory$"
  1447. errmsg9        db    "Alias list full$"
  1448. errmsg10    db    "List and stack too large$"
  1449. errmsg11    db    "Invalid key assignment$"
  1450. errmsg12    db    "Number too big$"
  1451. errmsg13    db    "Alias not in list$"
  1452. errmsg14    db    "Error using Int 2Fh$"
  1453. endmsg        db    13,10,"$"
  1454.  
  1455. shiftmsg    db    "S-$"
  1456. altmsg        db    "A-$"
  1457. ctlmsg        db    "C-$"
  1458.  
  1459. file_linecount    dw    0            ;Line number being processed.
  1460. caps_flag    db    0
  1461. param_found    db    0            ;Cmd line parameter found flag
  1462. append_cr    db    0            ;Append cr to alias flag
  1463. cmdcom_name    db    "COMMAND"        ;Name of command.com
  1464.  
  1465. cmd_switches    db    "sfeldbum*/"        ;Letters of valid commands.
  1466. cmd_switch_end    =    $
  1467. cmd_jmp_tbl    dw    offset setstacksize    ;This jump table is used to
  1468.         dw    offset loadaliasfile    ;  call the routines that
  1469.         dw    offset enablealias      ;  process the command line
  1470.         dw    offset listalias    ;  arguments
  1471.         dw    offset disablealias
  1472.         dw    offset setlistbuffer
  1473.         dw    offset remove
  1474.         dw    offset minstacklen
  1475.         dw    offset comment_line    ;Comments can be indicated by
  1476.         dw    offset comment_line    ;  a /* or a //.
  1477.  
  1478. ;----------------------------------------------------------------------------
  1479. ; Initialization routine.
  1480. ;----------------------------------------------------------------------------
  1481. initialize    proc    near
  1482.         assume    cs:code,ds:code,es:code
  1483.         cld
  1484.         mov    ah,30h            ;Get DOS version
  1485.         int    21h
  1486.         xchg    al,ah            ;Swap major, minor numbers
  1487.         mov    dx,offset errmsg0    ;Bad DOS version
  1488.         cmp    ah,2            ;Run if DOS 2.0 or greater.
  1489.         jae    init1
  1490. jmp_disp_error:
  1491.         jmp    disp_error
  1492. init1:
  1493.         mov    dos_version,ax        ;Save version number
  1494.  
  1495.         mov    ah,4ah            ;Reduce memory allocation to
  1496.         mov    bx,1000h             ;  just this segment.
  1497.         int    21h
  1498.  
  1499.         mov    ax,offset end_of_code            ;Initialize alias list
  1500.         mov    word ptr [aliaslist_ptr],ax    ;  pointers.
  1501.         mov    ax,cs
  1502.         mov    word ptr [aliaslist_ptr+2],ax
  1503.         lds    di,aliaslist_ptr        ;Initialize alias list
  1504.         mov    ax,-1                ;  by writing a -1 as
  1505.         stosw                       ;  an end flag.
  1506.         mov    aliaslist_end,di
  1507. ;
  1508. ;See if a copy is already resident in memory. If > DOS 3.0, use int 2Fh.
  1509. ;
  1510.         mov    byte ptr [main+2],0    ;Initialize fingerprint
  1511.         cmp    dos_version,300h    ;See if DOS 3.0 or later
  1512.         jb    find_copy1        ;No, search the old way.
  1513.         mov    cx,16            ;Try 16 different IDs.
  1514. find_copy:
  1515.         xor    ax,ax
  1516.         mov    es,ax
  1517.         mov    ah,multiplex_id        ;Load ID.  Use Int 2Fh to
  1518.         int    2fh            ;  reach installed code so
  1519.         or    al,al            ;  that we are compatible
  1520.         jne    find_copy0        ;  with 386 memory managers.
  1521.         push    cs
  1522.         pop    es                      ;If AL not changed, ALIAS not
  1523.         jmp    short find_copy4    ;  installed.
  1524. find_copy0:
  1525.         push    cx
  1526.         call    cmpheader        ;See if really Alias by
  1527.         pop    cx                      ;  comparing file headers.
  1528.         je    find_copy3
  1529.         inc    multiplex_id        ;ID used by another program.
  1530.         loop    find_copy        ;  Change and try again.
  1531.         mov    dx,offset errmsg14    ;All IDs taken, print error
  1532.         jmp    disp_error            ;  msg and exit.
  1533. ;
  1534. ;For DOS 2.x find the installed code the old fashioned way by scanning
  1535. ;the memory control blocks.
  1536. ;
  1537. find_copy1:
  1538.         xor    bx,bx            ;zero BX for start
  1539.         mov    ax,cs            ;keep CS value in AX
  1540. find_copy2:
  1541.         inc    bx            ;increment search segment value
  1542.         mov    es,bx
  1543.         assume    es:nothing
  1544.         cmp    ax,bx            ;not installed if current
  1545.         je    find_copy4            ;  segment is found.
  1546.         call    cmpheader
  1547.         jne    find_copy2        ;loop back if not found
  1548. find_copy3:
  1549.         inc    alrdy_installed        ;Set installed flag
  1550. find_copy4:
  1551.         mov    other_seg,es        ;Save seg of installed code
  1552. ;
  1553. ;Parse the command line for switches.
  1554. ;
  1555.          mov    ah,48h            ;Allocate memory block for
  1556.           mov    bx,0800h        ;  alias file buffer.
  1557.          int    21h
  1558.          mov    dx,offset errmsg8    ;Not enough memory msg
  1559.          jc    jmp_disp_error
  1560.         mov    databuff_seg,ax        ;Save segment to file buffer.
  1561.         mov    es,ax            ;Treat the command line as
  1562.         xor    di,di            ;  a 1 line file.
  1563.         mov    si,offset command_tail
  1564.         xor    cx,cx
  1565.         or    cl,[si]            ;Get command line length
  1566.         je    parse_line_end        ;If zero, skip parse routine
  1567.         inc    si                      ;Copy command line into file
  1568.         inc    cx            ;  buffer.
  1569.         push    cx
  1570.         rep    movsb
  1571.         pop    cx            ;CX = file size.
  1572.         xor    si,si            ;Point SI to start of buffer
  1573.         push    es
  1574.         pop    ds            ;Set DS to file buffer seg
  1575.         assume    ds:nothing
  1576.         mov    es,cs:[other_seg]     ;Set ES to installed code
  1577. ;
  1578. ;Parse command line and command files.
  1579. ;
  1580. parse_line_loop:
  1581.         xor    bl,bl
  1582.         call    scanline             ;Get 1st character
  1583.         jc    parse_2                 ;If carriage return, skip line
  1584.         cmp    al,"/"            ;Compare character to switch.
  1585.         je    parse_switch_found
  1586.         cmp    al,"?"            ;See if help character
  1587.         je    parse_line_error
  1588.         call    setkey              ;Must be alias definition
  1589.         jc    parse_error
  1590.         mov    param_found,1        ;Set parameter found flag
  1591.         jmp    short parse_2        ;Return to parse loop
  1592. parse_line_error:
  1593.         mov    dx,offset errmsg2    ;Command not found msg
  1594. parse_error:    jmp    short disp_error
  1595. parse_switch_found:
  1596.         mov    param_found,1        ;Set parameter found flag
  1597.         lodsb                ;Get command line switch
  1598.         dec    cx
  1599.         cmp    al,'A'             ;Convert to lower case if
  1600.         jb    parse_1            ;  necessary.
  1601.         cmp    al,'Z'
  1602.         ja    parse_1
  1603.         or    al,20h
  1604. parse_1:
  1605.         push    cx            ;Scan the list of allowable
  1606.         push    es            ;  command switches. If switch
  1607.         push    cs            ;  found, use its position for
  1608.         pop    es            ;  an index into the list of
  1609.         mov    di,offset cmd_switches    ;  routines.
  1610.         mov    cx,offset cmd_switch_end - offset cmd_switches
  1611.         mov    bx,offset cmd_switch_end - offset cmd_switches - 1
  1612.         repne    scasb
  1613.         mov    ax,cx            ;Copy index into list
  1614.         pop    es
  1615.         pop    cx
  1616.         jne    parse_line_error
  1617.         sub    bx,ax            ;Compute offset into list
  1618.         shl    bx,1            ;Convert to word offset
  1619.         add    bx,offset cmd_jmp_tbl    ;Add the start addr of table.
  1620.         call    cs:[bx]            ;Call command routine.
  1621.         jc    disp_error        ;If error terminate parse.
  1622. parse_2:
  1623.         jcxz    parse_line_end        ;If at file end, exit parse.
  1624.                 jmp    short parse_line_loop
  1625. ;
  1626. ;See if installed. If not, install.
  1627. ;
  1628. parse_line_end:
  1629.         cmp    cs:[param_found],1    ;See if any parameters found
  1630.         je     init2            ;If already installed and
  1631.         cmp    cs:[alrdy_installed],0    ;  no parameters on the
  1632.         je    init2            ;  command line, default to
  1633.         mov    es,cs:[other_seg]     ;  showing program information
  1634.         call    listalias
  1635. init2:
  1636.         mov    ah,49h            ;Release memory block used
  1637.         mov    es,cs:[databuff_seg]    ;  for file buffer.
  1638.         int    21h
  1639.         push    cs
  1640.         pop    ds
  1641.         assume    ds:code
  1642.         mov    word ptr databuff_seg,0
  1643.         cmp    alrdy_installed,0    ;If not already installed,
  1644.         je    install            ;  jump to install routine.
  1645. exit:
  1646.         mov    ax,4C00h        ;Terminate with RC = 0
  1647.         int    21h
  1648. ;
  1649. ;Display error message.
  1650. ;
  1651. disp_error:
  1652.         xor    ax,ax            ;If file buffer still
  1653.         or     ax,databuff_seg        ;  allocated, deallocate it.
  1654.         jz    disp_error0
  1655.         mov    ah,49h            ;Release memory block used
  1656.         mov     es,ax            ;  for file buffer.
  1657.         int    21h
  1658. disp_error0:
  1659.         push    cs
  1660.         pop    ds
  1661.         assume    ds:code
  1662.         cmp    byte ptr filenam_field,0
  1663.         je    disp_error1             ;If processing a file, print
  1664.         push    dx                      ;  a message informing the
  1665.         mov    dx,offset filemsg1      ;  user the filename being
  1666.         call    printmsg                ;  processed and the line
  1667.         mov    ax,file_linecount       ;  that the error occured.
  1668.         call    hex2asc
  1669.         mov    dx,offset filemsg2
  1670.         call    printmsgcr
  1671.         pop    dx
  1672. disp_error1:
  1673.         call    printmsgcr        ;print string
  1674.         mov    ax,4c01h        ;Terminate with RC = 1
  1675.         int    21h
  1676. ;
  1677. ;Install routine. Find segment of COMMAND.COM, hook into int 21h, 2Fh and TSR.
  1678. ;
  1679.         assume    ds:code
  1680. install:
  1681.         mov    dx,offset program       ;Display copyright message
  1682.         call    printmsg
  1683.  
  1684.         push    ds            ;Save DS
  1685.         xor    ax,ax            ;Then zero it
  1686.         mov    ds,ax
  1687.         mov    cs:[points],ax        ;Record number of scan lines
  1688.         mov    ax,ds:[0460h]        ;  per character and cursor
  1689.         mov    cs:[cursor_mode],ax    ;  mode
  1690.         pop    ds            ;Restore DS
  1691.  
  1692.         mov    byte ptr filenam_field,0  ;Don't callout file on error
  1693.         mov    ah,52h            ;get address of first MCB
  1694.         int    21h
  1695.         mov    ax,es:[bx-2]        ;point ES to MCB
  1696.         mov    cx,20            ;Allow only 20 loops.
  1697. mcb_loop:
  1698.         mov    es,ax
  1699.         cmp    byte ptr es:[0],"M"    ;check for mcb signature
  1700.         jne    mcb_error
  1701.         inc    ax            ;point AX to memory block
  1702.         cmp    ax,es:[1]        ;See if this is a PSP block
  1703.         je     psp_found
  1704. mcb_continue:
  1705.         add    ax,es:[3]        ;Get size of memory block
  1706.         loop    mcb_loop
  1707. mcb_error:
  1708.         mov    dx,offset errmsg7    ;Can't locate command.com PSP
  1709.         jmp    disp_error
  1710. psp_found:
  1711.         cmp     dos_version,0400h    ;If DOS 4.00 or greater,
  1712.         jb    psp_found_1        ;  COMMAND.COM may not be the
  1713.         push    ds            ;  first program loaded.  Look
  1714.         mov    si,offset cmdcom_name    ;  at the name of the program
  1715.         mov    di,8            ;  stored in the last 8 bytes
  1716.         mov    cx,7            ;  of the memory control
  1717.         repe    cmpsb            ;  block.  If the string
  1718.         pop    ds            ;  "COMMAND" isn't found, keep
  1719.         jne    mcb_continue        ;  looking.
  1720. psp_found_1:
  1721.         mov    cmdcom_psp,ax        ;Save segment of cmd.com PSP
  1722.         mov    es,ax
  1723.         mov    ax,es:[2ch]        ;Get seg of master environment
  1724.         mov    master_env,ax
  1725. ;
  1726. ;Set up pointers to the cmd stack and to move the alias list to the end of the
  1727. ;command stack so it takes up less space when ALIAS resident.
  1728. ;
  1729.         mov    di,mystack_ptr        ;Get base of internal stack
  1730.         mov    work_buff_ptr,di    ;Copy ptr to alias buffer
  1731.         add    di,128            ;Add size of buffer
  1732.         mov    cmdstack_base,di    ;Copy for start of cmd stack
  1733.         mov    ax,cmdstack_size    ;Get size of command stack
  1734.         mov    ah,128              ;128 bytes for each entry
  1735.         mul    ah
  1736.         add    di,ax                 ;Add to cmd stack for
  1737.         mov    si,word ptr aliaslist_ptr    ;  start of the
  1738.         mov    cx,aliaslist_end        ;  alias list.
  1739.         mov     word ptr aliaslist_ptr,di    ;Save new pointer.
  1740.         sub    cx,si               ;Compute size of list.
  1741.         mov    dx,di            ;See if we have enough room
  1742.         add    dx,cx            ;  for everything in one seg.
  1743.         jnc    install_1
  1744.         mov    dx,offset errmsg10    ;Not enough memory, exit.
  1745.         jmp    disp_error
  1746. install_1:
  1747.         add    dx,alias_buffer        ;Add additional space for list
  1748.         mov    aliaslist_size,dx    ;Save pointer to end of seg
  1749.         add    dx,15            ;Convert memory needed to
  1750.         shr    dx,1            ;  paragraphs.
  1751.         shr    dx,1
  1752.         shr    dx,1
  1753.         shr    dx,1
  1754.         cmp    di,si            ;Check for overlap in the move
  1755.         jb    install_2        ;If overlap, copy list from
  1756.         std                ;  the top down to avoid
  1757.         add    di,cx            ;  overwriting the list.
  1758.         add    si,cx
  1759.         dec    si
  1760.         dec    di
  1761. ;
  1762. ;Revector interrupts 21h and 2Fh (if necessary).
  1763. ;
  1764. install_2:
  1765.         mov    ax,3521h        ;Get interrupt 21 (DOS)
  1766.         int    21h                     ;  vector.
  1767.         mov    word ptr [int21h],bx
  1768.         mov    word ptr [int21h+2],es
  1769.         push    dx            ;Save memory size parameter
  1770.         mov    ax,2521h                ;Point int 21 to internal
  1771.         mov    dx,offset dosint        ;  routine.
  1772.         int    21h
  1773.  
  1774.         cmp    dos_version,300h    ;See if we are using Int 2Fh
  1775.         jb    install_3
  1776.         mov    ax,352fh        ;Get interrupt 2F (MUX)
  1777.         int    21h                     ;  vector.
  1778.         mov    word ptr [int2fh],bx
  1779.         mov    word ptr [int2fh+2],es
  1780.         mov    ax,252fh                ;Point int 2F to internal
  1781.         mov    dx,offset muxint        ;  routine.
  1782.         int    21h
  1783. install_3:
  1784.         pop    dx
  1785.         push    ds            ;ES = DS
  1786.         pop    es
  1787.                 jmp    final_install        ;Jump to safe place for move.
  1788. initialize    endp
  1789.  
  1790. ;-----------------------------------------------------------------------------
  1791. ; CMPHEADER compares the first 16 bytes of this file with the segment
  1792. ;           pointed to by ES.
  1793. ; Entry:  DS - code segment
  1794. ;         ES - pointer to segment to compare
  1795. ; Exit:   ZF - 0 = segments match.
  1796. ;-----------------------------------------------------------------------------
  1797. cmpheader    proc    near
  1798.         mov    si,offset main+2    ;Search this segment for ASCII
  1799.         mov    di,si            ;  fingerprint.
  1800.         mov    cx,16
  1801.         repe    cmpsb
  1802.         ret
  1803. cmpheader    endp
  1804.  
  1805. ;-----------------------------------------------------------------------------
  1806. ; PRINTMSG prints the message pointed to by DX to the screen.
  1807. ; Entry:  DX - pointer to ASCII message terminated by $
  1808. ;-----------------------------------------------------------------------------
  1809. printmsg    proc    near
  1810.         assume    ds:nothing,es:nothing
  1811.         push    ds
  1812.         push    cs
  1813.         pop    ds
  1814.         assume    ds:code
  1815.         mov    ah,9            ;Print message
  1816.         int    21h
  1817.         pop    ds
  1818.         ret
  1819. printmsg    endp
  1820.  
  1821. ;-----------------------------------------------------------------------------
  1822. ; PRINTMSGCR calls PRINTMSG, then appends a carriage return to the message.
  1823. ; Entry:  DX - pointer to ASCII message terminated by $
  1824. ;-----------------------------------------------------------------------------
  1825. printmsgcr    proc    near
  1826.         assume    ds:nothing,es:nothing
  1827.         push    dx
  1828.         call    printmsg
  1829.         mov    dx,offset endmsg
  1830.         call    printmsg
  1831.         pop    dx
  1832.         ret
  1833. printmsgcr    endp
  1834.  
  1835. ;-----------------------------------------------------------------------------
  1836. ; SETSTACKSIZE - Sets the size of the command line stack.
  1837. ; Entry:  DS:SI - points to stack size in ascii
  1838. ; Exit:      CF - Clear if sucessful, Set if error, DX points to error msg.
  1839. ;-----------------------------------------------------------------------------
  1840. setstacksize    proc    near
  1841.         assume    ds:nothing,es:nothing
  1842.         xor    bl,bl            ;Check for installed code
  1843.         call    setparameter        ;Get num and convert to binary
  1844.         jc    setstack_exit        ;Check for error
  1845.         mov    cs:[cmdstack_size],ax    ;Save parameter
  1846. setstack_exit:
  1847.         ret
  1848. setstacksize    endp
  1849.  
  1850. ;-----------------------------------------------------------------------------
  1851. ; SETLISTBUFFER - Sets the size of the additional buffer reserved for alias
  1852. ;                 list expansion.
  1853. ; Entry:  DS:SI - points to buffer size in ascii
  1854. ; Exit:      CF - Clear if sucessful, Set if error, DX points to error msg.
  1855. ;-----------------------------------------------------------------------------
  1856. setlistbuffer    proc    near
  1857.         assume    ds:nothing,es:nothing
  1858.         xor    bl,bl            ;Check for installed code
  1859.         call    setparameter        ;Get num and convert to binary
  1860.         jc    setlistbuffer_exit      ;Check for error
  1861.         mov    cs:[alias_buffer],ax    ;Save buffer size parameter
  1862. setlistbuffer_exit:
  1863.         ret
  1864. setlistbuffer    endp
  1865.  
  1866. ;-----------------------------------------------------------------------------
  1867. ; MINSTACKLEN - sets the minimum legth of a command to stack.
  1868. ; Entry:     ES - segment of the installed code
  1869. ;         DS:SI - points to buffer size in ascii
  1870. ; Exit:      CF - Clear if sucessful, Set if error, DX points to error msg.
  1871. ;-----------------------------------------------------------------------------
  1872. minstacklen    proc    near
  1873.         assume    ds:nothing,es:nothing
  1874.         mov    bl,1             ;Don't check for installed code
  1875.         call    asc2bin            ;Get num and convert to binary
  1876.         jc    minstacklen_exit    ;Check for error
  1877.         cmp    al,126
  1878.         jb    minstacklen_1
  1879.         mov    dx,offset errmsg12    ;Stack length too big
  1880.         stc
  1881.         jmp    short minstacklen_exit
  1882. minstacklen_1:
  1883.         or     al,al            ;Make sure min length is not
  1884.         jne    minstacklen_2        ; specified at 0. If so,
  1885.         inc    al            ; change to 1.
  1886. minstacklen_2:
  1887.         mov    es:[minlength],al    ;Save minimum length parameter
  1888. minstacklen_exit:
  1889.         ret
  1890. minstacklen    endp
  1891.  
  1892. ;-----------------------------------------------------------------------------
  1893. ; SETPARAMETER - Common code used by the set stack and set buffer and set
  1894. ;                minimum command length routines.
  1895. ; Entry:  DS:SI - points to ascii number
  1896. ;            BL - Flag to indicate check for installed code, BL=0, check.
  1897. ; Exit:      CF - Clear if sucessful, Set if error.
  1898. ;-----------------------------------------------------------------------------
  1899. setparameter    proc    near
  1900.         assume    ds:nothing,es:nothing
  1901.         mov    dx,offset errmsg4     ;Can't change parameter msg
  1902.         cmp    cs:[alrdy_installed],1    ;If already installed don't
  1903.         je     setparam_error          ;  change parameter.
  1904.         call    asc2bin
  1905. setparam_exit:
  1906.         ret
  1907. setparam_error:
  1908.         stc                ;Set error flag.
  1909.         jmp    short setparam_exit
  1910. setparameter    endp
  1911.  
  1912. ;-----------------------------------------------------------------------------
  1913. ; SETKEY modifies the alias list to add function key definitions.
  1914. ; Entry:  DS:SI - pointer to string identifing the function key
  1915. ;            ES - pointer to segment of installed code
  1916. ; Exit:      CF - clear if successful
  1917. ;-----------------------------------------------------------------------------
  1918. setkey        proc    near
  1919.         assume    ds:nothing,es:nothing
  1920.         push    es
  1921.         cmp    al,"["            ;Determine alias or key
  1922.         je    setkey_1
  1923.          dec    si                      ;Backup before last key
  1924.          inc    cx
  1925.         jmp    short setkey_5
  1926. setkey_1:
  1927.         lodsb                ;Get next character
  1928.         dec    cx
  1929.         jcxz     setkey_badkey
  1930.         mov    bx,58            ;Load default F1 keycode
  1931.         or    al,20h            ;Convert to lower case
  1932.         cmp    al,"f"
  1933.         je    setkey_3
  1934.         add    bx,25            ;Assume shift F1 keycode
  1935.         cmp    al,"s"
  1936.         je    setkey_2
  1937.         add    bx,10            ;Assume ctl F1 keycode
  1938.         cmp    al,"c"
  1939.         je    setkey_2
  1940.         add    bx,10            ;Assume alt F1 keycode
  1941.         cmp    al,"a"
  1942.         jne    setkey_badkey
  1943. setkey_2:
  1944.         lodsb                ;Get next character
  1945.         dec    cx
  1946.         or    al,20h            ;Convert to lower case
  1947.         cmp    al,"f"            ;Make sure next key is "f"
  1948.         jne    setkey_badkey
  1949. setkey_3:
  1950.         call    asc2bin
  1951.         jc      setkey_badkey        ;If bad number, exit
  1952.         or     ax,ax
  1953.         je    setkey_badkey        ;Make sure not zero
  1954.         cmp    ax,10
  1955.         ja    setkey_badkey        ;Make sure less than 10
  1956.         cmp    byte ptr [si-1],"]"    ;Check for closing bracket
  1957.         jne     setkey_badkey        ;  if not found, error
  1958.         add    bx,ax            ;Add in function key number
  1959.         cmp    byte ptr [si]," "       ;Check to see if a character
  1960.         jbe    setkey_4                ;  trails the closing bracket.
  1961.         cmp    byte ptr [si],"*"       ;Check to see if an * is
  1962.         jne    setkey_badkey        ;  appended to the function
  1963.         lodsb                           ;  key assignment. If so,
  1964.         dec    cx                      ;  remove key and set flag
  1965.         mov    cs:[append_cr],1        ;  to append cr to command.
  1966. setkey_4:
  1967.         sub    si,2            ;Back up to keycode.
  1968.         xor    bh,bh
  1969.         mov    ds:[si],bx        ;Save keycode on command line
  1970.         add    cx,2
  1971. setkey_5:
  1972.         call    setalias                ;Use SETALIAS to load
  1973. setkey_exit:
  1974.         pop    es            ;Restore ptr to installed seg
  1975.         ret
  1976. setkey_badkey:
  1977.         mov    dx,offset errmsg11    ;Bad key assignment msg
  1978.         stc
  1979.         jmp    setkey_exit
  1980. setkey        endp
  1981.  
  1982.  
  1983. ;-----------------------------------------------------------------------------
  1984. ; SETALIAS modifies the alias list according to command line agruments.
  1985. ; Entry:  DS:SI - pointer to string to be inserted into alias list.
  1986. ;            ES - pointer to segment of installed code.
  1987. ; Exit:      CF - clear if successful
  1988. ;-----------------------------------------------------------------------------
  1989. setalias    proc    near
  1990.         assume    ds:nothing,es:nothing
  1991.         push    es
  1992.         xor    bl,bl            ;Find 1st character on
  1993.         call    scanline        ;  command line.
  1994.         jnc    setalias_1        ;If at end of line, exit
  1995.         jmp    setalias_exit        ;  routine.
  1996. setalias_1:
  1997. ;
  1998. ;Get length of alias, then search list for matching alias
  1999. ;
  2000.          dec    si            ;Backup to before 1st char.
  2001.         inc    cx
  2002.         mov    byte ptr cs:[alias_inlist],0 ;Assume not in list
  2003.         call    searchalias        ;Is there already an alias?
  2004.         jc     setalias_2        ;No, continue.
  2005.         inc    byte ptr cs:[alias_inlist]
  2006. ;
  2007. ;If in list, erase old alias from list.
  2008. ;
  2009.         call    delete_aliasent        ;Delete entry from list
  2010. setalias_2:
  2011. ;
  2012. ;Append new alias to the end of the list.
  2013. ;
  2014.         mov     bp,di            ;Save ptr to end of list.
  2015.         add    di,4                    ;Move past length fields.
  2016.         push    es            ;Get max size of alias list.
  2017.         mov    es,cs:[other_seg]
  2018.         mov    dx,es:[aliaslist_size]
  2019.         pop    es
  2020. ;
  2021. ;Append alias to list.
  2022. ;
  2023.         xor    ax,ax            ;Clear character counter
  2024. setalias_3:
  2025.         lodsb                ;Get byte
  2026.         dec    cx            ;Decriment buffer counter.
  2027.         jcxz    setalias_4             ;If at end of file, exit.
  2028.         cmp    al,13             ;See if at end of line.
  2029.         jne    setalias_6             ;No, continue.
  2030. setalias_4:
  2031.         cmp    byte ptr cs:[alias_inlist],0
  2032.         jne    setalias_5            ;Was alias in list?
  2033.         jmp    setalias_notnfil    ;No, incomplete alias specifed
  2034. setalias_5:
  2035.         jmp    setalias_exit        ;Yes, alias simply erased.
  2036. setalias_6:
  2037.         cmp    al,' '            ;See if at end of tag.
  2038.         je    setalias_8        ;Yes, exit copy loop
  2039.         cmp    al,9            ;Check for tab
  2040.         je    setalias_8
  2041.         cmp    di,dx             ;See if alias list is full
  2042.         jbe    setalias_7          ;No, continue
  2043.         jmp    setalias_full        ;Yes, exit routine
  2044. setalias_7:
  2045.         stosb                ;No, add character to list
  2046.         inc    ah               ;Inc size of tag
  2047.         jmp    short setalias_3
  2048. setalias_8:
  2049.         mov    es:[bp+2],ah        ;Save size of alias
  2050. ;
  2051. ;Append command to alias list.
  2052. ;
  2053.         mov    cs:[caps_flag],0    ;Clear environment var flag.
  2054.         xor    bx,bx            ;Find 1st character in
  2055.         call    scanline        ;  command.
  2056.         jc    setalias_exit        ;If no command, exit
  2057.         xor    ah,ah            ;Clear character counter
  2058. setalias_9:
  2059.         cmp    al,"%"            ;Check for environment var
  2060.         jne    setalias_11        ;  by checking for % signs.
  2061.         cmp    cs:[caps_flag],0    ;If caps flag set capitialize
  2062.         jne    setalias_10        ;  string before saving.
  2063.         mov    bl,ds:[si]        ;Get next character
  2064.         cmp    bl,"0"            ;If numberic, assume this is
  2065.         jb    setalias_10        ;  a line parameter, not an
  2066.         cmp    bl,"9"            ;  environment variable so
  2067.         jbe    setalias_11        ;  don't set caps flag.
  2068.         cmp    bl,"%"            ;Don't let double % signs
  2069.         je    setalias_11        ;  indicate environment var.
  2070. setalias_10:
  2071.         not    byte ptr cs:[caps_flag]    ;Toggle caps flag
  2072. setalias_11:
  2073.         cmp    cs:[caps_flag],0    ;Capitialize environment
  2074.         je    setalias_12        ;  variables so they will
  2075.         cmp    al,"a"            ;  match when searched for in
  2076.         jb     setalias_12        ;  the environment block.
  2077.         cmp    al,"z"
  2078.         ja     setalias_12
  2079.         and    al,0dfh            ;Make character uppercase.
  2080. setalias_12:
  2081.         cmp    di,dx             ;See if alias list is full
  2082.         ja     setalias_full        ;Yes, exit routine
  2083.         stosb                ;Append character on list
  2084.         inc    ah               ;Inc character counter.
  2085.         jcxz    setalias_13        ;Check for end of file.
  2086.         lodsb                ;Get next character
  2087.         dec    cx            ;Dec file counter.
  2088.         cmp    al,13            ;See if carriage return.
  2089.         jne    setalias_9              ;If not continue
  2090. setalias_13:
  2091.         cmp    cs:[append_cr],1    ;If flag set, append carrage
  2092.         jne    setalias_14        ;  return to command.
  2093.         mov    al,13
  2094.         inc    ah
  2095.         stosb
  2096.         mov    cs:[append_cr],0    ;Clear flag
  2097. setalias_14:
  2098.         mov    es:[bp+3],ah        ;Save command size
  2099.         mov    word ptr es:[di],-1    ;Set new end of list flag
  2100.         mov    ax,di                  ;Save end pointer to list
  2101.         add    ax,2            ;Make room for the end flag.
  2102.         mov    cs:[aliaslist_end],ax
  2103.         sub    di,bp            ;Compute size of entry
  2104.         mov    es:[bp],di        ;Put size over old end flag.
  2105.         inc    cs:[file_linecount]    ;Point counter to next line.
  2106. setalias_exit:
  2107.         clc
  2108. setalias_exit1:
  2109.         pop    es            ;Restore ptr to installed seg
  2110.         ret
  2111. setalias_full:
  2112.         mov    dx,offset errmsg9    ;Alias list too large msg.
  2113.         stc
  2114.         jmp    short setalias_exit1
  2115. setalias_notnfil:
  2116.         mov    dx,offset errmsg13    ;Alias not in list.
  2117.         stc
  2118.         jmp    short setalias_exit1
  2119. setalias    endp
  2120.  
  2121. ;-----------------------------------------------------------------------------
  2122. ; DELALIASENTRY - Deletes an alias entry
  2123. ; Entry:  DS:SI - pointer to the entry in the alias list to delete
  2124. ; Exit:      CF - clear if successful
  2125. ;-----------------------------------------------------------------------------
  2126. delete_aliasent    proc    near
  2127.         push    cx            ;Save registers
  2128.         push    si
  2129.         push    ds                      ;Yes, remove entry from list
  2130.         push    es                      ;  by moving the remainder of
  2131.         pop     ds                      ;  the list over this entry.
  2132.         mov    si,es:[di]        ;Point SI to the next list
  2133.         add    si,di            ;  entry.
  2134. delent_1:
  2135.         cmp     word ptr es:[si],-1       ;Check for the end of the list
  2136.         je    delent_2
  2137.         mov    cx,es:[si]        ;Get size of entry
  2138.         rep    movsb            ;Copy next entry over current
  2139.         jmp    short delent_1        ;  entry.
  2140. delent_2:
  2141.         mov    word ptr es:[di],-1    ;Set end of list indicator
  2142.         pop    ds            ;Get back file buffer pointer
  2143.         pop    si
  2144.         pop    cx
  2145.         ret
  2146. delete_aliasent    endp
  2147.  
  2148. ;-----------------------------------------------------------------------------
  2149. ; LOADALIASFILE loads a file containing a list of alias commands.
  2150. ; Entry:  DS:SI - pointer to the name of the file to open
  2151. ; exit:      CX - size of the file in bytes
  2152. ;            CF - clear if successful
  2153. ;-----------------------------------------------------------------------------
  2154. loadaliasfile    proc    near
  2155.         assume    ds:nothing,es:nothing
  2156.         xor    bl,bl
  2157.         call    scanline        ;Find 1st char of filename.
  2158.         mov     dx,si            ;Copy filename pointer
  2159.         inc    bl            ;Find end of filename
  2160.         call    scanline
  2161.         mov    byte ptr [si-1],0    ;Make filename ASCIIZ.
  2162.         dec    dx
  2163.         mov    ax,3d00h        ;Open file (Read only)
  2164.         int    21h
  2165.         jc    loadfile_error
  2166.         mov    bx,ax            ;Copy file handle
  2167. ;
  2168. ;Save the name of the file for error messages.
  2169. ;
  2170.         push    si
  2171.         push    es
  2172.         mov    di,offset filenam_field
  2173.         push    cs
  2174.         pop    es
  2175.         mov    si,dx
  2176. loadfile_1:
  2177.         lodsb
  2178.         stosb
  2179.         or    al,al
  2180.         jne    loadfile_1
  2181.         mov    byte ptr es:[di-1],"$"    ;Terminate string with $.
  2182.         pop    es
  2183.         pop    si
  2184. ;
  2185. ;Open file and read contents into file buffer.
  2186. ;
  2187.         mov    ah,3fh            ;Read alias file
  2188.         xor    dx,dx            ;Pont to base of file buffer.
  2189.         mov    cx,07f00h        ;Read up to 32512 bytes.
  2190.          int    21h
  2191.         mov    si,ax
  2192.         mov    byte ptr ds:[si],13    ;Append a CR to end of file.
  2193.         mov     cx,ax            ;Save new file size
  2194.         xor    si,si            ;Reset file pointer.
  2195.         mov    ah,3eh            ;Close file.
  2196.         int    21h
  2197.         mov    cs:[file_linecount],1    ;Reset line counter.
  2198. loadfile_exit:
  2199.         clc
  2200. loadfile_exit1:
  2201.         ret
  2202. loadfile_error:
  2203.         stc
  2204.         mov    dx,offset errmsg6    ;Bad filename specified.
  2205.         jmp    short loadfile_exit1
  2206. loadaliasfile    endp
  2207.  
  2208. ;-----------------------------------------------------------------------------
  2209. ; LISTALIAS prints the alias list to screen.
  2210. ; Entry:  ES - segment of the installed code
  2211. ;-----------------------------------------------------------------------------
  2212. listalias    proc    near
  2213.         assume    ds:nothing,es:nothing
  2214.         push    ds
  2215. ;
  2216. ;Print Command stack size and amount of alias buffer space remaining
  2217. ;
  2218.         mov    dx,offset infomsg2    ;Print size of command stack
  2219.         call    printmsg
  2220.         mov    ax,es:[cmdstack_size]    ;Get size of command stack
  2221.         call    hex2asc            ;Print size
  2222.         mov    dx,offset infomsg3    ;Print min cmd length
  2223.         call    printmsg
  2224.         xor    ax,ax
  2225.         mov    al,es:[minlength]    ;Get min cmd length to stack
  2226.         call    hex2asc            ;Print length
  2227.         mov    dx,offset infomsg4    ;Print label to buffer size
  2228.         call    printmsg
  2229.         lds    si,es:[aliaslist_ptr]    ;Get pointer to alias list
  2230. listalias_1:
  2231.         cmp    word ptr [si],-1    ;Scan through alias list to
  2232.         je    listalias_2        ;  find the end of the list.
  2233.                 add    si,[si]            ;Point to next entry
  2234.         jmp    short listalias_1
  2235. listalias_2:
  2236.         mov    ax,es:[aliaslist_size]    ;Get offset to end of buffer
  2237.         sub    ax,si            ;Subtract end of alias list
  2238.         sub    ax,2            ;Correct for end pointer
  2239.         call    hex2asc            ;Print size
  2240.         mov    dx,offset infomsg5    ;Indicate if alias translation
  2241.         call    printmsg        ;  is enabled or disabled
  2242.         mov    dx,offset infomsg5d    ;Disabled message
  2243.         cmp    byte ptr es:[chk_alias],0    ;See if alias enabled
  2244.         je    listalias_3
  2245.         mov    dx,offset infomsg5e     ;Enabled message
  2246. listalias_3:
  2247.         call    printmsg
  2248. ;
  2249. ;Scan through alias list to print function key assignments
  2250. ;
  2251.         xor    dx,dx            ;Clear alias found flag
  2252.         lds    si,es:[aliaslist_ptr]    ;Get pointer to alias list
  2253. listalias_4:
  2254.         cmp    word ptr [si],-1    ;Check for end of list
  2255.         jne    listalias_5
  2256.         jmp    listalias_11
  2257. listalias_5:
  2258.         mov    bx,si            ;Save pointer to entry.
  2259.          cmp    byte ptr [si+5],0    ;See if key assignment
  2260.          je    listalias_6        ;If so, skip entry
  2261.         or      dh,1            ;Set alias found flag
  2262.         add    si,[bx]            ;Point to next entry
  2263.         jmp    short listalias_4
  2264. listalias_6:
  2265. ;
  2266. ;Convert scan code into function key label
  2267. ;
  2268.         test    dh,80h            ;See if first time though
  2269.         jne    listalias_7
  2270.         push    dx
  2271.         mov    dx,offset infomsg6      ;If first time print header
  2272.         call    printmsgcr
  2273.         pop    dx
  2274.         or    dh,80h            ;Set header printed flag
  2275. listalias_7:
  2276.         call    printtab
  2277.         push    dx
  2278.                 add    si,4             ;Point SI to command string
  2279.         mov    al,[si]            ;Get key code
  2280.         mov    dh,al
  2281.         cmp    al,84                   ;Check for base code
  2282.         jb     listalias_9
  2283.         sub    dh,25
  2284.         mov     di,offset shiftmsg    ;Assume shift prefix
  2285.         cmp    al,94            ;Check for shift
  2286.         jb    listalias_8
  2287.         sub    dh,10
  2288.         mov     di,offset ctlmsg    ;Assume control prefix
  2289.         cmp    al,104            ;Check for ctl
  2290.         jb    listalias_8
  2291.         mov     di,offset altmsg    ;Assume alt prefix
  2292.         sub    dh,10
  2293. listalias_8:
  2294.         push    dx            ;Print prefix identifier
  2295.         mov    dx,di
  2296.         call    printmsg
  2297.         pop    dx
  2298. listalias_9:
  2299.         mov    dl,"F"            ;Set function key
  2300.         mov    ah,2            ;Character output
  2301.         int    21h
  2302.         mov    al,dh              ;Get modified key code
  2303.         sub    al,58            ;Convert from scan code to hex
  2304.         xor    ah,ah
  2305.         call    hex2asc            ;Print function key number
  2306.         mov    cl,[bx+3]        ;Get length of command
  2307.         inc    si            ;Point SI to command string
  2308.         inc    si
  2309.         mov    di,bx
  2310.         add    di,[bx]
  2311.         cmp    byte ptr [di-1],13    ;Check for carrage return
  2312.         jne    listalias_10        ;  after command. If found,
  2313.         mov    dl,'*'            ;  indicate immediate command
  2314.         mov    ah,2            ;  by appending an * to the
  2315.         int    21h            ;  end of the function key.
  2316. listalias_10:
  2317.         call    printtab
  2318.         call    printtab
  2319.         call    print_string        ;Print command to screen
  2320.         mov    dx,offset endmsg    ;Append carriage return to
  2321.         call    printmsg        ;  advance to next line. SI
  2322.         pop    dx                      ;  points to the next entry.
  2323.         jmp    listalias_4
  2324. ;
  2325. ;Scan through alias list to print aliases.
  2326. ;
  2327. listalias_11:
  2328.          test    dh,1                  ;See if any aliases found
  2329.          je    listalias_exit        ;If no aliases, skip remainder
  2330.         mov    dx,offset infomsg7    ;Print header
  2331.         call    printmsgcr
  2332.         xor    cx,cx            ;Clear CX
  2333.         lds    si,es:[aliaslist_ptr]    ;Get pointer to alias list
  2334. listalias_12:
  2335.         mov    bx,si            ;Save pointer to entry.
  2336.          cmp    byte ptr [si+5],0    ;See if key definition
  2337.          jne    listalias_13        ;If so, skip entry
  2338.         add    si,[bx]
  2339.         jmp    short listalias_14
  2340. listalias_13:
  2341.         call    printtab
  2342.                 add    si,4             ;Point SI to alias string
  2343.         mov    cl,[bx+2]        ;Get length of alias
  2344.         call    print_string        ;Print alias to screen
  2345.         call    printtab
  2346.         call    printtab
  2347.         mov    cl,[bx+3]        ;Get length of command
  2348.         call    print_string        ;Print command to screen
  2349.         mov    dx,offset endmsg    ;Append carriage return to
  2350.         call    printmsg        ;  advance to next line.
  2351. listalias_14:
  2352.         cmp    word ptr [si],-1    ;Check for end of list. SI
  2353.         jne    listalias_12        ;  points to the next entry.
  2354. listalias_exit:
  2355.         mov    dx,offset infomsg8    ;Print pointer to help msg
  2356.         call    printmsgcr
  2357.         pop    ds
  2358.         clc
  2359.         ret
  2360. listalias    endp
  2361.  
  2362. ;-----------------------------------------------------------------------------
  2363. ; PRINTTAB prints a TAB character to the screen.
  2364. ; Entry:  ES - segment of the installed code
  2365. ;-----------------------------------------------------------------------------
  2366. printtab    proc    near
  2367.         assume    ds:nothing,es:nothing
  2368.         mov    ah,2            ;Character output
  2369.         mov    dl,9            ;Print TAB character
  2370.         int    21h
  2371.         ret
  2372. printtab    endp
  2373.  
  2374. ;-----------------------------------------------------------------------------
  2375. ; ENABLEALIAS enables alias translation.
  2376. ; Entry:  ES - segment of the installed code
  2377. ;-----------------------------------------------------------------------------
  2378. enablealias    proc    near
  2379.         assume    ds:nothing,es:nothing
  2380.         mov    byte ptr es:[chk_alias],1    ;Enable alias
  2381.         clc
  2382.         ret
  2383. enablealias    endp
  2384.  
  2385. ;-----------------------------------------------------------------------------
  2386. ; DISABLEALIAS disables alias translation.
  2387. ; Entry:  ES - segment of the installed code
  2388. ;-----------------------------------------------------------------------------
  2389. disablealias     proc    near
  2390.         assume    ds:nothing,es:nothing
  2391.         mov    byte ptr es:[chk_alias],0    ;Disable alias
  2392.         clc
  2393.         ret
  2394. disablealias     endp
  2395.  
  2396. ;-----------------------------------------------------------------------------
  2397. ; REMOVE uninstalls the installed program from memory.
  2398. ;-----------------------------------------------------------------------------
  2399. remove        proc    near
  2400.         assume    ds:nothing,es:nothing
  2401.         push    ds
  2402.         mov    dx,offset errmsg1    ;Not installed msg
  2403.         cmp    cs:[alrdy_installed],0    ;See if installed
  2404.         je     remove_exit           ;Not installed, error
  2405.  
  2406.         mov    cx,cs:[other_seg]    ;Get segment of installed code
  2407.         mov    ax,3521h                ;Get DOS vector
  2408.         int    21h
  2409.         mov    ax,es            ;Check to make sure DOS
  2410.         cmp    ax,cs:[other_seg]    ;  vector not modified.
  2411.         jne    remove_error
  2412.  
  2413.         lds    dx,es:[int2fh]        ;Get old interrupt 2F vector
  2414.         cmp    dx,-1            ;See if Int used
  2415.         je    remove_1        ;No, skip check of Int 2F
  2416.         mov    ax,352fh                ;Get MUX vector
  2417.         int    21h
  2418.         mov    ax,es            ;Check to make sure MUX
  2419.         cmp    ax,cs:[other_seg]    ;  vector not modified.
  2420.         jne    remove_error
  2421.         mov    ax,252fh        ;Set interrupt
  2422.         int    21h
  2423. remove_1:
  2424.         lds    dx,es:[int21h]        ;Get old interrupt 21 vector
  2425.         mov    ax,2521h        ;Set interrupt
  2426.         int    21h
  2427.         mov    cx,es:[env_segment]
  2428.         mov    ah,49h            ;Free memory block
  2429.         int    21h
  2430.         mov    es,cx            ;Free environment block
  2431.         mov    ah,49h
  2432.         int    21h
  2433.         mov    dx,offset infomsg1    ;Indicate uninstalled.
  2434.         mov    byte ptr filenam_field,0 ;Clear filename field
  2435. remove_exit:
  2436.         stc
  2437.         pop    ds
  2438. remove_exit1:    ret
  2439. remove_error:
  2440.                  mov    dx,offset errmsg3    ;Can't remove error msg
  2441.         jmp    short remove_exit
  2442.  
  2443. remove        endp
  2444.  
  2445. ;-----------------------------------------------------------------------------
  2446. ; COMMENT_LINE allows comments in the alias file by skipping to the next
  2447. ; carriage return.
  2448. ; Entry:  SI - pointer to ASCII string
  2449. ;         CX - file length
  2450. ;-----------------------------------------------------------------------------
  2451. comment_line    proc near
  2452.         assume    ds:nothing,es:nothing
  2453. comment_loop:
  2454.         push    es
  2455.         push    ds
  2456.         pop    es
  2457.         mov    di,si            ;Copy file pointer
  2458.         mov    al,13            ;Scan for carriage return.
  2459.         repne    scasb
  2460.         inc    cs:[file_linecount]    ;Inc file line counter.
  2461.         mov    si,di            ;Restore file pointer.
  2462.         pop    es
  2463.         clc
  2464.          ret
  2465. comment_line    endp
  2466.  
  2467. ;-----------------------------------------------------------------------------
  2468. ; HEX2ASC converts a binary number to ASCII and prints it to the screen.
  2469. ; Entry:  AX - binary number
  2470. ;-----------------------------------------------------------------------------
  2471. hex2asc        proc near
  2472.         assume    ds:nothing,es:nothing
  2473.         push    bx
  2474.         mov    cx,5            ;Allow max of five digits
  2475. hex_loop1:
  2476.         xor    dx,dx                   ;Clear high word
  2477.         mov    bx,10            ;Load number base
  2478.         div    bx            ;Divide by base (10)
  2479.         add    dl,30h              ;Convert to ascii
  2480.         push    dx                      ;Save digit on stack
  2481.         loop    hex_loop1
  2482.         mov    cx,5            ;Allow max of five digits
  2483.         mov    bl,"0"            ;Set leading zero indicator
  2484. hex_loop2:
  2485.         pop    dx            ;Get digit off stack
  2486.         or     bl,dl             ;Don't print leading zeros.
  2487.         cmp    bl,"0"            ;The first non zero will
  2488.         je    hex_1            ;  change bl to non-zero.
  2489.         mov    ah,2            ;DOS character output
  2490.         int    21h
  2491. hex_1:
  2492.         loop    hex_loop2
  2493. hex_exit:
  2494.         pop    bx
  2495.          ret
  2496. hex2asc         endp
  2497.  
  2498. ;-----------------------------------------------------------------------------
  2499. ; ASC2BIN - converts an ASCII number of the command line to hex.
  2500. ; Entry:  DS:SI - pointer to ASCII number
  2501. ;-----------------------------------------------------------------------------
  2502. asc2bin        proc    near
  2503.         push    bx
  2504.         xor    bl,bl
  2505.         call    scanline        ;Find next character.
  2506.         mov    di,offset errmsg5    ;Bad number message
  2507.         jc    asc_error        ;If no number found, error
  2508.         mov    bl,al            ;Copy first digit.
  2509.                 xor    ax,ax            ;Clear out sum
  2510.         xor    bh,bh            ;Clear high byte for word adds
  2511. asc_loop:
  2512.         cmp    bl," "          ;If space, assume end of
  2513.         jbe    asc_exit        ;  number.
  2514.         cmp    bl,"]"            ;Exit if closing bracket
  2515.         je    asc_exit        ;  encountered
  2516.         sub    bl,"0"            ;Check for valid number then
  2517.         jb    asc_error        ;  convert to binary.
  2518.         cmp    bl,9
  2519.         ja    asc_error
  2520.         mov    dx,10            ;DX holds base multiplier
  2521.         mul    dx             ;Shift over current number
  2522.         jc    asc_overflow        ;If overflow, indicate error
  2523.         add    ax,bx            ;Add new digit to sum.
  2524.         jcxz    asc_exit        ;If end of file, exit.
  2525.         mov    bl,ds:[si]        ;Get next ASCII character
  2526.         inc    si            ;Point to next character
  2527.         dec    cx            ;Dec file size counter
  2528.         jmp    short asc_loop        ;Go back for more
  2529. asc_exit:
  2530.         clc                ;Clear error flag.
  2531. asc_exit1:
  2532.         pop    bx
  2533.         ret
  2534. asc_overflow:
  2535.         mov    di,offset errmsg12    ;Number too large message.
  2536. asc_error:
  2537.         mov    dx,di            ;Copy message pointer.
  2538.         stc                ;Set error flag.
  2539.         jmp    short asc_exit1
  2540. asc2bin        endp
  2541. ;-----------------------------------------------------------------------------
  2542. ; SCANLINE performs the same function as SCAN4CHAR but keeps track of the
  2543. ; carriage returns.
  2544. ; Entry:  SI - pointer to ASCII string
  2545. ;         BL - 0 = find next char, 1 = find next space
  2546. ;         CX - file length
  2547. ; Exit:   AL - first nonspace character
  2548. ;         CF - set if carriage return found
  2549. ;-----------------------------------------------------------------------------
  2550. scanline    proc    near
  2551.         call    scan4char        ;Find the next char.
  2552.         jnc    scanline_exit
  2553.         inc    cs:[file_linecount]    ;Point to next line.
  2554.         stc
  2555. scanline_exit:
  2556.         ret
  2557. scanline    endp
  2558.  
  2559. end_of_code    =    $
  2560. code        ends
  2561.  
  2562. end        main
  2563.