Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
9214 turbocat 1
/* PDCurses */
2
 
3
#include 
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 
45
 
46
#ifndef HAVE_VSSCANF
47
# include 
48
# include 
49
# include 
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 */