123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581 |
- /* PDCurses */
- #include <curspriv.h>
- /*man-start**************************************************************
- scanw
- -----
- ### Synopsis
- int scanw(const char *fmt, ...);
- int wscanw(WINDOW *win, const char *fmt, ...);
- int mvscanw(int y, int x, const char *fmt, ...);
- int mvwscanw(WINDOW *win, int y, int x, const char *fmt, ...);
- int vwscanw(WINDOW *win, const char *fmt, va_list varglist);
- int vw_scanw(WINDOW *win, const char *fmt, va_list varglist);
- ### Description
- These routines correspond to the standard C library's scanf() family.
- Each gets a string from the window via wgetnstr(), and uses the
- resulting line as input for the scan.
- The duplication between vwscanw() and vw_scanw() is for historic
- reasons. In PDCurses, they're the same.
- ### Return Value
- On successful completion, these functions return the number of items
- successfully matched. Otherwise they return ERR.
- ### Portability
- X/Open ncurses NetBSD
- scanw Y Y Y
- wscanw Y Y Y
- mvscanw Y Y Y
- mvwscanw Y Y Y
- vwscanw Y Y Y
- vw_scanw Y Y Y
- **man-end****************************************************************/
- #include <string.h>
- #ifndef HAVE_VSSCANF
- # include <stdlib.h>
- # include <ctype.h>
- # include <limits.h>
- static int _pdc_vsscanf(const char *, const char *, va_list);
- # define vsscanf _pdc_vsscanf
- #endif
- int vwscanw(WINDOW *win, const char *fmt, va_list varglist)
- {
- char scanbuf[256];
- PDC_LOG(("vwscanw() - called\n"));
- if (wgetnstr(win, scanbuf, 255) == ERR)
- return ERR;
- return vsscanf(scanbuf, fmt, varglist);
- }
- int scanw(const char *fmt, ...)
- {
- va_list args;
- int retval;
- PDC_LOG(("scanw() - called\n"));
- va_start(args, fmt);
- retval = vwscanw(stdscr, fmt, args);
- va_end(args);
- return retval;
- }
- int wscanw(WINDOW *win, const char *fmt, ...)
- {
- va_list args;
- int retval;
- PDC_LOG(("wscanw() - called\n"));
- va_start(args, fmt);
- retval = vwscanw(win, fmt, args);
- va_end(args);
- return retval;
- }
- int mvscanw(int y, int x, const char *fmt, ...)
- {
- va_list args;
- int retval;
- PDC_LOG(("mvscanw() - called\n"));
- if (move(y, x) == ERR)
- return ERR;
- va_start(args, fmt);
- retval = vwscanw(stdscr, fmt, args);
- va_end(args);
- return retval;
- }
- int mvwscanw(WINDOW *win, int y, int x, const char *fmt, ...)
- {
- va_list args;
- int retval;
- PDC_LOG(("mvscanw() - called\n"));
- if (wmove(win, y, x) == ERR)
- return ERR;
- va_start(args, fmt);
- retval = vwscanw(win, fmt, args);
- va_end(args);
- return retval;
- }
- int vw_scanw(WINDOW *win, const char *fmt, va_list varglist)
- {
- PDC_LOG(("vw_scanw() - called\n"));
- return vwscanw(win, fmt, varglist);
- }
- #ifndef HAVE_VSSCANF
- /* _pdc_vsscanf() - Internal routine to parse and format an input
- buffer. It scans a series of input fields; each field is formatted
- according to a supplied format string and the formatted input is
- stored in the variable number of addresses passed. Returns the number
- of input fields or EOF on error.
- Don't compile this unless required. Some compilers (at least Borland
- C++ 3.0) have to link with math libraries due to the use of floats.
- Based on vsscanf.c and input.c from emx 0.8f library source,
- Copyright (c) 1990-1992 by Eberhard Mattes, who has kindly agreed to
- its inclusion in PDCurses. */
- #define WHITE(x) ((x) == ' ' || (x) == '\t' || (x) == '\n')
- #define NEXT(x) \
- do { \
- x = *buf++; \
- if (!x) \
- return (count ? count : EOF); \
- ++chars; \
- } while (0)
- #define UNGETC() \
- do { \
- --buf; --chars; \
- } while (0)
- static int _pdc_vsscanf(const char *buf, const char *fmt, va_list arg_ptr)
- {
- int count, chars, c, width, radix, d, i;
- int *int_ptr;
- long *long_ptr;
- short *short_ptr;
- char *char_ptr;
- unsigned char f;
- char neg, assign, ok, size;
- long n;
- char map[256], end;
- double dx, dd, *dbl_ptr;
- float *flt_ptr;
- int exp;
- char eneg;
- count = 0;
- chars = 0;
- c = 0;
- while ((f = *fmt) != 0)
- {
- if (WHITE(f))
- {
- do
- {
- ++fmt;
- f = *fmt;
- }
- while (WHITE(f));
- do
- {
- c = *buf++;
- if (!c)
- {
- if (!f || count)
- return count;
- else
- return EOF;
- } else
- ++chars;
- }
- while (WHITE(c));
- UNGETC();
- } else if (f != '%')
- {
- NEXT(c);
- if (c != f)
- return count;
- ++fmt;
- } else
- {
- assign = TRUE;
- width = INT_MAX;
- char_ptr = NULL;
- ++fmt;
- if (*fmt == '*')
- {
- assign = FALSE;
- ++fmt;
- }
- if (isdigit(*fmt))
- {
- width = 0;
- while (isdigit(*fmt))
- width = width * 10 + (*fmt++ - '0');
- if (!width)
- width = INT_MAX;
- }
- size = 0;
- if (*fmt == 'h' || *fmt == 'l')
- size = *fmt++;
- f = *fmt;
- switch (f)
- {
- case 'c':
- if (width == INT_MAX)
- width = 1;
- if (assign)
- char_ptr = va_arg(arg_ptr, char *);
- while (width > 0)
- {
- --width;
- NEXT(c);
- if (assign)
- {
- *char_ptr++ = (char) c;
- ++count;
- }
- }
- break;
- case '[':
- memset(map, 0, 256);
- end = 0;
- ++fmt;
- if (*fmt == '^')
- {
- ++fmt;
- end = 1;
- }
- i = 0;
- for (;;)
- {
- f = (unsigned char) *fmt;
- switch (f)
- {
- case 0:
- /* avoid skipping past 0 */
- --fmt;
- NEXT(c);
- goto string;
- case ']':
- if (i > 0)
- {
- NEXT(c);
- goto string;
- }
- /* no break */
- default:
- if (fmt[1] == '-' && fmt[2]
- && f < (unsigned char)fmt[2])
- {
- memset(map + f, 1, (unsigned char)fmt[2] - f);
- fmt += 2;
- }
- else
- map[f] = 1;
- break;
- }
- ++fmt;
- ++i;
- }
- case 's':
- memset(map, 0, 256);
- map[' '] = 1;
- map['\n'] = 1;
- map['\r'] = 1;
- map['\t'] = 1;
- end = 1;
- do
- {
- NEXT(c);
- }
- while (WHITE(c));
- string:
- if (assign)
- char_ptr = va_arg(arg_ptr, char *);
- while (width > 0 && map[(unsigned char) c] != end)
- {
- --width;
- if (assign)
- *char_ptr++ = (char) c;
- c = *buf++;
- if (!c)
- break;
- else
- ++chars;
- }
- if (assign)
- {
- *char_ptr = 0;
- ++count;
- }
- if (!c)
- return count;
- else
- UNGETC();
- break;
- case 'f':
- case 'e':
- case 'E':
- case 'g':
- case 'G':
- neg = ok = FALSE;
- dx = 0.0;
- do
- {
- NEXT(c);
- }
- while (WHITE(c));
- if (c == '+')
- {
- NEXT(c);
- --width;
- } else if (c == '-')
- {
- neg = TRUE;
- NEXT(c);
- --width;
- }
- while (width > 0 && isdigit(c))
- {
- --width;
- dx = dx * 10.0 + (double) (c - '0');
- ok = TRUE;
- c = *buf++;
- if (!c)
- break;
- else
- ++chars;
- }
- if (width > 0 && c == '.')
- {
- --width;
- dd = 10.0;
- NEXT(c);
- while (width > 0 && isdigit(c))
- {
- --width;
- dx += (double) (c - '0') / dd;
- dd *= 10.0;
- ok = TRUE;
- c = *buf++;
- if (!c)
- break;
- else
- ++chars;
- }
- }
- if (!ok)
- return count;
- if (width > 0 && (c == 'e' || c == 'E'))
- {
- eneg = FALSE;
- exp = 0;
- NEXT(c);
- --width;
- if (width > 0 && c == '+')
- {
- NEXT(c);
- --width;
- } else if (width > 0 && c == '-')
- {
- eneg = TRUE;
- NEXT(c);
- --width;
- }
- if (!(width > 0 && isdigit(c)))
- {
- UNGETC();
- return count;
- }
- while (width > 0 && isdigit(c))
- {
- --width;
- exp = exp * 10 + (c - '0');
- c = *buf++;
- if (!c)
- break;
- else
- ++chars;
- }
- if (eneg)
- exp = -exp;
- while (exp > 0)
- {
- dx *= 10.0;
- --exp;
- }
- while (exp < 0)
- {
- dx /= 10.0;
- ++exp;
- }
- }
- if (assign)
- {
- if (neg)
- dx = -dx;
- if (size == 'l')
- {
- dbl_ptr = va_arg(arg_ptr, double *);
- *dbl_ptr = dx;
- }
- else
- {
- flt_ptr = va_arg(arg_ptr, float *);
- *flt_ptr = (float)dx;
- }
- ++count;
- }
- if (!c)
- return count;
- else
- UNGETC();
- break;
- case 'i':
- neg = FALSE;
- radix = 10;
- do
- {
- NEXT(c);
- }
- while (WHITE(c));
- if (!(width > 0 && c == '0'))
- goto scan_complete_number;
- NEXT(c);
- --width;
- if (width > 0 && (c == 'x' || c == 'X'))
- {
- NEXT(c);
- radix = 16;
- --width;
- }
- else if (width > 0 && (c >= '0' && c <= '7'))
- radix = 8;
- goto scan_unsigned_number;
- case 'd':
- case 'u':
- case 'o':
- case 'x':
- case 'X':
- do
- {
- NEXT(c);
- }
- while (WHITE(c));
- switch (f)
- {
- case 'o':
- radix = 8;
- break;
- case 'x':
- case 'X':
- radix = 16;
- break;
- default:
- radix = 10;
- break;
- }
- scan_complete_number:
- neg = FALSE;
- if (width > 0 && c == '+')
- {
- NEXT(c);
- --width;
- }
- else if (width > 0 && c == '-' && radix == 10)
- {
- neg = TRUE;
- NEXT(c);
- --width;
- }
- scan_unsigned_number:
- n = 0;
- ok = FALSE;
- while (width > 0)
- {
- --width;
- if (isdigit(c))
- d = c - '0';
- else if (isupper(c))
- d = c - 'A' + 10;
- else if (islower(c))
- d = c - 'a' + 10;
- else
- break;
- if (d < 0 || d >= radix)
- break;
- ok = TRUE;
- n = n * radix + d;
- c = *buf++;
- if (!c)
- break;
- else
- ++chars;
- }
- if (!ok)
- return count;
- if (assign)
- {
- if (neg)
- n = -n;
- switch (size)
- {
- case 'h':
- short_ptr = va_arg(arg_ptr, short *);
- *short_ptr = (short) n;
- break;
- case 'l':
- long_ptr = va_arg(arg_ptr, long *);
- *long_ptr = (long) n;
- break;
- default:
- int_ptr = va_arg(arg_ptr, int *);
- *int_ptr = (int) n;
- }
- ++count;
- }
- if (!c)
- return count;
- else
- UNGETC();
- break;
- case 'n':
- if (assign)
- {
- int_ptr = va_arg(arg_ptr, int *);
- *int_ptr = chars;
- ++count;
- }
- break;
- default:
- if (!f) /* % at end of string */
- return count;
- NEXT(c);
- if (c != f)
- return count;
- break;
- }
- ++fmt;
- }
- }
- return count;
- }
- #endif /* HAVE_VSSCANF */
|