Subversion Repositories svn1

Rev

Rev 53 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 root 1
/*************************************************************************
2
*           Copyright (C) 1995 Embedded Solutions
3
*                       All rights reserved
4
*
5
* file:     src\vduW32.c
6
*
7
* purpose:  This module contains all the VDU interface routines
8
*
9
*           This instance of this file implements the functions
10
*           in a Win32 platform.
11
*
12
*           A small number of routines are provided. These can be emulated
13
*           on other machines to provide similar functions
14
*
15
*           A number of general purpose I/O routines are also provided
16
*
17
* functions
18
*       init_screen             - Initialize the screen
19
*       cur                     - Position the cursor on the screen
20
*       clearscreen             - Clears the vdu screen
21
*       beep                    - Generate a bell character
22
*       flush_out               - Flush terminal output
23
*       getinp                  - Get one character of input
24
*       getnum                  - Get a number from the operator
25
*       getstring               - Get and edit a string
26
*       getsex                  - Get a sex type from the operator
27
*       getclass                - Get a class descriptor
28
*       getcountry              - Get a country descriptor
29
*       getfnc                  - Get menu selector
30
*       getyes                  - Prompt for YES / NO
31
*       to_upper                - Convert character to upper case
32
*       to_lower                - Convert character to lower case
33
*       sleep                   - Wait a bit
34
*       printf                  - Text display routines
35
*       putchar                 - Text display routines
36
*       console_clreol          - Clear to end of the line
37
*       console_prompt          - Display a hightlighted prompt
38
*
39
* programmer: David Purdie
40
*
41
* revision  date        by      reason
42
*   00.0    17/09/2002  DDP     Created
43
*
44
**************************************************************************/
45
 
46
#include    <stdio.h>
47
#include    <ctype.h>
48
#include    <windows.h>
49
#include    <wincon.h>
50
 
51
#include    "consts.h"
52
#include    "structs.h"
53
#include    "proto.h"
54
 
55
/* variables used by the routines */
56
 
57
int         n_lines;                             /* Number of lines on the screen */
58
int         n_cols;
59
 
60
int         rubout = '\010';                     /* users rubout character */
61
char        escape = '\033';                     /* Escape character */
62
int         abort_flag = FALSE;                  /* Abort character detected */
63
int         fnc_opr;                             /* Function key pushed */
53 - 64
char        *force_cmds = NULL;                  /* Initial commnads */
1 root 65
 
66
 
67
HANDLE      h_console;                          /* Output handle */
68
 
69
/*
70
**  Prototypes
71
*/
72
int get_kb_character( void );
73
 
53 - 74
/*----------------------------------------------------------------------------
75
** FUNCTION           : set_commands
76
**
77
** DESCRIPTION        :
78
**
79
**
80
** INPUTS             : cptr            - Address of commands to execute
81
**
82
** RETURNS            : Nothing
83
**
84
** PRECONDITION       : 
85
**
86
** EXCEPTIONS         :
87
**
88
** WARNING            :
89
**
90
** SEE ALSO           :
91
----------------------------------------------------------------------------*/
1 root 92
 
53 - 93
void set_commands ( char * cptr )
94
{
95
    force_cmds = cptr;
96
}
97
 
98
 
1 root 99
/*========================================================================
100
 *
101
 *  Initialize the screen
102
 *
103
 *  Purpose:
104
 *      This function is called to Initialize the screen
105
 *
106
 *  Parameters:
107
 *      None
108
 *
109
 *  Returns:
110
 *      Nothing
111
 *
112
 *========================================================================*/
113
 
114
void init_screen( void )
115
{
116
    /*
117
    **  Save a handle to the console
118
    */
119
    h_console = GetStdHandle(STD_OUTPUT_HANDLE);
120
 
121
    /*
122
    **  Operate within a virtual console area of 24 * 80
123
    **  Ignore the real console area
124
    */
125
    n_lines = 24;                                /* Fix number of lines for export */
126
    n_cols = 80;                                 /* Number of cols */
127
}
128
 
129
 
