home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / ONLINE / ELM23-2 / ELM23-2.ZIP / src / in_utils.c < prev    next >
C/C++ Source or Header  |  1992-08-04  |  14KB  |  507 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: in_utils.c,v 4.1 90/04/28 22:43:13 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 4.1 $   $State: Exp $
  6.  *
  7.  *             Copyright (c) 1986, 1987 Dave Taylor
  8.  *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein, Elm Coordinator
  13.  *    elm@DSI.COM            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log:    in_utils.c,v $
  17.  * Revision 4.1  90/04/28  22:43:13  syd
  18.  * checkin of Elm 2.3 as of Release PL0
  19.  *
  20.  *
  21.  ******************************************************************************/
  22.  
  23. /** Mindless I/O routines for ELM
  24.  
  25. **/
  26.  
  27. #include "headers.h"
  28. #include <errno.h>
  29. #include <ctype.h>
  30.  
  31. #ifdef BSD
  32. #  undef tolower
  33. #endif
  34.  
  35. #ifndef OS2
  36. extern int errno;        /* system error number */
  37. unsigned alarm();
  38. #endif
  39.  
  40. #define isstopchar(c)        (c == ' ' || c == '\t' || c == '/')
  41. #define isslash(c)        (c == '/')
  42. #define erase_a_char()        { Writechar(BACKSPACE); Writechar(' '); \
  43.                       Writechar(BACKSPACE); fflush(stdout); }
  44.  
  45. int
  46. want_to(question, dflt)
  47. char *question, dflt;
  48. {
  49.     /** Ask 'question' on LINES-2 left enough to just leave room for an
  50.         answer, returning the answer in lower case.
  51.         Echo answer as full "Yes" or "No".  'dflt' is the
  52.         default answer if <return> is pressed. (Note: 'dflt' is also what
  53.         will be returned if <return> is pressed!)
  54.     **/
  55.     register int ch, cols;
  56.  
  57.     cols = COLUMNS - (strlen(question) + 5 );    /* 5 for "Yes." + 1 */
  58.  
  59.     MoveCursor(LINES-3, cols);
  60.     CleartoEOLN();
  61.     PutLine3(LINES-3, cols,"%s%c%c", question, dflt, BACKSPACE);
  62.     fflush(stdout);
  63.     fflush(stdin);
  64.  
  65.     ch = ReadCh();
  66.     ch = tolower(ch);
  67.  
  68.     while (!( ch == 'y' || ch == 'n' || ch == '\n' || ch == '\r')) {
  69.       ch = ReadCh();
  70.       ch = tolower(ch);
  71.     }
  72.     if(ch == '\n' || ch == '\r')
  73.       ch = dflt;
  74.  
  75.     if(ch == 'y')
  76.       Write_to_screen("Yes.", 0);
  77.     else
  78.       Write_to_screen("No.", 0);
  79.  
  80.     return(ch);
  81. }
  82.  
  83. int
  84. read_number(ch)
  85. char ch;
  86. {
  87.     /** Read a number, where 'ch' is the leading digit! **/
  88.  
  89.     char buff[NLEN];
  90.     int  num;
  91.  
  92.     buff[0] = ch;
  93.     buff[1] = '\0';
  94.  
  95.     PutLine0(LINES-3, COLUMNS-40,"Set current message to :");
  96.     if (optionally_enter(buff, LINES-3, COLUMNS-15, TRUE, FALSE) == -1)
  97.       return(current);
  98.  
  99.     sscanf(buff,"%d", &num);
  100.     return(num);
  101. }
  102.  
  103. int
  104. optionally_enter(string, x, y, append_current, passwd)
  105. char *string;
  106. int  x,y, append_current, passwd;
  107. {
  108.     /** This will display the string on the screen and allow the user to
  109.         either accept it (by pressing RETURN) or alter it according to
  110.         what the user types.   The various flags are:
  111.              string    is the buffer to use (with optional initial value)
  112.           x,y       is the location we're at on the screen (-1,-1 means
  113.                that we can't use this info and need to find out
  114.                the current location)
  115.          append_current  means that we have an initial string and that
  116.                the cursor should be placed at the END of the line,
  117.                not the beginning (the default).
  118.          passwd       accept non-printing characters and do not echo
  119.                entered characters.
  120.  
  121.         If we hit an interrupt or EOF we'll return non-zero.
  122.     **/
  123.  
  124.     int ch;
  125.     register int ch_count = 0, iindex = 0, escaped = OFF;
  126.  
  127.     clearerr(stdin);
  128.  
  129.     if(!passwd) {
  130.       if(!(x >=0 && y >= 0))
  131.         GetXYLocation(&x, &y);
  132.       PutLine1(x, y, "%s", string);
  133.     }
  134.  
  135.     CleartoEOLN();
  136.  
  137.     if (! append_current) {
  138.       MoveCursor(x,y);
  139.     }
  140.     else
  141.       iindex = strlen(string);
  142.  
  143.     if (cursor_control)
  144.       transmit_functions(OFF);
  145.  
  146.     /** now we have the screen as we want it and the cursor in the
  147.         right place, we can loop around on the input and return the
  148.         string as soon as the user presses <RETURN>
  149.     **/
  150.  
  151.     do {
  152.       ch = getchar();
  153.  
  154.       if (ch == ctrl('D') || ch == EOF) {        /* we've hit EOF */
  155.         if (cursor_control)
  156.           transmit_functions(ON);
  157.         return(1);
  158.       }
  159.  
  160.       if (ch_count++ == 0) {
  161.         if (ch == '\n' || ch == '\r') {
  162.           if (cursor_control)
  163.             transmit_functions(ON);
  164.           return(0);
  165.         }
  166.         else if (! append_current) {
  167.           CleartoEOLN();
  168.           iindex = (append_current? strlen(string) : 0);
  169.         }
  170.       }
  171.  
  172.       /* the following is converted from a case statement to
  173.          allow the variable characters (backspace, kill_line
  174.          and break) to be processed.  Case statements in
  175.          C require constants as labels, so it failed ...
  176.       */
  177.  
  178.       if (ch == backspace &&
  179.         (!escaped || (!isprint(ch) && !passwd))) {
  180.         /* This is tricky. Here we are dealing with all situations
  181.          * under which a backspace (really whatever erase char is
  182.          * set to, not necessarily \b) erases the previous character.
  183.          * It will erase unless escaped, because if it's escaped
  184.          * it is taken literally. There is one exception to that --
  185.          * if backspace would be rejected (we don't accept non-printing
  186.          * characters in non-passwd mode), we accept it here as an
  187.          * erasing character, for it if got rejected there would
  188.          * be no way of erasing a preceding backslash. */
  189.         escaped = OFF;
  190.         if (iindex > 0) {
  191.           if(!passwd)
  192.         Writechar(BACKSPACE);
  193.             iindex--;
  194.         }
  195.         if(!passwd) {
  196.           Writechar(' ');
  197.           Writechar(BACKSPACE);
  198.           fflush(stdout);
  199.         }
  200.       }
  201.       else if (ch == EOF || ch == '\n' || ch == '\r') {
  202.         escaped = OFF;
  203.         string[iindex] = '\0';
  204.         if (cursor_control)
  205.           transmit_functions(ON);
  206.         return(0);
  207.       }
  208.       else if (!passwd && ch == ctrl('W')) {    /* back up a word! */
  209.         escaped = OFF;
  210.         if (iindex == 0)
  211.           continue;        /* no point staying here.. */
  212.         iindex--;
  213.         if (isslash(string[iindex])) {
  214.           erase_a_char();
  215.         }
  216.         else {
  217.           while (iindex >= 0 && isspace(string[iindex])) {
  218.             iindex--;
  219.             erase_a_char();
  220.           }
  221.  
  222.           while (iindex >= 0 && ! isstopchar(string[iindex])) {
  223.             iindex--;
  224.             erase_a_char();
  225.           }
  226.           iindex++;    /* and make sure we point at the first AVAILABLE slot */
  227.         }
  228.       }
  229.       else if (!passwd && ch == ctrl('R')) {
  230.         escaped = OFF;
  231.         string[iindex] = '\0';
  232.         PutLine1(x,y, "%s", string);
  233.         CleartoEOLN();
  234.       }
  235.       else if (!escaped && ch == kill_line) {
  236.         /* needed to test if escaped since kill_line character could
  237.          * be a desired valid printing character */
  238.         escaped = OFF;
  239.         if(!passwd) {
  240.           MoveCursor(x,y);
  241.           CleartoEOLN();
  242.         }
  243.         iindex = 0;
  244.       }
  245.       else if (ch == '\0') {
  246.         escaped = OFF;
  247.         if (cursor_control)
  248.           transmit_functions(ON);
  249.         fflush(stdin);     /* remove extraneous chars, if any */
  250.         string[0] = '\0'; /* clean up string, and... */
  251.         return(-1);
  252.       }
  253.       else if (!passwd && !isprint(ch)) {
  254.         /* non-printing character - warn with bell*/
  255.         /* don't turn off escaping backslash since current character
  256.          * doesn't "use it up".
  257.          */
  258.         Writechar('\007');
  259.       }
  260.       else {  /* default case */
  261.           if(escaped && (ch == backspace || ch == kill_line)) {
  262.         /* if last character was a backslash,
  263.          * and if this character is escapable
  264.          * simply write this character over it even if
  265.          * this character is a backslash.
  266.          */
  267.         if(!passwd)
  268.           Writechar(BACKSPACE);
  269.         iindex--;
  270.         string[iindex++] = ch;
  271.         if(!passwd)
  272.           Writechar(ch);
  273.             escaped = OFF;
  274.           } else {
  275.         string[iindex++] = ch;
  276.         if(!passwd)
  277.           Writechar(ch);
  278.         escaped = ( ch == '\\' ? ON : OFF);
  279.           }
  280.       }
  281.     } while (iindex < SLEN);
  282.  
  283.     string[iindex] = '\0';
  284.  
  285.     if (cursor_control)
  286.       transmit_functions(ON);
  287.  
  288.     return(0);
  289. }
  290.  
  291. int
  292. pattern_enter(string, alt_string, x, y, alternate_prompt)
  293. char *string, *alt_string, *alternate_prompt;
  294. int  x,y;
  295. {
  296.     /** This function is functionally similar to the routine
  297.         optionally-enter, but if the first character pressed
  298.         is a '/' character, then the alternate prompt and string
  299.         are used rather than the normal one.  This routine
  300.         returns 1 if alternate was used, 0 if not
  301.     **/
  302.  
  303.     int ch;
  304.     register iindex = 0, escaped = OFF;
  305.  
  306.     PutLine1(x, y, "%s", string);
  307.     CleartoEOLN();
  308.     MoveCursor(x,y);
  309.  
  310.     if (cursor_control)
  311.       transmit_functions(OFF);
  312.  
  313.     ch = getchar();
  314.  
  315.     if (ch == '\n' || ch == '\r') {
  316.       if (cursor_control)
  317.         transmit_functions(ON);
  318.       return(0);    /* we're done.  No change needed */
  319.     }
  320.  
  321.     if (ch == '/') {
  322.       PutLine1(x, 0, "%s", alternate_prompt);
  323.       CleartoEOLN();
  324.       (void) optionally_enter(alt_string, x, strlen(alternate_prompt)+1,
  325.          FALSE, FALSE);
  326.       return(1);
  327.     }
  328.  
  329.     CleartoEOLN();
  330.  
  331.     iindex = 0;
  332.  
  333.     if (ch == kill_line) {
  334.       MoveCursor(x,y);
  335.           CleartoEOLN();
  336.       iindex = 0;
  337.     }
  338.     else if (ch != backspace) {
  339.       if(ch == '\\') escaped = ON;
  340.       Writechar(ch);
  341.       string[iindex++] = ch;
  342.     }
  343.     else if (iindex > 0) {
  344.       iindex--;
  345.       erase_a_char();
  346.     }
  347.     else {
  348.       Writechar(' ');
  349.       Writechar(BACKSPACE);
  350.     }
  351.  
  352.     do {
  353.       fflush(stdout);
  354.       ch = getchar();
  355.  
  356.       /* the following is converted from a case statement to
  357.          allow the variable characters (backspace, kill_line
  358.          and break) to be processed.  Case statements in
  359.          C require constants as labels, so it failed ...
  360.       */
  361.  
  362.         if (ch == backspace &&
  363.           (!escaped || !isprint(ch)) ) {
  364.           /* This is tricky. Here we are dealing with all situations
  365.            * under which a backspace (really whatever erase char is
  366.            * set to, not necessarily \b) erases the previous character.
  367.            * It will erase unless escaped, because if it's escaped
  368.            * it is taken literally. There is one exception to that --
  369.            * if backspace would be rejected (we don't accept non-printing
  370.            * characters in non-passwd mode), we accept it here as an
  371.            * erasing character, for it if got rejected there would
  372.            * be no way of erasing a preceding backslash. */
  373.           escaped = OFF;
  374.               if (iindex > 0) {
  375.         iindex--;
  376.         erase_a_char();
  377.           }
  378.           else {
  379.         Writechar(' ');
  380.         Writechar(BACKSPACE);
  381.           }
  382.         }
  383.         else if (ch == '\n' || ch == '\r') {
  384.           escaped = OFF;
  385.           string[iindex] = '\0';
  386.           if (cursor_control)
  387.             transmit_functions(ON);
  388.           return(0);
  389.         }
  390.         else if (ch == ctrl('W')) {
  391.           escaped = OFF;
  392.           if (iindex == 0)
  393.             continue;        /* no point staying here.. */
  394.           iindex--;
  395.           if (isslash(string[iindex])) {
  396.             erase_a_char();
  397.           }
  398.           else {
  399.             while (iindex >= 0 && isspace(string[iindex])) {
  400.               iindex--;
  401.               erase_a_char();
  402.             }
  403.  
  404.             while (iindex >= 0 && ! isstopchar(string[iindex])) {
  405.               iindex--;
  406.               erase_a_char();
  407.             }
  408.             iindex++;/* and make sure we point at the first AVAILABLE slot */
  409.           }
  410.         }
  411.         else if (ch == ctrl('R')) {
  412.           escaped = OFF;
  413.           string[iindex] = '\0';
  414.           PutLine1(x,y, "%s", string);
  415.           CleartoEOLN();
  416.         }
  417.         else if (!escaped && ch == kill_line) {
  418.           /* needed to test if escaped since kill_line character could
  419.            * be a desired valid printing character */
  420.           escaped = OFF;
  421.           MoveCursor(x,y);
  422.               CleartoEOLN();
  423.           iindex = 0;
  424.         }
  425.         else if (ch == '\0') {
  426.           escaped = OFF;
  427.           if (cursor_control)
  428.             transmit_functions(ON);
  429.           fflush(stdin);     /* remove extraneous chars, if any */
  430.           string[0] = '\0'; /* clean up string, and... */
  431.           return(-1);
  432.         }
  433.         else if (!isprint(ch)) {
  434.           /* non-printing character - warn with bell*/
  435.           /* don't turn off escaping backslash since current character
  436.            * doesn't "use it up".
  437.            */
  438.           Writechar('\007');
  439.         }
  440.         else {  /* default case */
  441.         if(escaped && (ch == backspace || ch == kill_line)) {
  442.           /* if last character was a backslash,
  443.            * and if this character is escapable
  444.            * simply write this character over it even if
  445.            * this character is a backslash.
  446.            */
  447.           Writechar(BACKSPACE);
  448.           iindex--;
  449.           string[iindex++] = ch;
  450.           Writechar(ch);
  451.           escaped = OFF;
  452.         } else {
  453.           string[iindex++] = ch;
  454.           Writechar(ch);
  455.           escaped = ( ch == '\\' ? ON : OFF);
  456.         }
  457.         }
  458.     } while (iindex < SLEN);
  459.  
  460.     string[iindex] = '\0';
  461.  
  462.     if (cursor_control)
  463.       transmit_functions(ON);
  464.     return(0);
  465. }
  466.  
  467. int
  468. GetPrompt()
  469. {
  470.     /** This routine does a read/timeout for a single character.
  471.         The way that this is determined is that the routine to
  472.         read a character is called, then the "errno" is checked
  473.         against EINTR (interrupted call).  If they match, this
  474.         returns NO_OP_COMMAND otherwise it returns the normal
  475.         command.  On BSD systems, the EINTR will never be returned
  476.         so we instead longjmp from the signal handler.
  477.     **/
  478.  
  479.     int ch;
  480.  
  481.     if (timeout > 0) {
  482.       alarm((unsigned) timeout);
  483. #if defined(BSD) || defined(OS2)
  484.       if (setjmp(GetPromptBuf)) {
  485.         InGetPrompt = 0;
  486.         ch = NO_OP_COMMAND;
  487.         alarm((unsigned) 0);
  488.       }
  489.       else {
  490.         InGetPrompt = 1;
  491.         ch = ReadCh();
  492.         InGetPrompt = 0;
  493.         alarm((unsigned) 0);
  494.       }
  495. #else
  496.         errno = 0;    /* we actually have to do this.  *sigh*  */
  497.         ch = ReadCh();
  498.         if (errno == EINTR) ch = NO_OP_COMMAND;
  499.         alarm((unsigned) 0);
  500. #endif
  501.     }
  502.     else
  503.       ch = ReadCh();
  504.  
  505.     return(ch);
  506. }
  507.