home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 036 / less232.zip / CMDBUF.C < prev    next >
C/C++ Source or Header  |  1994-09-02  |  17KB  |  915 lines

  1. /*
  2.  * Copyright (c) 1984,1985,1989,1994  Mark Nudelman
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice in the documentation and/or other materials provided with 
  12.  *    the distribution.
  13.  *
  14.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
  15.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  17.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
  18.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  19.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
  20.  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
  21.  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  22.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
  23.  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 
  24.  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25.  */
  26.  
  27.  
  28. /*
  29.  * Functions which manipulate the command buffer.
  30.  * Used only by command() and related functions.
  31.  */
  32.  
  33. #include "less.h"
  34. #define    LITERAL    ('\\')
  35.  
  36. extern int sc_width;
  37.  
  38. static char cmdbuf[120];    /* Buffer for holding a multi-char command */
  39. static int cmd_col;        /* Current column of the multi-char command */
  40. static char *cp;        /* Pointer into cmdbuf */
  41.  
  42. #if TAB_COMPLETE_FILENAME
  43. static int cmd_complete();
  44. /*
  45.  * These variables are statics used by cmd_complete.
  46.  */
  47. static int in_completion = 0;
  48. static char *tk_text;
  49. static char *tk_original;
  50. static char *tk_ipoint;
  51. static char *tk_trial;
  52. static struct textlist tk_tlist;
  53. #endif
  54.  
  55. #if CMD_HISTORY
  56. /*
  57.  * A mlist structure represents a command history.
  58.  */
  59. struct mlist
  60. {
  61.     struct mlist *next;
  62.     struct mlist *prev;
  63.     struct mlist *curr_mp;
  64.     char *string;
  65. };
  66.  
  67. /*
  68.  * These are the various command histories that exist.
  69.  */
  70. struct mlist mlist_search =  
  71.     { &mlist_search,  &mlist_search,  &mlist_search,  NULL };
  72. public void *ml_search = (void *) &mlist_search;
  73. struct mlist mlist_examine = 
  74.     { &mlist_examine, &mlist_examine, &mlist_examine, NULL };
  75. public void *ml_examine = (void *) &mlist_examine;
  76. #if SHELL_ESCAPE || PIPEC
  77. struct mlist mlist_shell =   
  78.     { &mlist_shell,   &mlist_shell,   &mlist_shell,   NULL };
  79. public void *ml_shell = (void *) &mlist_shell;
  80. #endif /* SHELL_ESCAPE || PIPEC */
  81.  
  82. /*
  83.  * History for the current command.
  84.  */
  85. static struct mlist *curr_mlist = NULL;
  86.  
  87. #endif /* CMD_HISTORY */
  88.  
  89. /*
  90.  * Reset command buffer (to empty).
  91.  */
  92.     public void
  93. cmd_reset()
  94. {
  95.     cp = cmdbuf;
  96.     *cp = '\0';
  97.     cmd_col = 0;
  98. }
  99.  
  100. /*
  101.  * How many characters are in the command buffer?
  102.  */
  103.     public int
  104. len_cmdbuf()
  105. {
  106.     return (strlen(cmdbuf));
  107. }
  108.  
  109. /*
  110.  * Backspace in the command buffer.
  111.  * Delete the char to the left of the cursor.
  112.  */
  113.     static int
  114. cmd_erase()
  115. {
  116.     register char *s;
  117.     char *p;
  118.     int col;
  119.  
  120.     if (cp == cmdbuf)
  121.     {
  122.         /*
  123.          * Backspace past beginning of the buffer:
  124.          * this usually means abort the command.
  125.          */
  126.         return (CC_QUIT);
  127.     }
  128.     /*
  129.      * Back up the pointer.
  130.      */
  131.     --cp;
  132.     /*
  133.      * Remember the current cursor column and 
  134.      * set it back the width of the char being erased.
  135.      */
  136.     col = cmd_col;
  137.     p = prchar(*cp);
  138.     cmd_col -= strlen(p);
  139.     /*
  140.      * Shift left the buffer after the erased char.
  141.      */
  142.     for (s = cp;  *s != '\0';  s++)
  143.         s[0] = s[1];
  144.     /*
  145.      * Back up the cursor to the position of the erased char,
  146.      * clear the tail of the line,
  147.      * and reprint the line after the erased char.
  148.      */
  149.     while (col > cmd_col)
  150.     {
  151.         putbs();
  152.         col--;
  153.     }
  154.     clear_eol();
  155.     for (s = cp;  *s != '\0';  s++)
  156.     {
  157.         p = prchar(*s);
  158.         putstr(p);
  159.         col += strlen(p);
  160.     }
  161.     /*
  162.      * Back up the cursor again.
  163.      */
  164.     while (col > cmd_col)
  165.     {
  166.         putbs();
  167.         col--;
  168.     }
  169.     
  170.     /*
  171.      * This is rather weird.
  172.      * We say that erasing the entire command string causes us
  173.      * to abort the current command, BUT ONLY IF there is no history
  174.      * for this type of command.  This causes commands like search (/)
  175.      * and edit (:e) to stay active even if we erase the entire string,
  176.      * but commands like <digit> and - go away when we erase the string.
  177.      * (See same thing in cmd_kill.)
  178.      */
  179.     if (curr_mlist == NULL && cp == cmdbuf && *cp == '\0')
  180.         return (CC_QUIT);
  181.     return (CC_OK);
  182. }
  183.  
  184. /*
  185.  * Delete the char under the cursor.
  186.  */
  187.     static int
  188. cmd_delete()
  189. {
  190.     char *p;
  191.     
  192.     if (*cp == '\0')
  193.     {
  194.         /*
  195.          * At end of string; there is no char under the cursor.
  196.          */
  197.         return (CC_OK);
  198.     }
  199.     /*
  200.      * Move right, then use cmd_erase.
  201.      */
  202.     p = prchar(*cp);
  203.     cp++;
  204.     putstr(p);
  205.     cmd_col += strlen(p);
  206.     cmd_erase();
  207.     return (CC_OK);
  208. }
  209.  
  210. /*
  211.  * Delete the "word" to the left of the cursor.
  212.  */
  213.     static int
  214. cmd_werase()
  215. {
  216.     if (cp > cmdbuf && cp[-1] == ' ')
  217.     {
  218.         /*
  219.          * If the char left of cursor is a space,
  220.          * erase all the spaces left of cursor (to the first non-space).
  221.          */
  222.         while (cp > cmdbuf && cp[-1] == ' ')
  223.             (void) cmd_erase();
  224.     } else
  225.     {
  226.         /*
  227.          * If the char left of cursor is not a space,
  228.          * erase all the nonspaces left of cursor (the whole "word").
  229.          */
  230.         while (cp > cmdbuf && cp[-1] != ' ')
  231.             (void) cmd_erase();
  232.     }
  233.     return (CC_OK);
  234. }
  235.  
  236. /*
  237.  * Delete the "word" under the cursor.
  238.  */
  239.     static int
  240. cmd_wdelete()
  241. {
  242.     if (*cp == ' ')
  243.     {
  244.         /*
  245.          * If the char under the cursor is a space,
  246.          * delete it and all the spaces right of cursor.
  247.          */
  248.         while (*cp == ' ')
  249.             (void) cmd_delete();
  250.     } else
  251.     {
  252.         /*
  253.          * If the char under the cursor is not a space,
  254.          * delete it and all nonspaces right of cursor (the whole word).
  255.          */
  256.         while (*cp != ' ' && *cp != '\0')
  257.             (void) cmd_delete();
  258.     }
  259.     return (CC_OK);
  260. }
  261.  
  262. /*
  263.  * Move cursor to start of command buffer.
  264.  */
  265.     static int
  266. cmd_home()
  267. {
  268.     char *p;
  269.     
  270.     /*
  271.      * Back up until we hit start of buffer.
  272.      */
  273.     while (cp > cmdbuf)
  274.     {
  275.         cp--;
  276.         p = prchar(*cp);
  277.         cmd_col -= strlen(p);
  278.         while (*p++ != '\0')
  279.             putbs();
  280.     }
  281.     return (CC_OK);
  282. }
  283.  
  284. /*
  285.  * Delete all chars in the command buffer.
  286.  */
  287.     static int
  288. cmd_kill()
  289. {
  290.     if (cmdbuf[0] == '\0')
  291.     {
  292.         /*
  293.          * Buffer is already empty; abort the current command.
  294.          */
  295.         return (CC_QUIT);
  296.     }
  297.     (void) cmd_home();
  298.     *cp = '\0';
  299.     clear_eol();
  300.     /*
  301.      * Same weirdness as in cmd_erase.
  302.      * If the current command has no history, abort the current command.
  303.      */
  304.     if (curr_mlist == NULL)
  305.         return (CC_QUIT);
  306.     return (CC_OK);
  307. }
  308.  
  309. /*
  310.  * Move cursor right one character.
  311.  */
  312.     static int
  313. cmd_right()
  314. {
  315.     char *p;
  316.     
  317.     if (*cp == '\0')
  318.     {
  319.         /* 
  320.          * Already at the end of the line.
  321.          */
  322.         return (CC_OK);
  323.     }
  324.     p = prchar(*cp);
  325.     cp++;
  326.     putstr(p);
  327.     cmd_col += strlen(p);
  328.     return (CC_OK);
  329. }
  330.  
  331. /*
  332.  * Move cursor left one character.
  333.  */
  334.     static int
  335. cmd_left()
  336. {
  337.     char *p;
  338.     
  339.     if (cp <= cmdbuf)
  340.     {
  341.         /* Already at the beginning of the line */
  342.         return (CC_OK);
  343.     }
  344.     cp--;
  345.     p = prchar(*cp);
  346.     cmd_col -= strlen(p);
  347.     while (*p++ != '\0')
  348.         putbs();
  349.     return (CC_OK);
  350. }
  351.  
  352. #if CMD_HISTORY
  353. /*
  354.  * Select an mlist structure to be the current command history.
  355.  */
  356.     public void
  357. set_mlist(mlist)
  358.     void *mlist;
  359. {
  360.     curr_mlist = (struct mlist *) mlist;
  361. }
  362.  
  363. /*
  364.  * Move up or down in the currently selected command history list.
  365.  */
  366.     static int
  367. cmd_updown(action)
  368.     int action;
  369. {
  370.     char *p;
  371.     char *s;
  372.     
  373.     if (curr_mlist == NULL)
  374.     {
  375.         /*
  376.          * The current command has no history list.
  377.          */
  378.         bell();
  379.         return (CC_OK);
  380.     }
  381.     cmd_home();
  382.     clear_eol();
  383.     /*
  384.      * Move curr_mp to the next/prev entry.
  385.      */
  386.     if (action == EC_UP)
  387.         curr_mlist->curr_mp = curr_mlist->curr_mp->prev;
  388.     else
  389.         curr_mlist->curr_mp = curr_mlist->curr_mp->next;
  390.     /*
  391.      * Copy the entry into cmdbuf and echo it on the screen.
  392.      */
  393.     s = curr_mlist->curr_mp->string;
  394.     if (s == NULL)
  395.         s = "";
  396.     for (cp = cmdbuf;  *s != '\0';  s++, cp++)
  397.     {
  398.         *cp = *s;
  399.         p = prchar(*cp);
  400.         cmd_col += strlen(p);
  401.         putstr(p);
  402.     }
  403.     *cp = '\0';
  404.     return (CC_OK);
  405. }
  406.  
  407. /*
  408.  * Accept the command in the command buffer.
  409.  * Add it to the currently selected history list.
  410.  */
  411.     public void
  412. cmd_accept()
  413. {
  414.     struct mlist *ml;
  415.     
  416.     /*
  417.      * Nothing to do if there is no currently selected history list.
  418.      */
  419.     if (curr_mlist == NULL)
  420.         return;
  421.     /*
  422.      * Don't save a trivial command.
  423.      */
  424.     if (strlen(cmdbuf) == 0)
  425.         return;
  426.     /*
  427.      * Don't save if a duplicate of a command which is already in the history.
  428.      * But select the one already in the history to be current.
  429.      */
  430.     for (ml = curr_mlist->next;  ml != curr_mlist;  ml = ml->next)
  431.     {
  432.         if (strcmp(ml->string, cmdbuf) == 0)
  433.             break;
  434.     }
  435.     if (ml == curr_mlist)
  436.     {
  437.         /*
  438.          * Did not find command in history.
  439.          * Save the command and put it at the end of the history list.
  440.          */
  441.         ml = (struct mlist *) ecalloc(1, sizeof(struct mlist));
  442.         ml->string = save(cmdbuf);
  443.         ml->next = curr_mlist;
  444.         ml->prev = curr_mlist->prev;
  445.         curr_mlist->prev->next = ml;
  446.         curr_mlist->prev = ml;
  447.     }
  448.     /*
  449.      * Point to the cmd just after the just-accepted command.
  450.      * Thus, an UPARROW will always retrieve the previous command.
  451.      */
  452.     curr_mlist->curr_mp = ml->next;
  453. }
  454. #endif
  455.  
  456. /*
  457.  * Try to perform a line-edit function on the command buffer,
  458.  * using a specified char as a line-editing command.
  459.  * Returns:
  460.  *    CC_PASS    The char does not invoke a line edit function.
  461.  *    CC_OK    Line edit function done.
  462.  *    CC_QUIT    The char requests the current command to be aborted.
  463.  */
  464.     static int
  465. cmd_edit(c)
  466.     int c;
  467. {
  468.     int action;
  469.     
  470.     /*
  471.      * See if the char is indeed a line-editing command.
  472.      */
  473.     action = editchar(c, (curr_mlist == NULL) ? EC_NOHISTORY : 0);
  474.     switch (action)
  475.     {
  476.     case EC_RIGHT:
  477.         in_completion = 0;
  478.         return (cmd_right());
  479.     case EC_LEFT:
  480.         in_completion = 0;
  481.         return (cmd_left());
  482.     case EC_W_RIGHT:
  483.         in_completion = 0;
  484.         while (*cp != '\0' && *cp != ' ')
  485.             cmd_right();
  486.         while (*cp == ' ')
  487.             cmd_right();
  488.         return (CC_OK);
  489.     case EC_W_LEFT:
  490.         in_completion = 0;
  491.         while (cp > cmdbuf && cp[-1] == ' ')
  492.             cmd_left();
  493.         while (cp > cmdbuf && cp[-1] != ' ')
  494.             cmd_left();
  495.         return (CC_OK);
  496.     case EC_HOME:
  497.         in_completion = 0;
  498.         return (cmd_home());
  499.     case EC_END:
  500.         in_completion = 0;
  501.         while (*cp != '\0')
  502.             cmd_right();
  503.         return (CC_OK);
  504.     case EC_INSERT:
  505.         in_completion = 0;
  506.         return (CC_OK);
  507.     case EC_BACKSPACE:
  508.         in_completion = 0;
  509.         return (cmd_erase());
  510.     case EC_LINEKILL:
  511.         in_completion = 0;
  512.         return (cmd_kill());
  513.     case EC_W_BACKSPACE:
  514.         in_completion = 0;
  515.         return (cmd_werase());
  516.     case EC_DELETE:
  517.         in_completion = 0;
  518.         return (cmd_delete());
  519.     case EC_W_DELETE:
  520.         in_completion = 0;
  521.         return (cmd_wdelete());
  522. #if CMD_HISTORY
  523.     case EC_UP:
  524.     case EC_DOWN:
  525.         in_completion = 0;
  526.         return (cmd_updown(action));
  527. #endif
  528. #if TAB_COMPLETE_FILENAME
  529.     case EC_F_COMPLETE:
  530.     case EC_B_COMPLETE:
  531.     case EC_EXPAND:
  532.         return (cmd_complete(action));
  533. #endif
  534.     default:
  535.         in_completion = 0;
  536.         return (CC_PASS);
  537.     }
  538. }
  539.  
  540. /*
  541.  * Insert a char into the command buffer, at the current position.
  542.  */
  543.     static int
  544. cmd_ichar(c)
  545.     int c;
  546. {
  547.     int col;
  548.     char *p;
  549.     char *s;
  550.     
  551.     if (strlen(cmdbuf) >= sizeof(cmdbuf)-2)
  552.     {
  553.         /*
  554.          * No room in the command buffer for another char.
  555.          */
  556.         bell();
  557.         return (CC_ERROR);
  558.     }
  559.         
  560.     /*
  561.      * Remember the current cursor column and 
  562.      * move it forward the width of the char being inserted.
  563.      */
  564.     col = cmd_col;
  565.     p = prchar(c);
  566.     cmd_col += strlen(p);
  567.     if (cmd_col >= sc_width-1)
  568.     {
  569.         cmd_col -= strlen(p);
  570.         bell();
  571.         return (CC_ERROR);
  572.     }
  573.     /*
  574.      * Insert the character in the string.
  575.      * First, make room for the new char.
  576.      */
  577.     for (s = &cmdbuf[strlen(cmdbuf)];  s >= cp;  s--)
  578.         s[1] = s[0];
  579.     *cp++ = c;
  580.     /*
  581.      * Reprint the tail of the line after the inserted char.
  582.      */
  583.     clear_eol();
  584.     for (s = cp-1;  *s != '\0';  s++)
  585.     {
  586.         p = prchar(*s);
  587.         col += strlen(p);
  588.         if (col >= sc_width-1)
  589.         {
  590.             /*
  591.              * Oops.  There is no room on the screen
  592.              * for the new char.  Back up the cursor to
  593.              * just after the inserted char and erase it.
  594.              */
  595.             col -= strlen(p);
  596.             while (col > cmd_col)
  597.             {
  598.                 putbs();
  599.                 col--;
  600.             }
  601.             (void) cmd_erase();
  602.             bell();
  603.             return (CC_ERROR);
  604.         }
  605.         putstr(p);
  606.     }
  607.     /*
  608.      * Back up the cursor to just after the inserted char.
  609.      */
  610.     while (col > cmd_col)
  611.     {
  612.         putbs();
  613.         col--;
  614.     }
  615.     return (CC_OK);
  616. }
  617.  
  618. #if TAB_COMPLETE_FILENAME
  619. /*
  620.  * Insert a string into the command buffer, at the current position.
  621.  */
  622.     static int
  623. cmd_istr(str)
  624.     char *str;
  625. {
  626.     char *s;
  627.     int action;
  628.     
  629.     for (s = str;  *s != '\0';  s++)
  630.     {
  631.         action = cmd_ichar(*s);
  632.         if (action != CC_OK)
  633.         {
  634.             bell();
  635.             return (action);
  636.         }
  637.     }
  638.     return (CC_OK);
  639. }
  640.  
  641. /*
  642.  * Find the beginning and end of the "current" word.
  643.  * This is the word which the cursor (cp) is inside or at the end of.
  644.  * Return pointer to the beginning of the word and put the
  645.  * cursor at the end of the word.
  646.  */
  647.     static char *
  648. delimit_word()
  649. {
  650.     char *word;
  651.     
  652.     /*
  653.      * Move cursor to end of word.
  654.      */
  655.     if (*cp != ' ')
  656.     {
  657.         /*
  658.          * Cursor is on a nonspace.
  659.          * Move cursor right to the next space.
  660.          */
  661.         while (*cp != ' ' && *cp != '\0')
  662.             cmd_right();
  663.     } else if (cp[-1] != ' ')
  664.     {
  665.         /*
  666.          * Cursor is on a space, and char to the left is a nonspace.
  667.          * We're already at the end of the word.
  668.          */
  669.         ;
  670.     } else /* (*cp == ' ' && cp[-1] == ' ') */
  671.     {
  672.         /*
  673.          * Cursor is on a space and char to the left is a space.
  674.          * Huh? There's no word here.
  675.          */
  676.         return (NULL);
  677.     }
  678.     /*
  679.      * Search backwards for beginning of the word.
  680.      */
  681.     for (word = cp-1;  word > cmdbuf;  word--)
  682.         if (word[-1] == ' ')
  683.             break;
  684.     return (word);
  685. }
  686.  
  687. /*
  688.  * Set things up to enter completion mode.
  689.  * Expand the word under the cursor into a list of filenames 
  690.  * which start with that word, and set tk_text to that list.
  691.  */
  692.     static void
  693. init_compl()
  694. {
  695.     char *word;
  696.     char c;
  697.     
  698.     /*
  699.      * Get rid of any previous tk_text.
  700.      */
  701.     if (tk_text != NULL)
  702.     {
  703.         free(tk_text);
  704.         tk_text = NULL;
  705.     }
  706.     /*
  707.      * Find the original (uncompleted) word in the command buffer.
  708.      */
  709.     word = delimit_word();
  710.     if (word == NULL)
  711.         return;
  712.     /*
  713.      * Set the insertion point to the point in the command buffer
  714.      * where the original (uncompleted) word now sits.
  715.      */
  716.     tk_ipoint = word;
  717.     /*
  718.      * Save the original (uncompleted) word
  719.      */
  720.     if (tk_original != NULL)
  721.         free(tk_original);
  722.     tk_original = (char *) ecalloc(cp-word+1, sizeof(char));
  723.     strncpy(tk_original, word, cp-word);
  724.     /*
  725.      * Get the expanded filename.
  726.      * This may result in a single filename, or
  727.      * a blank-separated list of filenames.
  728.      */
  729.     c = *cp;
  730.     *cp = '\0';
  731.     tk_text = fcomplete(word);
  732.     *cp = c;
  733. }
  734.  
  735. /*
  736.  * Return the next word in the current completion list.
  737.  */
  738.     static char *
  739. next_compl(action, prev)
  740.          int action;
  741.     char *prev;
  742. {
  743.     switch (action)
  744.     {
  745.     case EC_F_COMPLETE:
  746.         return (forw_textlist(&tk_tlist, prev));
  747.     case EC_B_COMPLETE:
  748.         return (back_textlist(&tk_tlist, prev));
  749.     default:
  750.         /* Cannot happen */
  751.         return ("?");
  752.     }
  753. }
  754.  
  755. /*
  756.  * Complete the filename before (or under) the cursor.
  757.  * cmd_complete may be called multiple times.  The global in_completion
  758.  * remembers whether this call is the first time (create the list),
  759.  * or a subsequent time (step thru the list).
  760.  */
  761.     static int
  762. cmd_complete(action)
  763.     int action;
  764. {
  765.  
  766.     if (!in_completion || action == EC_EXPAND)
  767.     {
  768.         /*
  769.          * Expand the word under the cursor and 
  770.          * use the first word in the expansion 
  771.          * (or the entire expansion if we're doing EC_EXPAND).
  772.          */
  773.         init_compl();
  774.         if (tk_text == NULL)
  775.         {
  776.             bell();
  777.             return (CC_OK);
  778.         }
  779.         if (action == EC_EXPAND)
  780.         {
  781.             /*
  782.              * Use the whole list.
  783.              */
  784.             tk_trial = tk_text;
  785.         } else
  786.         {
  787.             /*
  788.              * Use the first filename in the list.
  789.              */
  790.             in_completion = 1;
  791.             init_textlist(&tk_tlist, tk_text);
  792.             tk_trial = next_compl(action, (char*)NULL);
  793.         }
  794.     } else
  795.     {
  796.         /*
  797.          * We already have a completion list.
  798.          * Use the next/previous filename from the list.
  799.          */
  800.         tk_trial = next_compl(action, tk_trial);
  801.     }
  802.     
  803.       /*
  804.        * Remove the original word, or the previous trial completion.
  805.        */
  806.     while (cp > tk_ipoint)
  807.         (void) cmd_erase();
  808.     
  809.     if (tk_trial == NULL)
  810.     {
  811.         /*
  812.          * There are no more trial completions.
  813.          * Insert the original (uncompleted) filename.
  814.          */
  815.         in_completion = 0;
  816.         if (cmd_istr(tk_original) != CC_OK)
  817.             goto fail;
  818.     } else
  819.     {
  820.         /*
  821.          * Insert trial completion.
  822.          */
  823.         if (cmd_istr(tk_trial) != CC_OK)
  824.             goto fail;
  825.     }
  826.     
  827.     return (CC_OK);
  828.     
  829. fail:
  830.     in_completion = 0;
  831.     bell();
  832.     return (CC_OK);
  833. }
  834.  
  835. #endif /* TAB_COMPLETE_FILENAME */
  836.  
  837. /*
  838.  * Process a single character of a multi-character command, such as
  839.  * a number, or the pattern of a search command.
  840.  * Returns:
  841.  *    CC_OK        The char was accepted.
  842.  *    CC_QUIT        The char requests the command to be aborted.
  843.  *    CC_ERROR    The char could not be accepted due to an error.
  844.  */
  845.     public int
  846. cmd_char(c)
  847.     int c;
  848. {
  849.     int action;
  850.  
  851.     if (*cp == LITERAL)
  852.     {
  853.         /*
  854.          * Delete the LITERAL char and insert the new char.
  855.          */
  856.         cmd_delete();
  857.         return (cmd_ichar(c));
  858.     }
  859.         
  860.     /*
  861.      * See if it is a special line-editing character.
  862.      */
  863.     if (in_mca())
  864.     {
  865.         action = cmd_edit(c);
  866.         switch (action)
  867.         {
  868.         case CC_OK:
  869.         case CC_QUIT:
  870.             return (action);
  871.         case CC_PASS:
  872.             break;
  873.         }
  874.     }
  875.     
  876.     /*
  877.      * Insert the char into the command buffer.
  878.      */
  879.     action = cmd_ichar(c);
  880.     if (action != CC_OK)
  881.         return (action);
  882.     if (c == LITERAL)
  883.         cmd_left();
  884.     return (CC_OK);
  885. }
  886.  
  887. /*
  888.  * Return the number currently in the command buffer.
  889.  */
  890.     public int
  891. cmd_int()
  892. {
  893.     return (atoi(cmdbuf));
  894. }
  895.  
  896. /*
  897.  * Display a string, usually as a prompt for input into the command buffer.
  898.  */
  899.     public void
  900. cmd_putstr(s)
  901.     char *s;
  902. {
  903.     putstr(s);
  904.     cmd_col += strlen(s);
  905. }
  906.  
  907. /*
  908.  * Return a pointer to the command buffer.
  909.  */
  910.     public char *
  911. get_cmdbuf()
  912. {
  913.     return (cmdbuf);
  914. }
  915.