130
/*========================================================================
131
 *
132
 *  Restore screen to normal
133
 *
134
 *  Purpose:
135
 *      This function is called to Restore screen to normal
136
 *
137
 *  Parameters:
138
 *      None
139
 *
140
 *  Returns:
141
 *      Nothing
142
 *
143
 *========================================================================*/
144
 
145
void fix_screen( void )                          /* Restore screen to normal */
146
{
147
    flush_out();
148
}
149
 
150
/*========================================================================
151
 *
152
 *  Position the cursor on the screen
153
 *
154
 *  Purpose:
155
 *      This function is called to Position the cursor on the screen
156
 *
157
 *  Parameters:
158
 *      x               col number
159
 *      y               line number
160
 *
161
 *  Returns:
162
 *      Nothing
163
 *
164
 *========================================================================*/
165
 
166
void cur( int x, int y )
167
{
168
    COORD cursor;
169
 
170
    cursor.Y = y;
171
    cursor.X = x;
172
    SetConsoleCursorPosition ( h_console, cursor );
173
}
174
 
175
/*========================================================================
176
 *
177
 *  Position the cursor on the screen
178
 *
179
 *  Purpose:
180
 *      This function is called to save the current cursor location
181
 *      A single level save - for debug
182
 *
183
 *  Parameters:
184
 *      None
185
 *
186
 *  Returns:
187
 *      Nothing
188
 *
189
 *========================================================================*/
190
int save_x,save_y;
191
void save_cur(void)
192
{
193
 
194
    CONSOLE_SCREEN_BUFFER_INFO console_info;
195
 
196
    /*
197
    **  Determine the screen size and the current location of the
198
    **  cursor within the screen
199
    */
200
    GetConsoleScreenBufferInfo( h_console, &console_info );
201
    save_x = console_info.dwCursorPosition.X;
202
    save_y = console_info.dwCursorPosition.Y;
203
}
204
 
205
void restore_cur(void)
206
{
207
    cur( save_x, save_y);
208
}
209
 
210
 
211
/*========================================================================
212
 *
213
 *  Clears the vdu screen 
214
 *
215
 *  Purpose:
216
 *      This function is called to Clears the vdu screen
217
 *      From the Microsoft Web Site 
218
 *
219
 *  Parameters:
220
 *      None
221
 *
222
 *  Returns:
223
 *      Nothing
224
 *
225
 *========================================================================*/
226
 
227
void clearscreen( void )
228
{
229
    COORD coordScreen = { 0, 0 };        /* home for the cursor  */
230
    DWORD cCharsWritten;
231
    CONSOLE_SCREEN_BUFFER_INFO csbi;
232
    DWORD dwConSize;
233
 
234
    /*
235
    **   Get the number of character cells in the current buffer.
236
    */
237
 
238
    if( !GetConsoleScreenBufferInfo( h_console, &csbi ))
239
        return;
240
    dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
241
 
242
    /*
243
    **   Fill the entire screen with blanks.
244
    */
245
    if( !FillConsoleOutputCharacter( h_console, (TCHAR) ' ',
246
                                dwConSize, coordScreen, &cCharsWritten ))
247
        return;
248
 
249
    /*
250
    **    Get the current text attribute.
251
    */
252
    if( !GetConsoleScreenBufferInfo( h_console, &csbi ))
253
        return;
254
 
255
    /*
256
    **  Set the buffer's attributes accordingly.
257
    */
258
    if( !FillConsoleOutputAttribute( h_console, csbi.wAttributes,
259
                                dwConSize, coordScreen, &cCharsWritten ))
260
        return;
261
 
262
    /*
263
    **   Put the cursor at its home coordinates.
264
    */
265
    SetConsoleCursorPosition( h_console, coordScreen );
266
}
267
 
268
/*========================================================================
269
 *
270
 *  Generate a bell character
271
 *
272
 *  Purpose:
273
 *      This function is called to Generate a bell character
274
 *
275
 *  Parameters:
276
 *      None
277
 *
278
 *  Returns:
279
 *      Nothing
280
 *
281
 *========================================================================*/
282
 
