Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /* PDCurses */
  2.  
  3. #include <curspriv.h>
  4.  
  5. /*man-start**************************************************************
  6.  
  7. scanw
  8. -----
  9.  
  10. ### Synopsis
  11.  
  12.     int scanw(const char *fmt, ...);
  13.     int wscanw(WINDOW *win, const char *fmt, ...);
  14.     int mvscanw(int y, int x, const char *fmt, ...);
  15.     int mvwscanw(WINDOW *win, int y, int x, const char *fmt, ...);
  16.     int vwscanw(WINDOW *win, const char *fmt, va_list varglist);
  17.     int vw_scanw(WINDOW *win, const char *fmt, va_list varglist);
  18.  
  19. ### Description
  20.  
  21.    These routines correspond to the standard C library's scanf() family.
  22.    Each gets a string from the window via wgetnstr(), and uses the
  23.    resulting line as input for the scan.
  24.  
  25.    The duplication between vwscanw() and vw_scanw() is for historic
  26.    reasons. In PDCurses, they're the same.
  27.  
  28. ### Return Value
  29.  
  30.    On successful completion, these functions return the number of items
  31.    successfully matched. Otherwise they return ERR.
  32.  
  33. ### Portability
  34.                              X/Open  ncurses  NetBSD
  35.     scanw                       Y       Y       Y
  36.     wscanw                      Y       Y       Y
  37.     mvscanw                     Y       Y       Y
  38.     mvwscanw                    Y       Y       Y
  39.     vwscanw                     Y       Y       Y
  40.     vw_scanw                    Y       Y       Y
  41.  
  42. **man-end****************************************************************/
  43.  
  44. #include <string.h>
  45.  
  46. #ifndef HAVE_VSSCANF
  47. # include <stdlib.h>
  48. # include <ctype.h>
  49. # include <limits.h>
  50.  
  51. static int _pdc_vsscanf(const char *, const char *, va_list);
  52.  
  53. # define vsscanf _pdc_vsscanf
  54. #endif
  55.  
  56. int vwscanw(WINDOW *win, const char *fmt, va_list varglist)
  57. {
  58.     char scanbuf[256];
  59.  
  60.     PDC_LOG(("vwscanw() - called\n"));
  61.  
  62.     if (wgetnstr(win, scanbuf, 255) == ERR)
  63.         return ERR;
  64.  
  65.     return vsscanf(scanbuf, fmt, varglist);
  66. }
  67.  
  68. int scanw(const char *fmt, ...)
  69. {
  70.     va_list args;
  71.     int retval;
  72.  
  73.     PDC_LOG(("scanw() - called\n"));
  74.  
  75.     va_start(args, fmt);
  76.     retval = vwscanw(stdscr, fmt, args);
  77.     va_end(args);
  78.  
  79.     return retval;
  80. }
  81.  
  82. int wscanw(WINDOW *win, const char *fmt, ...)
  83. {
  84.     va_list args;
  85.     int retval;
  86.  
  87.     PDC_LOG(("wscanw() - called\n"));
  88.  
  89.     va_start(args, fmt);
  90.     retval = vwscanw(win, fmt, args);
  91.     va_end(args);
  92.  
  93.     return retval;
  94. }
  95.  
  96. int mvscanw(int y, int x, const char *fmt, ...)
  97. {
  98.     va_list args;
  99.     int retval;
  100.  
  101.     PDC_LOG(("mvscanw() - called\n"));
  102.  
  103.     if (move(y, x) == ERR)
  104.         return ERR;
  105.  
  106.     va_start(args, fmt);
  107.     retval = vwscanw(stdscr, fmt, args);
  108.     va_end(args);
  109.  
  110.     return retval;
  111. }
  112.  
  113. int mvwscanw(WINDOW *win, int y, int x, const char *fmt, ...)
  114. {
  115.     va_list args;
  116.     int retval;
  117.  
  118.     PDC_LOG(("mvscanw() - called\n"));
  119.  
  120.     if (wmove(win, y, x) == ERR)
  121.         return ERR;
  122.  
  123.     va_start(args, fmt);
  124.     retval = vwscanw(win, fmt, args);
  125.     va_end(args);
  126.  
  127.     return retval;
  128. }
  129.  
  130. int vw_scanw(WINDOW *win, const char *fmt, va_list varglist)
  131. {
  132.     PDC_LOG(("vw_scanw() - called\n"));
  133.  
  134.     return vwscanw(win, fmt, varglist);
  135. }
  136.  
  137. #ifndef HAVE_VSSCANF
  138.  
  139. /* _pdc_vsscanf() - Internal routine to parse and format an input
  140.    buffer. It scans a series of input fields; each field is formatted
  141.    according to a supplied format string and the formatted input is
  142.    stored in the variable number of addresses passed. Returns the number
  143.    of input fields or EOF on error.
  144.  
  145.    Don't compile this unless required. Some compilers (at least Borland
  146.    C++ 3.0) have to link with math libraries due to the use of floats.
  147.  
  148.    Based on vsscanf.c and input.c from emx 0.8f library source,
  149.    Copyright (c) 1990-1992 by Eberhard Mattes, who has kindly agreed to
  150.    its inclusion in PDCurses. */
  151.  
  152. #define WHITE(x) ((x) == ' ' || (x) == '\t' || (x) == '\n')
  153.  
  154. #define NEXT(x) \
  155.         do { \
  156.             x = *buf++; \
  157.             if (!x) \
  158.                return (count ? count : EOF); \
  159.             ++chars; \
  160.            } while (0)
  161.  
  162. #define UNGETC() \
  163.         do { \
  164.             --buf; --chars; \
  165.            } while (0)
  166.  
  167. static int _pdc_vsscanf(const char *buf, const char *fmt, va_list arg_ptr)
  168. {
  169.     int count, chars, c, width, radix, d, i;
  170.     int *int_ptr;
  171.     long *long_ptr;
  172.     short *short_ptr;
  173.     char *char_ptr;
  174.     unsigned char f;
  175.     char neg, assign, ok, size;
  176.     long n;
  177.     char map[256], end;
  178.     double dx, dd, *dbl_ptr;
  179.     float *flt_ptr;
  180.     int exp;
  181.     char eneg;
  182.  
  183.     count = 0;
  184.     chars = 0;
  185.     c = 0;
  186.     while ((f = *fmt) != 0)
  187.     {
  188.         if (WHITE(f))
  189.         {
  190.             do
  191.             {
  192.                 ++fmt;
  193.                 f = *fmt;
  194.             }
  195.             while (WHITE(f));
  196.             do
  197.             {
  198.                 c = *buf++;
  199.                 if (!c)
  200.                 {
  201.                     if (!f || count)
  202.                         return count;
  203.                     else
  204.                         return EOF;
  205.                 } else
  206.                     ++chars;
  207.             }
  208.             while (WHITE(c));
  209.             UNGETC();
  210.         } else if (f != '%')
  211.         {
  212.             NEXT(c);
  213.             if (c != f)
  214.                 return count;
  215.             ++fmt;
  216.         } else
  217.         {
  218.             assign = TRUE;
  219.             width = INT_MAX;
  220.             char_ptr = NULL;
  221.             ++fmt;
  222.             if (*fmt == '*')
  223.             {
  224.                 assign = FALSE;
  225.                 ++fmt;
  226.             }
  227.             if (isdigit(*fmt))
  228.             {
  229.                 width = 0;
  230.                 while (isdigit(*fmt))
  231.                     width = width * 10 + (*fmt++ - '0');
  232.                 if (!width)
  233.                     width = INT_MAX;
  234.             }
  235.             size = 0;
  236.             if (*fmt == 'h' || *fmt == 'l')
  237.                 size = *fmt++;
  238.             f = *fmt;
  239.             switch (f)
  240.             {
  241.             case 'c':
  242.                 if (width == INT_MAX)
  243.                     width = 1;
  244.                 if (assign)
  245.                     char_ptr = va_arg(arg_ptr, char *);
  246.                 while (width > 0)
  247.                 {
  248.                     --width;
  249.                     NEXT(c);
  250.                     if (assign)
  251.                     {
  252.                         *char_ptr++ = (char) c;
  253.                         ++count;
  254.                     }
  255.                 }
  256.                 break;
  257.             case '[':
  258.                 memset(map, 0, 256);
  259.                 end = 0;
  260.                 ++fmt;
  261.                 if (*fmt == '^')
  262.                 {
  263.                     ++fmt;
  264.                     end = 1;
  265.                 }
  266.                 i = 0;
  267.                 for (;;)
  268.                 {
  269.                     f = (unsigned char) *fmt;
  270.                     switch (f)
  271.                     {
  272.                     case 0:
  273.                         /* avoid skipping past 0 */
  274.                         --fmt;
  275.                         NEXT(c);
  276.                         goto string;
  277.                     case ']':
  278.                         if (i > 0)
  279.                         {
  280.                             NEXT(c);
  281.                             goto string;
  282.                         }
  283.                         /* no break */
  284.                     default:
  285.                         if (fmt[1] == '-' && fmt[2]
  286.                             && f < (unsigned char)fmt[2])
  287.                         {
  288.                             memset(map + f, 1, (unsigned char)fmt[2] - f);
  289.                             fmt += 2;
  290.                         }
  291.                         else
  292.                             map[f] = 1;
  293.                         break;
  294.                     }
  295.                     ++fmt;
  296.                     ++i;
  297.                 }
  298.             case 's':
  299.                 memset(map, 0, 256);
  300.                 map[' '] = 1;
  301.                 map['\n'] = 1;
  302.                 map['\r'] = 1;
  303.                 map['\t'] = 1;
  304.                 end = 1;
  305.                 do
  306.                 {
  307.                     NEXT(c);
  308.                 }
  309.                 while (WHITE(c));
  310.             string:
  311.                 if (assign)
  312.                     char_ptr = va_arg(arg_ptr, char *);
  313.                 while (width > 0 && map[(unsigned char) c] != end)
  314.                 {
  315.                     --width;
  316.                     if (assign)
  317.                         *char_ptr++ = (char) c;
  318.                     c = *buf++;
  319.                     if (!c)
  320.                         break;
  321.                     else
  322.                         ++chars;
  323.                 }
  324.                 if (assign)
  325.                 {
  326.                     *char_ptr = 0;
  327.                     ++count;
  328.                 }
  329.                 if (!c)
  330.                     return count;
  331.                 else
  332.                     UNGETC();
  333.                 break;
  334.             case 'f':
  335.             case 'e':
  336.             case 'E':
  337.             case 'g':
  338.             case 'G':
  339.                 neg = ok = FALSE;
  340.                 dx = 0.0;
  341.                 do
  342.                 {
  343.                     NEXT(c);
  344.                 }
  345.                 while (WHITE(c));
  346.                 if (c == '+')
  347.                 {
  348.                     NEXT(c);
  349.                     --width;
  350.                 } else if (c == '-')
  351.                 {
  352.                     neg = TRUE;
  353.                     NEXT(c);
  354.                     --width;
  355.                 }
  356.                 while (width > 0 && isdigit(c))
  357.                 {
  358.                     --width;
  359.                     dx = dx * 10.0 + (double) (c - '0');
  360.                     ok = TRUE;
  361.                     c = *buf++;
  362.                     if (!c)
  363.                         break;
  364.                     else
  365.                         ++chars;
  366.                 }
  367.                 if (width > 0 && c == '.')
  368.                 {
  369.                     --width;
  370.                     dd = 10.0;
  371.                     NEXT(c);
  372.                     while (width > 0 && isdigit(c))
  373.                     {
  374.                         --width;
  375.                         dx += (double) (c - '0') / dd;
  376.                         dd *= 10.0;
  377.                         ok = TRUE;
  378.                         c = *buf++;
  379.                         if (!c)
  380.                             break;
  381.                         else
  382.                             ++chars;
  383.                     }
  384.                 }
  385.                 if (!ok)
  386.                     return count;
  387.                 if (width > 0 && (c == 'e' || c == 'E'))
  388.                 {
  389.                     eneg = FALSE;
  390.                     exp = 0;
  391.                     NEXT(c);
  392.                     --width;
  393.                     if (width > 0 && c == '+')
  394.                     {
  395.                         NEXT(c);
  396.                         --width;
  397.                     } else if (width > 0 && c == '-')
  398.                     {
  399.                         eneg = TRUE;
  400.                         NEXT(c);
  401.                         --width;
  402.                     }
  403.                     if (!(width > 0 && isdigit(c)))
  404.                     {
  405.                         UNGETC();
  406.                         return count;
  407.                     }
  408.                     while (width > 0 && isdigit(c))
  409.                     {
  410.                         --width;
  411.                         exp = exp * 10 + (c - '0');
  412.                         c = *buf++;
  413.                         if (!c)
  414.                             break;
  415.                         else
  416.                             ++chars;
  417.                     }
  418.                     if (eneg)
  419.                         exp = -exp;
  420.                     while (exp > 0)
  421.                     {
  422.                         dx *= 10.0;
  423.                         --exp;
  424.                     }
  425.                     while (exp < 0)
  426.                     {
  427.                         dx /= 10.0;
  428.                         ++exp;
  429.                     }
  430.                 }
  431.                 if (assign)
  432.                 {
  433.                     if (neg)
  434.                         dx = -dx;
  435.                     if (size == 'l')
  436.                     {
  437.                         dbl_ptr = va_arg(arg_ptr, double *);
  438.                         *dbl_ptr = dx;
  439.                     }
  440.                     else
  441.                     {
  442.                         flt_ptr = va_arg(arg_ptr, float *);
  443.                         *flt_ptr = (float)dx;
  444.                     }
  445.                     ++count;
  446.                 }
  447.                 if (!c)
  448.                     return count;
  449.                 else
  450.                     UNGETC();
  451.                 break;
  452.             case 'i':
  453.                 neg = FALSE;
  454.                 radix = 10;
  455.                 do
  456.                 {
  457.                     NEXT(c);
  458.                 }
  459.                 while (WHITE(c));
  460.                 if (!(width > 0 && c == '0'))
  461.                     goto scan_complete_number;
  462.                 NEXT(c);
  463.                 --width;
  464.                 if (width > 0 && (c == 'x' || c == 'X'))
  465.                 {
  466.                     NEXT(c);
  467.                     radix = 16;
  468.                     --width;
  469.                 }
  470.                 else if (width > 0 && (c >= '0' && c <= '7'))
  471.                     radix = 8;
  472.                 goto scan_unsigned_number;
  473.             case 'd':
  474.             case 'u':
  475.             case 'o':
  476.             case 'x':
  477.             case 'X':
  478.                 do
  479.                 {
  480.                     NEXT(c);
  481.                 }
  482.                 while (WHITE(c));
  483.                 switch (f)
  484.                 {
  485.                 case 'o':
  486.                     radix = 8;
  487.                     break;
  488.                 case 'x':
  489.                 case 'X':
  490.                     radix = 16;
  491.                     break;
  492.                 default:
  493.                     radix = 10;
  494.                     break;
  495.                 }
  496.             scan_complete_number:
  497.                 neg = FALSE;
  498.                 if (width > 0 && c == '+')
  499.                 {
  500.                     NEXT(c);
  501.                     --width;
  502.                 }
  503.                 else if (width > 0 && c == '-' && radix == 10)
  504.                 {
  505.                     neg = TRUE;
  506.                     NEXT(c);
  507.                     --width;
  508.                 }
  509.             scan_unsigned_number:
  510.                 n = 0;
  511.                 ok = FALSE;
  512.                 while (width > 0)
  513.                 {
  514.                     --width;
  515.                     if (isdigit(c))
  516.                         d = c - '0';
  517.                     else if (isupper(c))
  518.                         d = c - 'A' + 10;
  519.                     else if (islower(c))
  520.                         d = c - 'a' + 10;
  521.                     else
  522.                         break;
  523.                     if (d < 0 || d >= radix)
  524.                         break;
  525.                     ok = TRUE;
  526.                     n = n * radix + d;
  527.                     c = *buf++;
  528.                     if (!c)
  529.                         break;
  530.                     else
  531.                         ++chars;
  532.                 }
  533.                 if (!ok)
  534.                     return count;
  535.                 if (assign)
  536.                 {
  537.                     if (neg)
  538.                         n = -n;
  539.                     switch (size)
  540.                     {
  541.                     case 'h':
  542.                         short_ptr = va_arg(arg_ptr, short *);
  543.                         *short_ptr = (short) n;
  544.                         break;
  545.                     case 'l':
  546.                         long_ptr = va_arg(arg_ptr, long *);
  547.                         *long_ptr = (long) n;
  548.                         break;
  549.                     default:
  550.                         int_ptr = va_arg(arg_ptr, int *);
  551.                         *int_ptr = (int) n;
  552.                     }
  553.                     ++count;
  554.                 }
  555.                 if (!c)
  556.                     return count;
  557.                 else
  558.                     UNGETC();
  559.                 break;
  560.             case 'n':
  561.                 if (assign)
  562.                 {
  563.                     int_ptr = va_arg(arg_ptr, int *);
  564.                     *int_ptr = chars;
  565.                     ++count;
  566.                 }
  567.                 break;
  568.             default:
  569.                 if (!f) /* % at end of string */
  570.                     return count;
  571.                 NEXT(c);
  572.                 if (c != f)
  573.                     return count;
  574.                 break;
  575.             }
  576.             ++fmt;
  577.         }
  578.     }
  579.     return count;
  580. }
  581. #endif /* HAVE_VSSCANF */
  582.