home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / snip9707.zip / EDITGETS.C < prev    next >
C/C++ Source or Header  |  1997-07-05  |  15KB  |  442 lines

  1. /* +++Date last modified: 05-Jul-1997 */
  2.  
  3. /* editgets.c - line input w/editing                                        */
  4. /* this code is released to the public domain                               */
  5. /* written by Jon Burchmore                                                 */
  6. /* modifications & enhancements by Bob Stout                                */
  7.  
  8. /* This is as close to ANSI compliant C that I could come, but it was made  */
  9. /* on an IBM compatible computer, so I designed it for that platform.       */
  10.  
  11. /* EXT_KEYS.C in SNIPPETS provides the ext_getch() function, which returns  */
  12. /* a single extended character from the KEYBOARD, not stdin, and waits if   */
  13. /* it must. It is be possible to re-write this function for a computer      */
  14. /* besides an IBM PC. To do so, just rewrite EXT_KEYS.C and using the same  */
  15. /* key definitions in EXT_KEYS.H                                            */
  16.  
  17. /* Similarly, CURSOR.C in SNIPPETS is used to make the cursor larger when   */
  18. /* in insert mode and smaller when in overwrite mode. To port to a non-PC   */
  19. /* system, simply rewrite CURSOR.C using the same prototype and calling     */
  20. /* parameters as specified in CURSOR.H.                                     */
  21.  
  22. #include <conio.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <ctype.h>
  27. #include <time.h>
  28. #include "sniptype.h"
  29. #include "ext_keys.h"
  30. #include "cursor.h"
  31. #include "editgets.h"
  32. #include "minmax.h"
  33.  
  34. #define CTRL_CHARS_ALLOWED 0  /* Non-zero allows entry of Ctrl-characters   */
  35.  
  36. #define BAD_KEY() {fputc('\a', stderr); break;}
  37. #define putch(x)   fputc((x), stderr)
  38.  
  39. int TabSize = 8;
  40.  
  41. /*
  42. **  Password mode:
  43. **
  44. **  0 - Normal operation
  45. **  1 - Conventional password mode - '*' is echoed for all characters,
  46. **      only ESC, ENTER, BACKSPC, and CTLHOME are active.
  47. **  2 - Secure password mode - same as above except random characters are
  48. **      displayed rather than '*'s to distract snoops from watching the keys.
  49. */
  50.  
  51. int password_mode = 0;
  52.  
  53. static const char PWchars[] = /* Frequency approximates English usage   */
  54.       "aaabbccddeeeeffgghhiiijklllmmmnnnoooppqrrrsssstttuuvwwxyz"
  55.       "1234567890-|,@._"
  56.       "aaabbccddeeeeffgghhiiijklllmmmnnnoooppqrrrsssstttuuvwwxyz";
  57.  
  58. static int pickPWchar(void);
  59.  
  60. /*
  61. **  Arguments: 1) Buffer to receive string
  62. **             2) Size of buffer
  63. **             3) Default string
  64. */
  65.  
  66. int editgets(char *s, int maxlen, char *string)
  67. {
  68.       char temp[500];         /* Working buffer                         */
  69.       int   insert,           /* Non-zero if in insert mode             */
  70.             done = 0,         /* Non-Zero if done                       */
  71.             pos,              /* Our position within the string         */
  72.             len,              /* The current length of the string       */
  73.             i, j, k,          /* Temporary variables                    */
  74.             c,                /* Keyboard input                         */
  75.             skip;             /* Spaces to skip when tabbing            */
  76.  
  77.       if (NULL == string)
  78.             string = "";
  79.  
  80.       if (0 != (pos = len = strlen(string)))
  81.             strncpy(temp, string, min(len, maxlen));
  82.  
  83.       for (i = 0; i < maxlen; ++i)
  84.       {
  85.             if (NUL == *string)
  86.                   putch('_');
  87.             else  putch(*string++);
  88.       }
  89.       for (i = 0; i < (maxlen - len); ++i)
  90.             putch('\b');
  91.       fflush(stderr);
  92.  
  93.       /* Set insert mode, save cursor, and use a big cursor */
  94.  
  95.       insert = 1;
  96.       cursor('S');
  97.       cursor('B');
  98.  
  99.       while (!done)
  100.       {
  101.             c = ext_getch();
  102.             switch (c)
  103.             {
  104.             case Key_ESC :
  105.                   if (len == 0)
  106.                         break;
  107.                   if (pos != len)
  108.                   {
  109.                         for (i = pos; i < len; i++)
  110.                               putch('_');
  111.                   }
  112.                   for (i = len; i > 0; i--)
  113.                   {
  114.                         putch('\b');
  115.                         putch('_');
  116.                         putch('\b');
  117.                   }
  118.                   pos = len = 0;
  119.                   break;
  120.  
  121.             case Key_LTARROW :
  122.             case Key_PLTARROW :
  123.                   if (password_mode)
  124.                         BAD_KEY();
  125.                   if (pos == 0)
  126.                         break;
  127.                   pos--;
  128.                   putch('\b');
  129.                   break;
  130.  
  131.             case Key_RTARROW :
  132.             case Key_PRTARROW :
  133.                   if (password_mode)
  134.                         BAD_KEY();
  135.                   if (pos == len)
  136.                         break;
  137.                   if (pos != maxlen)
  138.                   {
  139.                         putch(temp[pos]);
  140.                         pos++;
  141.                   }
  142.                   break;
  143.  
  144.             case Key_HOME :
  145.             case Key_PHOME :
  146.                   if (password_mode)
  147.                         BAD_KEY();
  148.                   while (pos-- > 0)
  149.                         putch('\b');
  150.                   pos = 0;
  151.                   break;
  152.  
  153.             case Key_END :
  154.             case Key_PEND :
  155.                   if (password_mode)
  156.                         BAD_KEY();
  157.                   while (pos < len)
  158.                         putch(temp[pos++]);
  159.                   break;
  160.  
  161.             case Key_INS :
  162.             case Key_PINS :
  163.                   if (password_mode)
  164.                         BAD_KEY();
  165.                   insert = (!(insert));
  166.                   cursor(insert ? 'B' : 'N');
  167.                   break;
  168.  
  169.             case Key_DEL :
  170.             case Key_PDEL :
  171.                   if (password_mode)
  172.                         BAD_KEY();
  173.                   if (pos == len)
  174.                         break;
  175.                   for (i = pos; i < len; i++)
  176.                         temp[i] = temp[i + 1];
  177.                   len--;
  178.                   for (i = pos; i < len; i++)
  179.                         putch(temp[i]);
  180.                   putch('_');
  181.                   for (i = len + 1; i > pos; i--)
  182.                         putch('\b');
  183.                   break;
  184.  
  185.             case Key_BACKSPC :
  186.                   if (pos == 0)
  187.                         break;
  188.                   if (pos != len)
  189.                   {
  190.                         for (i = pos - 1; i < len; i++)
  191.                               temp[i] = temp[i + 1];
  192.                         pos--;
  193.                         len--;
  194.                         putch('\b');
  195.                         for (i = pos; i < len; i++)
  196.                               putch(temp[i]);
  197.                         putch('_');
  198.                         for (i = len; i >= pos; i--)
  199.                               putch('\b');
  200.                   }
  201.                   else
  202.                   {
  203.                         putch('\b');
  204.                         putch('_');
  205.                         putch('\b');
  206.                         pos = --len;
  207.                   }
  208.                   break;
  209.  
  210.             case Key_ENTER :
  211.             case Key_PADENTER :
  212.             case Key_NL :
  213.                   done = 1;
  214.                   break;
  215.  
  216.             case Key_CEND :
  217.             case Key_CPEND :
  218.                   if (password_mode)
  219.                         BAD_KEY();
  220.                   for (i = pos; i < len; ++i)
  221.                         putch('_');
  222.                   for (i = pos; i < len; ++i)
  223.                         putch('\b');
  224.                   len = pos;
  225.                   break;
  226.  
  227.             case Key_CHOME :
  228.             case Key_CPHOME :
  229.                   if (pos == 0)
  230.                         break;
  231.                   if (pos != len)
  232.                   {
  233.                         while (0 != pos)
  234.                         {
  235.                               for (i = pos - 1; i < len; i++)
  236.                                     temp[i] = temp[i + 1];
  237.                               pos--;
  238.                               len--;
  239.                               putch('\b');
  240.                               for (i = pos; i < len; i++)
  241.                                     putch(temp[i]);
  242.                               putch('_');
  243.                               for (i = len; i >= pos; i--)
  244.                                     putch('\b');
  245.                         }
  246.                   }
  247.                   else
  248.                   {
  249.                         while (0 != pos)
  250.                         {
  251.                               putch('\b');
  252.                               putch('_');
  253.                               putch('\b');
  254.                               pos = --len;
  255.                         }
  256.                   }
  257.                   break;
  258.  
  259.             case Key_CRTARROW :
  260.             case Key_CPRTARROW :
  261.                   if (password_mode)
  262.                         BAD_KEY();
  263.                   do
  264.                   {
  265.                         if (pos == len)
  266.                               break;
  267.                         if (pos != maxlen)
  268.                         {
  269.                               putch(temp[pos]);
  270.                               pos++;
  271.                         }
  272.                   } while (isspace(temp[pos]));
  273.                   do
  274.                   {
  275.                         if (pos == len)
  276.                               break;
  277.                         if (pos != maxlen)
  278.                         {
  279.                               putch(temp[pos]);
  280.                               pos++;
  281.                         }
  282.                   } while (!isspace(temp[pos]));
  283.                   break;
  284.  
  285.             case Key_CLTARROW :
  286.             case Key_CPLTARROW :
  287.                   if (password_mode)
  288.                         BAD_KEY();
  289.                   do
  290.                   {
  291.                         if (pos == 0)
  292.                               break;
  293.                         pos--;
  294.                         putch('\b');
  295.                   } while (isspace(temp[pos]));
  296.                   do
  297.                   {
  298.                         if (pos == 0)
  299.                               break;
  300.                         pos--;
  301.                         putch('\b');
  302.                   } while (!isspace(temp[pos]));
  303.                   break;
  304.  
  305.             case Key_TAB :
  306.                   if (password_mode)
  307.                         BAD_KEY();
  308.                   if (pos == maxlen)
  309.                         break;
  310.  
  311.                   skip = TabSize - ((pos + TabSize) % TabSize);
  312.  
  313.                   if (insert)
  314.                   {
  315.                         if ((len + skip) > maxlen)
  316.                               skip = maxlen - len;
  317.  
  318.                         for (i = pos, j = len + skip - 1, k = len - 1;
  319.                               i < len ; ++i, --j, --k)
  320.                         {
  321.                               temp[j] = temp[k];
  322.                         }
  323.                   }
  324.                   else  /* overwrite */
  325.                   {
  326.                         if ((pos + skip) > maxlen)
  327.                               skip = maxlen - pos;
  328.                   }
  329.                   for (i = 0; i < skip; ++i)
  330.                   {
  331.                         temp[pos++] = ' ';
  332.                         putch(' ');
  333.                   }
  334.                   len = insert ? len + skip : max(len, pos);
  335.                   for (i = pos; i < len; ++i)
  336.                         putch(temp[i]);
  337.                   for (i = len; i > pos; --i)
  338.                         putch('\b');
  339.                   break;
  340.  
  341.             default :
  342.                   if (pos == maxlen)
  343.                         break;
  344.  
  345.                   if (c & 0xff00          /* Illegal extended character */
  346.  
  347. #if !CTRL_CHARS_ALLOWED
  348.  
  349.                   || iscntrl(c)
  350. #endif
  351.                   )
  352.                   {
  353.                         BAD_KEY();
  354.                   }
  355.  
  356.                   if ((!(insert)) || pos == len)
  357.                   {
  358.                         temp[pos++] = (char)c;
  359.                         if (pos > len) len++;
  360.                         if (password_mode)
  361.                         {
  362.                               if (2 == password_mode)
  363.                                     putch(pickPWchar());
  364.                               else  putch('*');
  365.                         }
  366.                         else  putch(c);
  367.                   }
  368.                   else
  369.                   {
  370.                         if (len == maxlen)
  371.                               break;
  372.                         for (i = len++; i >= pos; i--)
  373.                               temp[i + 1] = temp[i];
  374.                         temp[pos++] = (char)c;
  375.                         if (password_mode)
  376.                         {
  377.                               if (2 == password_mode)
  378.                                     putch(pickPWchar());
  379.                               else  putch('*');
  380.                         }
  381.                         else  putch(c);
  382.                         for (i = pos; i < len; i++)
  383.                               putch(temp[i]);
  384.                         for (i = len; i > pos; i--)
  385.                               putch('\b');
  386.                   }
  387.             }
  388.       }
  389.       temp[len] = '\0';
  390.       strcpy(s, temp);
  391.       cursor('Z');            /* Restore cursor size  */
  392.       return len;
  393. }
  394.  
  395. static int pickPWchar(void)
  396. {
  397.       static int inited = 0;
  398.  
  399.       if (!inited)
  400.       {
  401.             srand(((unsigned int)time(NULL)) | 1);
  402.             inited = 1;
  403.       }
  404.       
  405.       return PWchars[rand() % (sizeof(PWchars) - 1)];
  406. }
  407.  
  408. #ifdef TEST
  409.  
  410. main()
  411. {
  412.       char mystring[60];
  413.  
  414.       memset(mystring, 0, 60);
  415.       puts("                  "
  416.             "0        1         2         3         4         5         6");
  417.       puts("                  "
  418.             "123456789012345678901234567890123456789012345678901234567890");
  419.       fputs("Enter any string: ", stderr);
  420.       editgets(mystring, 60, "This is a test");
  421.       puts("");
  422.       printf("editgets() returned:\n\"%s\"\n", mystring);
  423.  
  424.       password_mode = 1;
  425.       memset(mystring, 0, 60);
  426.       fputs("Enter any password: ", stderr);
  427.       editgets(mystring, 50, NULL);
  428.       puts("");
  429.       printf("editgets() returned:\n\"%s\"\n", mystring);
  430.  
  431.       password_mode = 2;
  432.       memset(mystring, 0, 60);
  433.       fputs("Enter any password: ", stderr);
  434.       editgets(mystring, 50, NULL);
  435.       puts("");
  436.       printf("editgets() returned:\n\"%s\"\n", mystring);
  437.  
  438.       return 0;
  439. }
  440.  
  441. #endif /* TEST */
  442.