283
void beep( void )
284
{
285
    putchar( '\007' );
286
}
287
 
288
 
289
/*========================================================================
290
 *
291
 *  Flush terminal output
292
 *
293
 *  Purpose:
294
 *      This function is called to Flush terminal output
295
 *
296
 *  Parameters:
297
 *      None
298
 *
299
 *  Returns:
300
 *      Nothing
301
 *
302
 *========================================================================*/
303
 
304
void flush_out( void )
305
{
306
}
307
 
308
 
309
/*========================================================================
310
 *
311
 *  Get one character of input
312
 *
313
 *  Purpose:
314
 *      This function is called to Get one character of input
315
 *
316
 *  Parameters:
317
 *      None
318
 *
319
 *  Returns:
320
 *      Ascii code or internal control code which will be greater than
321
 *      a byte
322
 *
323
 *========================================================================*/
324
 
325
int getinp( void )
326
{
327
 
328
    /*
329
     * General input routine
330
     * Will intercept function keys and set flags
331
     */
332
 
333
    int         c;
334
 
53 - 335
    if ( force_cmds && *force_cmds )
336
    {
337
        c = *force_cmds++;
338
    }
339
    else
340
    {
341
        c = get_kb_character();
342
    }
1 root 343
    if( c & 0xff )
344
    {
345
        c = c & 0xff;
346
        if( c == '\r' )
347
            c = '\n';
348
        if( c == ABORT_CHAR || c == ABORT_CHAR_1 )
349
        {
350
            abort_flag = TRUE;
351
            c = ABORT_CHAR;
352
        }
353
        return ( c );                            /* Input is ascii char */
354
    }
355
    c >>= 8;                                     /* Upper byte */
356
    if( c >= 59 && c <= 68 )
357
    {
358
        fnc_opr = FNC1 + c - 59;
359
        return ( 0 );
360
    }
361
    switch ( c )
362
    {
363
    case 71:    return ( HOME_KEY );
364
    case 72:    return ( UPARROW );
365
    case 75:    return ( LEFTARROW );
366
    case 77:    return ( RIGHTARROW );
367
    case 80:    return ( DOWNARROW );
368
    case 73:    return ( PAGE_UP );
369
    case 81:    return ( PAGE_DOWN );
370
    case 79:    return ( END_KEY );
371
    case 82:    return ( INSERT_KEY );
372
    case 83:    return ( DELETE_KEY );
373
    case 15:    return ( BACKTAB );
374
    }
375
    return ( 0 );
376
}
377
 
378
 
379
/*========================================================================
380
 *
381
 *  Get a number from the operator
382
 *
383
 *  Purpose:
384
 *      This function is called to get a number from the operator
385
 *      
386
 *      This routine will accept numeric data entry from the operator
387
 *      the routine will limit the operator input to a limited number
388
 *      of characters. This allowes fixed format input
389
 *      
390
 *  Parameters:
391
 *      max_len         Max field width allowed
392
 *      final_buf       pointer to the final resting place of the number
393
 *
394
 *  Returns:
395
 *      This routine will return an indication of operator input
396
 *          0 - No valid entry
397
 *          1 - data entered and transfered to number.
398
 *
399
 *========================================================================*/
400
 
401
bool getnum( int max_len, int *final_buf )
402
{
403
    char        n_buf[30];                       /* Convert number here */
404
 
405
    n_buf[0] = '\0';
406
    if ( *final_buf )
407
        sprintf( n_buf, "%*.*d", max_len,max_len, *final_buf );
408
    if( getstring( max_len, n_buf, Digit ) )
409
    {
410
        sscanf( n_buf, "%d", final_buf );
411
        return ( TRUE );
412
    }
413
    else
414
        return ( FALSE );
415
}
416
 
417
/*========================================================================
418
 *
419
 *  Get and edit a string
420
 *
421
 *  Purpose:
422
 *      This function is called to Get and edit a string
423
 *
424
 *  Parameters:
425
 *      len                 Max length of the string
426
 *      str                 Address of the string
427
 *      limit               Types of chars allowed
428
 *
429
 *  Returns:
430
 *      Length of the input string
431
 *
432
 *========================================================================*/
