home *** CD-ROM | disk | FTP | other *** search
/ vsiftp.vmssoftware.com / VSIPUBLIC@vsiftp.vmssoftware.com.tar / FREEWARE / FREEWARE40.ZIP / flistfrontend / src / edtcmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-06  |  8.2 KB  |  355 lines

  1. #ifndef NO_IDENT
  2. static char *Id = "$Id: edtcmd.c,v 1.12 1995/06/06 09:44:14 tom Exp $";
  3. #endif
  4.  
  5. /*
  6.  * Title:    edtcmd.c
  7.  * Author:    Thomas E. Dickey
  8.  * Created:    16 Apr 1985 (from DIRCMD, 10 May 1984)
  9.  * Last update:
  10.  *        19 Feb 1995, prototypes
  11.  *        18 Feb 1995, port to AXP (renamed 'alarm').
  12.  *        27 Apr 1985
  13.  *
  14.  * Entry:    edtcmd:        Accept & edit a command
  15.  *        edtcmd_init:    Initialize this module
  16.  *        edtcmd_get:    Get a single character
  17.  *        edtcmd_last:    Compare argument with last from 'edtcmd_get'.
  18.  *        edtcmd_crt:    Merge input+reference buffers to display.
  19.  */
  20.  
  21. #include    <stdlib.h>
  22. #include    <stdio.h>
  23. #include    <ctype.h>
  24. #include    <string.h>
  25.  
  26. #include    "bool.h"
  27. #include    "cmdstk.h"
  28. #include    "getpad.h"
  29. #include    "getraw.h"
  30. #include    "edtcmd.h"
  31.  
  32. #include    "strutils.h"
  33.  
  34. #define    RUBOUT    '\177'
  35. #define    CTL(c)    (037 & (c))
  36.  
  37. /*
  38.  * 'lastcommand' is used as a 1-level stack to suppress repeated error messages
  39.  *    due to repeated (or stuck) key.  The logic is tested in the main program
  40.  *    of 'FLIST', where all commands are reduced to a single code.
  41.  */
  42. static    int    lastcommand;
  43. static    int    thiscommand;    /* 1-level stack for repeat test */
  44. static    char    *cmdbfr    = nullC;
  45.  
  46. /* <edtcmd_get>:
  47.  * Read a character, saving the previous one, for repeated-key testing.
  48.  * We do screen-dump and refresh here as well:
  49.  */
  50. int
  51. edtcmd_get (void)
  52. {
  53.     lastcommand = thiscommand;
  54.     for (;;)
  55.     {
  56.         switch (thiscommand = getpad())
  57.         {
  58.         case CTL('W'):    crt_refresh ();        break;
  59.         case CTL('K'):    snapshot ();        break;
  60.         default:    return (thiscommand);
  61.         }
  62.     }
  63. }
  64.  
  65. /* <edtcmd_last>:
  66.  * Test if the argument is the same as the previous character.  This is used
  67.  * to latch multiple-keystroke errors (such as from a stuck key).
  68.  */
  69. int
  70. edtcmd_last (int c)
  71. {
  72.     return ((c > 0) && (c == lastcommand));
  73. }
  74.  
  75. /* <edtcmd>:
  76.  * Read/edit a "visible" command
  77.  */
  78.  
  79. #define    doARROW    (flags & 8)    /* Return arrow keys in 128-255 code    */
  80. #define    doHIGH    (flags & 4)    /* Highlight command as it is entered    */
  81. #define    doLOWER    (flags & 2)    /* Lowercase command as it is entered    */
  82. #define    doTRIM    (flags & 1)    /* Trim leading/trailing blanks        */
  83.  
  84. #define    THIS    cmdbfr[col]
  85. #define    PREV    cmdbfr[col-1]
  86. #define    DELETE    {strcpy (&PREV, &THIS); col--; }
  87. #define    SHOWIT    edtcmd_crt (cmdbfr, refbfr, doHIGH, do_col, do_line, col)
  88. #define    COMMAND    (doLOWER ? _tolower(command) : _toupper(command))
  89.  
  90. char *
  91. edtcmd (
  92.     int    command,    /* Initial and scratch value        */
  93.     char    *delim,        /* Delimiters (if used, for repeat-count) */
  94.     int    flags,        /* Bits: highlight, lowercase, trim    */
  95.     int    do_line,    /* Line on which to enter command     */
  96.     int    do_col,        /* Column at which to begin command    */
  97.     char    *do_hlp,    /* Help-interface string        */
  98.     char    *do_1st,    /* Starting contents of command-result    */
  99.     char    *do_ref)    /* Reference copy of command-line    */
  100. {
  101.     int    len,            /* Current command-length    */
  102.         col,            /* Edit-index into 'cmdbfr[]'    */
  103.         maxcols    = crt_width()-do_col-2,    /* Max length of cmd-string */
  104.         complete= FALSE,
  105.         j,
  106.         get_dir    = 1;        /* Normal sense of RETRIEVE    */
  107.     char    refbfr[CRT_COLS],
  108.         tmp[CRT_COLS];
  109.  
  110.  
  111.     cmdstk_tos ();
  112.     strcpy (cmdbfr, do_1st);
  113.     strcpy (refbfr, do_ref);
  114.  
  115. retrieve:
  116.     if (command == RETRIEVE)
  117.     {
  118.         if (cmdstk_get (cmdbfr, get_dir))
  119.         {
  120.             if (! doLOWER)    strucpy (cmdbfr, nullC);
  121.         }
  122.         else
  123.         {
  124.             sound_alarm ();
  125.             goto did_abort;
  126.         }
  127.     }
  128.     else if (isprint(command) && isascii(command))
  129.         sprintf (cmdbfr, "%c", COMMAND);
  130.  
  131.     col    = strlen (cmdbfr);
  132.     get_dir    = 1;            /* Normal sense of RETRIEVE    */
  133.  
  134.     SHOWIT;                /* show the new command    */
  135.     /*
  136.      * Perform restricted command editing a la EDT, by recognizing
  137.      * backspace, linefeed, delete, left/right arrows for editing.
  138.      * Normal printing characters (including space) are inserted at
  139.      * cursor position.
  140.      *
  141.      * If 'doARROW' is set, we do not use arrow-keys for editing/retrieval,
  142.      * but instead pass them back mapped into the range 128-255 on the end
  143.      * of the input string.
  144.      */
  145.     while (!complete)
  146.     {
  147.         ctlx_clr();        /* Reset CTRL/X flag    */
  148.         switch (command = edtcmd_get())
  149.         {
  150.         case padUP:
  151.             if (doARROW)    goto do_arrow;
  152.         case RETRIEVE:
  153.             command    = RETRIEVE;
  154.             get_dir    = 1;
  155.             goto retrieve;
  156.         case padDOWN:
  157.             if (doARROW)    goto do_arrow;
  158.             command    = RETRIEVE;
  159.             get_dir = -1;
  160.             goto retrieve;
  161.         case RUBOUT:
  162.             if (col)    DELETE
  163.             else        sound_alarm ();
  164.             break;
  165.         case CTL('X'):
  166.         case CTL('U'):
  167.         case CTL('C'):
  168.         case CTL('Y'):
  169.             cmdbfr[0] = cmdbfr[1] = col = 0;
  170.             break;
  171.         case padENTER:
  172.         case '\r':
  173.             if (delim)
  174.             {
  175.                 if (strchr(delim, command))
  176.                     complete = TRUE;
  177.                 else
  178.                     sound_alarm();
  179.             }
  180.             else
  181.                 complete = TRUE;
  182.             break;
  183.         case '\n':
  184.             if (col)
  185.             {
  186.                 if (isspace(PREV))
  187.                 {
  188.                     while (col && isspace(PREV))
  189.                         DELETE
  190.                 }
  191.                 while (col && !isspace(PREV))
  192.                     DELETE
  193.             }
  194.             else        sound_alarm();
  195.             break;
  196.         case padLEFT:        /* left-arrow    */
  197.             if (doARROW)    goto do_arrow;
  198.         case CTL('D'):        /* (cf: VMS 4.0)*/
  199.             if (col > 0)    col--;
  200.             else        sound_alarm();
  201.             break;
  202.  
  203.         case padRIGHT:        /* right-arrow    */
  204.             if (doARROW)    goto do_arrow;
  205.         case CTL('F'):        /* (cf: VMS 4.0)*/
  206.             if (col < maxcols-1)
  207.             {
  208.                 if (++col >= strlen(cmdbfr))
  209.                     strcat (cmdbfr, " ");
  210.             }
  211.             else
  212.                 sound_alarm();
  213.             break;        
  214.  
  215.         case '\b':
  216.         case pad0:
  217.             col = 0;
  218.             break;
  219.         case pad2:
  220.         case CTL('E'):        /* (a la VMS 4.0)    */
  221.             col = strlen(cmdbfr);
  222.             break;
  223.         case HELPKEY:
  224.             crt_help (nullC, do_hlp);
  225.             break;
  226.         case ' ':
  227.             if (doTRIM && col == 0)
  228.             {
  229.                 sound_alarm ();
  230.                 break;
  231.             }
  232.         default:
  233.             if (isascii(command)
  234.             &&  isprint(command)
  235.             &&  strlen(cmdbfr) < maxcols)
  236.             {
  237.             register int use_it = TRUE;
  238.                 /*
  239.                  * If we have a delimiter, it will be returned
  240.                  * as the last character on the command-string
  241.                  * (unless it happens to be '\n').
  242.                  */
  243.                 command = COMMAND;
  244.                 if (delim)
  245.                 {
  246.                     if (strchr(delim, command))
  247.                         complete = TRUE;
  248.                     else if (!isdigit(command))
  249.                         use_it = FALSE;    
  250.                 }
  251.                 if (use_it)
  252.                 {
  253.                     strcpy (tmp, &THIS);
  254.                     strtrim (tmp);
  255.                     sprintf (&THIS, "%c%s", command, tmp);
  256.                     col++;
  257.                 }
  258.                 else
  259.                     sound_alarm ();
  260.             }
  261.             else
  262.                 sound_alarm ();
  263.         }    /* end:switch(command) */
  264.         /*
  265.          * Cursor movement may temporarily lengthen the buffer.  Trim
  266.          * trailing blanks:
  267.          */
  268.         len    = doTRIM ? strtrim(cmdbfr) : strlen(cmdbfr);
  269.         j    = max(len, col) - len;
  270.         while (j-- > 0)
  271.             strcat  (cmdbfr, " ");
  272.  
  273.         if (!gotraw() || complete) SHOWIT;
  274.         if (strlen(cmdbfr) <= 0)
  275.         {
  276.             cmdbfr[0] = EOS;
  277.             goto did_abort;
  278.         }
  279.  
  280.         /*
  281.          * Enter this block to return an arrow-key (or other keypad
  282.          * control, as required), mapped into the range 128-255.
  283.          */
  284.         command    = EOS;
  285. do_arrow:    if (command > 255)    /* 'pad' codes are 256-511    */
  286.         {
  287.             SHOWIT;
  288.             sprintf (tmp, "%c", command | 128);
  289.             strcat (cmdbfr, tmp);
  290.             complete = TRUE;
  291.         }
  292.  
  293.     }    /* end:while (! complete) */
  294. did_abort:
  295.     lastcommand = EOS;
  296.     ctlx_clr ();        /* Reset CTRL/X flag    */
  297.     return (cmdbfr);
  298. }
  299.  
  300. /* <edtcmd_init>:
  301.  * Initialize this module.  We need a buffer in which to build commands,
  302.  * 'cmdbfr', as well as a buffer in which to store the prior-state of a
  303.  * line which we are receiving upon.
  304.  */
  305. void
  306. edtcmd_init (void)
  307. {
  308.     cmdbfr = calloc(1, CRT_COLS+1);
  309.     lastcommand = EOS;
  310. }
  311.  
  312. /* <edtcmd_crt>:
  313.  * Display the text for the current "visible-command".  The command-text is
  314.  * displayed *highlighted*, with a trailing space (so that if we are overstriking
  315.  * a display-line, there is a gap).  The cursor is positioned to the current-
  316.  * column.
  317.  *
  318.  * This procedure is self-contained (does not directly reference any static
  319.  * data).
  320.  */
  321. void
  322. edtcmd_crt (
  323.     char    *cmd_,    /* Text to overlay 'ref_[]'        (asciz)    */
  324.     char    *ref_,    /* Reference, to restore/update            */
  325.     int    highlight, /* Do highlighting of new text if true    */
  326.     int    rcol,    /* Column at which 'cmd_[]' is put     1..n    */
  327.     int    rline,    /* Reference: line in screen         1..n    */
  328.     int    ccol)    /* Reference: cursor-column in 'cmd_[]', 0..n    */
  329. {
  330.     int    j    = strlen(ref_),
  331.         len    = strlen(cmd_);
  332.     char    *c_,
  333.         tocmp    [CRT_COLS],
  334.         toshow    [CRT_COLS];
  335.  
  336.     for (c_ = toshow; *cmd_; c_++, cmd_++)
  337.     {
  338.         if (highlight)
  339.             *c_ = tohigh(*cmd_);
  340.         else
  341.             *c_ = *cmd_;
  342.     }
  343.  
  344.     strcpy (tocmp, ref_);
  345.     while (j < rcol)    strcpy (&tocmp[j++], " ");
  346.     strncpy (&tocmp[rcol-1], toshow, len);
  347.     j     = rcol + len - 1;
  348.     tocmp[j] = ' ';            /* add a space on the end */
  349.     if (strlen(ref_) <= j)
  350.         tocmp[j+1] = '\0';    /* ...but keep trailing null */
  351.  
  352.     crt_text (tocmp, rline, 0);
  353.     crt_move (rline+1, rcol+ccol);
  354. }
  355.