433
 
434
int getstring( int len, char *str, enum class_enum limit )
435
{
436
    char        buf[100];                        /* Internal edit buffer */
437
    int         i;                               /* Current index into buf */
438
    int         ii;                              /* Number of characters in buf */
439
    int         j;                               /* Loooopy variable */
440
    int         ch;                              /* Current input character */
441
 
442
    ( void ) memset( buf, 0, 100 );              /* Init the buffer */
443
    ( void ) strcpy( buf, str );                 /* Copy in the original string */
444
    ii = i = strlen( str );                      /* i is at the end of the string */
445
    printf( "%s", buf );                         /* Display the current string */
446
 
447
    /*
448
     * This routine assumes that the cursor is at the end of
449
     * the string as it is displayed on the screen
450
     */
451
 
452
    while( !abort_flag )
453
    {
454
        ch = getinp();                           /* Get the next character */
455
 
456
        if( ch == '\n' || ch == '\t' || fnc_opr || abort_flag )/* RETURN */
457
            break;                               /* Finish the edit */
458
 
459
        else if( ch == rubout && i )             /* Users rubout character */
460
        {
461
            i--;
462
            putchar( '\010' );
463
            for( j = i; j <= ii; j++ )
464
                buf[j] = buf[j + 1];
465
            printf( "%s ", &buf[i] );            /* Print remainder of the buffer */
466
            ii--;                                /* One less in the buffer */
467
            for( j = i; j <= ii; j++ )
468
                putchar( '\010' );
469
        }
470
 
471
        else if( ch == DELETE_KEY && i != ii )   /* Delete char under cursor */
472
        {
473
            for( j = i; j <= ii; j++ )
474
                buf[j] = buf[j + 1];
475
            printf( "%s ", &buf[i] );
476
            ii--;
477
            for( j = i; j <= ii; j++ )
478
                putchar( '\010' );
479
        }
480
 
481
        else if( ( ch == '\010' || ch == LEFTARROW ) && i ) /* Back-space */
482
        {
483
            i--;
484
            putchar( '\010' );
485
        }
486
 
487
        else if( ch == RIGHTARROW && i < ii )    /* forward */
488
            putchar( buf[i++] );
489
 
490
        else if( ( ii < len ) && ( ( ( limit == Alphanum  || limit == AlphnumUpper) && isprint( ch ) ) || ( ( limit == Digit ) && isascii( ch ) && isdigit( ch ) ) || ( ( limit == Alpha ) && isalpha( ch ) ) ) )    /* Insert the char */
491
        {
492
            if ( limit == AlphnumUpper )
493
                ch = toupper(ch);
494
 
495
            for( j = ii + 1; j > i; j-- )
496
                buf[j] = buf[j - 1];
497
            buf[i] = ch;
498
            ii++;
499
            printf( "%s", &buf[i++] );  /* Print remainder of the buffer */
500
            for( j = i; j < ii; j++ )
501
                putchar( '\010' );
502
        }
503
        else
504
        {
505
            beep();
506
        }
507
    }
508
 
509
    /*
510
     * Edit complete - transfer the data to the user 
511
     */
512
 
513
    printf( "%s", &buf[i] );            /* Cursor to end of the buffer */
514
    if( !abort_flag )
515
        strcpy( str, buf );             /* Copy buffer to the user */
516
    else
517
        ii = 0;
518
    return ( ii );                               /* Return length of input */
519
}
520
 
521
/*========================================================================
522
 *
523
 *  Get a sex type from the operator
524
 *
525
 *  Purpose:
526
 *      This function is called to Get a sex type from the operator
527
 *
528
 *  Parameters:
529
 *      None
530
 *
531
 *  Returns:
532
 *      A sex type
533
 *      The unknown sex type is used to signal no change in state
534
 *
535
 *========================================================================*/
536
 
537
sex_type getsex( void )
538
{
539
    sex_type    curr = unknown;                  /* current sex type in display */
540
    char        c;
541
 
542
    while( ( c = getinp() ) != ABORT_CHAR )
543
    {
544
        if( c == '\n' || c == '\t' )
545
        {
546
            return ( curr );
547
        }
45 - 548
        if( c == 'M' || c == 'm')
1 root 549
        {
550
            printf( "Male  \010\010\010\010\010\010" );
551
            curr = male;
552
        }
45 - 553
        else if( c == 'F' || c == 'f' )
1 root 554
        {
555
            printf( "Female\010\010\010\010\010\010" );
556
            curr = female;
557
        }
558
        else
559
        {
560
            beep();
561
        }
562
    }
563
    return ( unknown );
564
}
565
 
566
/*========================================================================
567
 *
568
 *  Get a class descriptor
569
 *
570
 *  Purpose:
571
 *      This function is called to Get a class descriptor
572
 *
573
 *  Parameters:
574
 *      None
575
 *
576
 *  Returns:
577
 *      An integer which is the index into the  config.team_class array
578
 *
579
 *========================================================================*/
580
 
581
int getclass( void )
582
{
583
    char        cc[3];                           /* Input character */
584
    int         i, j;                            /* One those loopy things */
585
 
586
 
587
    cc[0] = '\0';
588
    while( ( j = getstring( 2, cc, AlphnumUpper ) ) != 0 )
589
    {
590
        /*
591
        **  Is this a valid class
592
        */
593
        if ( (i = lookup_class(cc, NULL)) > 0 )
594
            return (i);
595
 
596
        /*
597
        **  Invalid
598
        **  Rubout and try again
599
        */
600
        beep();
601
        for( i = 0; i < j; i++ )
602
            putchar( '\010' );
603
    }
604
    return ( 0 );
605
}
606
 
607
/*========================================================================
608
 *
609
 *  Get a country descriptor
610
 *
611
 *  Purpose:
612
 *      This function is called to Get a country descriptor
613
 *
614
 *  Parameters:
615
 *      None
616
 *
617
 *  Returns:
618
 *      An integer which is the index into the config.country_name array.
619
 *
620
 *========================================================================*/
621
 
622
int getcountry( void )
623
{
624
    char        cc[5];                           /* Input character */
625
    int         i, j, k;                         /* One those loopy things */
626
 
627
    cc[0] = '\0';
628
    while( ( j = getstring( 4, cc, Alphanum ) ) != 0 )
629
    {
630
 
631
        /*
632
         * Attempt to locate the entered country in the list of defined countries
633
         */
634
 
635
        for( i = 0; i < MAX_COUNTRY; i++ )
636
        {
637
            for( k = 0; k <= j; k++ )
638
            {
639
                if( cc[k] == '\000' )
640
                    return ( ++i );              /* Found it */
641
 
642
                if( toupper( cc[k] ) !=
643
                    toupper( config.country_name[i].abr[k] ) )
644
                    break;
645
            }
646
        }
647
        beep();
648
        for( i = 0; i < j; i++ )
649
            putchar( '\010' );
650
    }
651
    return ( 0 );
652
}
653
 
654
/*========================================================================
655
 *
656
 *  Get menu selector
657
 *
658
 *  Purpose:
659
 *      This function is called to Get menu selector
660
 *
661
 *      This function will accept characters until one in
662
 *      "list" is encountered. This is returned to the user
663
 *      RETURN is valid if the first character of the list is not a "*"
664
 *      it will return the first charcater of the list;
665
 *      ABORT will return a zero
666
 *
667
 *  Parameters:
668
 *      List        A string of valid responses
669
 *
670
 *  Returns:
671
 *      Selected character
672
 *
673
 *========================================================================*/
674
 
675
char getfnc( char *list )
676
{
677
    char       *copylist;
678
    char        c;
679
    char        result = 0;
680
 
681
    copylist = ( *list == '*' ) ? list + 1 : list;
682
    while( ( c = getinp() ) != ABORT_CHAR )
683
    {
684
        c = toupper( c );                        /* Get a character */
685
        if( strchr( copylist, c ) )
686
        {
687
            result = c;
688
            break;
689
        }
690
 
691
        if( c == '\n' && *list != '*' )
692
        {
693
            result = *list;
694
            break;
695
        }
696
 
697
        beep();
698
    }
699
 
700
    /*
701
    **  Display the option selected
702
    **  Not ready for this yet. Looks a bit ugle in a few places
703
    */
704
    /*    if ( result )
705
    **    putchar(result);
706
    */
707
 
708
    return ( result );
709
}
710
 
711
/*========================================================================
712
 *
713
 *  Prompt for YES / NO
714
 *
715
 *  Purpose:
716
 *      This function is called to Prompt for YES / NO
717
 *
718
 *  Parameters:
719
 *      prompt      Prompt to display to the user
720
 *
721
 *  Returns:
722
 *      TRUE for Yes, FALSE for No
723
 *
724
 *========================================================================*/
725
 
726
bool getyes( char *prompt )
727
{
728
    char        c;
729
 
730
    printf( "%s ? ", prompt );
731
    c = getfnc( "*YN" );
732
    putchar( '\n' );
733
    return ( c == 'Y' );
734
}
735
 
736
/*========================================================================
737
 *
738
 *  Convert character to upper case
739
 *
740
 *  Purpose:
741
 *      This function is called to convert character to upper case
742
 *
743
 *  Parameters:
744
 *      ch      Character to convert
745
 *
746
 *  Returns:
747
 *      Converted character
748
 *
749
 *========================================================================*/
750
 
751
char to_upper( char ch )
752
{
753
    if( islower( ch ) )
754
        return ( ch + 'A' - 'a' );
755
    return ( ch );
756
}
757
 
758
/*========================================================================
759
 *
760
 *  Convert character to lower case
761
 *
762
 *  Purpose:
763
 *      This function is called to convert character to lower case
764
 *
765
 *  Parameters:
766
 *      ch      Character to convert
767
 *
768
 *  Returns:
769
 *      Converted character
770
 *
771
 *========================================================================*/
772
 
773
char to_lower( char ch )
774
{
775
    if( isupper( ch ) )
776
        return ( ch + 'a' - 'A' );
777
    return ( ch );
778
}
779
 
780
 
781
/*========================================================================
782
 *
783
 *  Wait a bit
784
 *
785
 *  Purpose:
786
 *      This function is called to idle and to nothing for a while
787
 *
788
 *  Parameters:
789
 *      t           Time to wait
790
 *
791
 *  Returns:
792
 *      Nothing
793
 *
794
 *========================================================================*/
795
 
796
void sleep( int t )
797
{
798
    Sleep ( t * 1000 );
799
}
800
 
801
 
802
/*========================================================================
803
 *
804
 *  Clear to the end of the current display line
805
 *
806
 *  Purpose:
807
 *      Clears to the end of the line
808
 *
809
 *  Parameters:
810
 *      None
811
 *
812
 *  Returns:
813
 *      Nothing
814
 *
815
 *========================================================================*/
816
void console_clreol( void )
817
{
818
 
819
    CONSOLE_SCREEN_BUFFER_INFO console_info;
820
    DWORD                      rlen;
821
 
822
    int ii;
823
    int top;
824
 
825
 
826
    /*
827
    **  Determine the screen size and the current location of the
828
    **  cursor within the screen
829
    */
830
    GetConsoleScreenBufferInfo( h_console, &console_info );
831
 
832
    /*
833
    **  Clear all of it
834
    */
835
    top = console_info.dwSize.X - console_info.dwCursorPosition.X;
836
 
837
    for ( ii = 0; ii < top ; ii++ )
838
    {
839
        WriteConsole( h_console, " ", 1, &rlen, NULL );
840
    }
841
    cur ( console_info.dwCursorPosition.X, console_info.dwCursorPosition.Y );
842
}
843
 
844
/*========================================================================
845
 *
846
 *  printf - Text display routines
847
 *  putchar - Text display routines
848
 *
849
 *
850
 *  Purpose:
851
 *      Intercept standard output calls and direct output to the
852
 *      console.
853
 *
854
 *  Parameters: As per standard function definitions
855
 *      None
856
 *
857
 *  Returns:
858
 *      As per standard function definitions
859
 *
860
 *========================================================================*/
861
 
862
 
863
int putchar(int cc)
864
{
865
    printf( "%c", cc );
866
    return 1;
867
}
868
 
869
// void gross_error_message(void)
870
// {
871
//     LPVOID lpMsgBuf;
872
//
873
//     FormatMessage(
874
//         FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
875
//         NULL,
876
//         GetLastError(),
877
//         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
878
//         (LPTSTR) &lpMsgBuf,
879
//         0,
880
//         NULL
881
//     );
882
//
883
//     // Display the string.
884
//     MessageBox( NULL, lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION );
885
//
886
//     // Free the buffer.
887
//     LocalFree( lpMsgBuf );
888
// }
889
 
890
int printf( const char *format, ... )
891
{
892
    va_list     ap;
893
    char        pp[200];
894
    int         len;
895
    BOOL        result;
896
    HANDLE      h_console;
897
 
898
    DWORD       llen;
899
    DWORD       rlen;
900
 
901
 
902
    va_start( ap, format );
903
    len = vsprintf( pp, format, ap );
904
    va_end( ap );
905
 
906
    llen = len;
907
    h_console = GetStdHandle(STD_OUTPUT_HANDLE);
908
    result = WriteConsole( h_console, pp, llen, &rlen, NULL );
909
    return ( len );
910
}
911
 
912
/*========================================================================
913
 *
914
 *  Display a prompt character in a highlight
915
 *
916
 *  Purpose:
917
 *      USed to highlight menu entries
918
 *
919
 *  Parameters:
920
 *      None
921
 *
922
 *  Returns:
923
 *      Nothing
924
 *
925
 *========================================================================*/
926
void console_prompt( char prompt )
927
{
928
    SetConsoleTextAttribute( h_console, FOREGROUND_GREEN );
929
    putchar( prompt );
930
    SetConsoleTextAttribute( h_console, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE );
931
}
932
 
933
/*------------------------------------------------------------------------------
934
Name:           get_kb_character
935
Description:    Extract a keyboard character - including cursor and function
936
                keys.
937
Parameters:     None
938
Global Refs:
939
Returns:        a 16 bit value that encodes ascii character and scan code
940
Side-effects:
941
------------------------------------------------------------------------------*/
942
 
943
int get_kb_character( void )
944
{
945
    HANDLE          hConsoleInput;
946
    INPUT_RECORD    Buffer;
947
    DWORD           NumberOfEventsRead;
948
 
949
    hConsoleInput = GetStdHandle(STD_INPUT_HANDLE);
950
 
951
    /*
952
    **  Process console events until we get a suitable keystroke event
953
    */
954
    FlushFileBuffers( h_console );
955
    for (;;)
956
    {
957
        if (ReadConsoleInput( hConsoleInput, &Buffer, 1, &NumberOfEventsRead ))
958
        {
959
            /*
960
            **  Only want keyboard depression - ignore other events
961
            */
962
            if (Buffer.EventType == KEY_EVENT && Buffer.Event.KeyEvent.bKeyDown)
963
            {
964
                /*
965
                **  Ignore several scan codes
966
                **  CNTRL, ALT, SHIFT, CAPLOCK
967
                */
968
                if (Buffer.Event.KeyEvent.wVirtualScanCode == 0x38 ||
969
                    Buffer.Event.KeyEvent.wVirtualScanCode == 0x1D ||
970
                    Buffer.Event.KeyEvent.wVirtualScanCode == 0x2A ||
971
                    Buffer.Event.KeyEvent.wVirtualScanCode == 0x3A)
972
                {
973
                    continue;
974
                }
975
 
976
                return ( (int) (Buffer.Event.KeyEvent.uChar.AsciiChar + (Buffer.Event.KeyEvent.wVirtualScanCode << 8)));
977
            }
978
        }
979
    }
980
 
981
}
982
 
983
/********************************* EOF ***********************************/
984