home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 436_01 / indemo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-07  |  25.0 KB  |  770 lines

  1. /*************************************************************************
  2.     INDEMO.C -- Driver for testing and debugging INCON.
  3.  
  4.     Compiler:  Borland Turbo C 2.01
  5.  
  6.     INCON source files and the object and library files created from
  7.     them are:
  8.         Copyright (c) 1993-94, Richard Zigler.
  9.     You may freely distribute unmodified source, object, and library
  10.     files, and incorporate them into your own non-commercial software,
  11.     provided that this paragraph and the program name and copyright
  12.     strings defined in INCON.C are included in all copies.
  13. *************************************************************************/
  14.  
  15. #include <bios.h>                                /* for keyboard routines            */
  16. #include <conio.h>                            /* for console i/o routines        */
  17. #include <dos.h>                                /* for FP_SEG and FP_OFF            */
  18. #include <math.h>                                /* for sin()                            */
  19. #include <stdio.h>                            /* for scanf()                            */
  20. #include <stdlib.h>                            /* for exit() and ato?()            */
  21. #include <string.h>                            /* for string operations            */
  22. #include "indefs.h"                            /* declarations and definitions    */
  23. #include "indecl.h"                            /* function prototypes                */
  24.  
  25. /****
  26.     Set UPPER_LOWER to 0 if you want the flags on the menu to appear
  27.     in uppercase only.
  28. ****/
  29.  
  30. #define UPPER_LOWER        1
  31.  
  32. #define FULL_SCREEN        1,1,80,25        /* full screen coordinates            */
  33. #define MENU_ITEMS        19                    /* number of items in menu            */
  34. #define MSG_BLK_SIZ        8                    /* message block size (words)        */
  35. #define RADIX                10                    /* radix for itoa()                    */
  36. #define ALPHA_WIDTH        120                /* width of alpha prompt            */
  37. #define ALPHA_PREC        0                    /* alpha fields optional            */
  38. #define ALPHA_FILL        250                /* small bullet for text fill        */
  39. #define NUMER_WIDTH        3                    /* width of numeric prompts        */
  40. #define NUMER_PREC        1                    /* numeric fields mandatory        */
  41. #define NUMER_FILL        32                    /* numeric field fill char            */
  42. #define LOGIC_WIDTH        1                    /* width of yes/no prompts            */
  43. #define VISIBLE_LEN        0                    /* scroll field visible length    */
  44. #define FIELD_ATTR        0                    /* invert current attribute        */
  45. #define FIELD_PAD            NUMER_FILL        /* pad return with spaces            */
  46.  
  47. #define HUGE_PTR(x)        ((char huge *)(x))    /* far pointer arithmetic    */
  48.  
  49. /**** Main Menu ****/
  50.  
  51. static char *MainMenu =
  52. {
  53. "\r\n"
  54. "═══════════════════════════════════════╦════════════════════════════════════════"
  55. "                  Field Parameters     ║     Field Flags\r\n"
  56. "             ──────────────────────────╫──────────────────────────\r\n"
  57. "                  Width                ║     Strip        [ ]\r\n"
  58. "                  Precision            ║     Message      [ ]\r\n"
  59. "                  Visible              ║     Sign         [ ]\r\n"
  60. "                                       ║     Display      [ ]\r\n"
  61. "                  Attribute            ║     Confirm      [ ]\r\n"
  62. "                  Fill                 ║     Delimit      [ ]\r\n"
  63. "                  Pad                  ║     xKeys        [ ]\r\n"
  64. "                                       ║     Scroll       [ ]\r\n"
  65. "                  Type         [ ]     ║     Hide         [ ]\r\n"
  66. "                  Justify      [ ]     ║     Template     [ ]\r\n"
  67. };
  68.  
  69. /**** Field Coordinates ****/
  70.  
  71. static int Field[MENU_ITEMS][2] =
  72. {
  73. {  1,  1 },                                        /* Default input string                */
  74. { 32,  5 },                                        /* Width                                    */
  75. { 32,  6 },                                        /* Prec                                    */
  76. { 32,  7 },                                        /* Visible                                */
  77. { 32,  9 },                                        /* Attr                                    */
  78. { 32, 10 },                                        /* Fill                                    */
  79. { 32, 11 },                                        /* Pad                                    */
  80. { 32, 13 },                                        /* Input Type                            */
  81. { 32, 14 },                                        /* Justify                                */
  82. { 59,  5 },                                        /* Strip                                    */
  83. { 59,  6 },                                        /* Message                                */
  84. { 59,  7 },                                        /* Sign                                    */
  85. { 59,  8 },                                        /* Display                                */
  86. { 59,  9 },                                        /* Confirm                                */
  87. { 59, 10 },                                        /* Delimit                                */
  88. { 59, 11 },                                        /* xKeys                                    */
  89. { 59, 12 },                                        /* Scroll                                */
  90. { 59, 13 },                                        /* Hide                                    */
  91. { 59, 14 },                                        /* Template                                */
  92. };
  93.  
  94. /**** Menu Info Strings ****/
  95.  
  96. static char *MenuInfo[MENU_ITEMS] =
  97. {
  98. "Enter default input string, or press [Enter], [Tab], or [Shift+Tab] for none.",
  99. "Maximum field width.",
  100. "Minimum input required or float field decimals.",
  101. "Scrolling field visible length.",
  102. "Input field video attribute; 0 for inverse of current screen attribute.",
  103. "Decimal ASCII character in unoccupied positions of the input field.",
  104. "Decimal ASCII character in leading and trailing spaces of justified output.",
  105. "May be Alpha, Upper, Integer, Float, or Mixed.",
  106. "May be None, Left, Center, or Right.",
  107. "Strip delimiters from template fields.",
  108. "Display run-time error messages.",
  109. "Allow sign in numeric fields.",
  110. "Display default input string.",
  111. "Require confirmation of input.",
  112. "Display field between delimiters.",
  113. "Trap extended keys.",
  114. "Allow alpha fields to scroll.",
  115. "Do not display input in field.",
  116. "Treat default input string as input template.",
  117. };
  118.  
  119. #define INFO_LINE            1,24                /* put info line here                */
  120. #define INFO_AT            1,25                /* put info string here                */
  121.  
  122. /****
  123.     dPrompt holds the default input string between calls to InCon, so
  124.     that the string doesn't have to be reinitialized between calls.
  125.     dPrompt is copied to ioBuf, the working version of the input
  126.     string that is passed to InCon.  ioBuf is modified or not,
  127.     depending on whether InCon detects an entry error or whether
  128.     the user presses an extended key in xKeyList.
  129. ****/
  130.  
  131. static char            dPrompt        [INCON_BUFFER + 1];
  132. static char            ioBuf            [INCON_BUFFER + 1];
  133.  
  134. extern char            Copyright[];                        /* defined in INCON.C    */
  135. static char            ProgName[]        = "INDEMO 3.1";
  136. const  char            StatsFlags[]    = "B BBB BB B B B B B B B B B B";
  137.  
  138. #if (UPPER_LOWER)
  139. static char            TypeStr[] = "aAuUiIfFmM";        /* input type options    */
  140. static char            JustStr[] = "nNlLcCrR";            /* input justification    */
  141. static char              NoYes[] = "nNyY";                /* yes/no flags options    */
  142. #else
  143. static char            TypeStr[] = "AUIFM";
  144. static char            JustStr[] = "NLCR";
  145. static char              NoYes[] = "NY";
  146. #endif
  147.  
  148. /****
  149.     The extended-key list passes codes for [Tab], [Shift+Tab],
  150.     and the unshifted function keys.  InCon treats the list as
  151.     a C string; it must be terminated by a null byte.
  152. ****/
  153.  
  154. const BYTE xKeyList[] =
  155.                 { 9, 15, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 0 };
  156.  
  157. /**** Menu Navigation and Help ****/
  158.  
  159. static int pascal DemoMenu    ( int, int, int, MBLOCK far *, char *             );
  160. extern int pascal InHelp    ( int                                                        );
  161.  
  162. /************************************************************************/
  163. /* main()                                                                                    */
  164. /*                                                                                                */
  165. /* The message block passed to InCon is declared as a union.                */
  166. /* In the input loop, it is addressed as an array of integers;                */
  167. /* in the output loop, it is addressed as a structure.                        */
  168.  
  169. void main( void )
  170. {
  171. register int        i;                            /* loop counter, utility            */
  172. register int        incon_ret;                /* return code from InCon            */
  173. int                    yn;                        /* yes/no loop-control flag        */
  174. int                    attr;                        /* current video attribute            */
  175. int                    help_attr;                /* normal attr for help screen    */
  176. WORD                    work;                        /* working storage                    */
  177. BIT_FLAGS        *    flags;                    /* flags from user message block    */
  178. union
  179.     {
  180.     long                user_long;                /* integer field value                */
  181.     double            user_dbl;                /* float field value                    */
  182.     }                    user_val;                /* value of user input                */
  183.  
  184.                                                     /* message blocks used by INDEMO    */
  185. static MBLOCK        a_block;                    /*  alpha field block                */
  186. static MBLOCK        n_block;                    /*  numeric field block                */
  187. static MBLOCK        l_block;                    /*  logical (yes/no) field block    */
  188. static MBLOCK        u_block;                    /* user message block                */
  189.  
  190. MBLOCK far        *    block_ptr;                /* message block pointer            */
  191.  
  192. char                *    work_buf;                /* pointer to scratch buffer        */
  193. char                *    str_ptr_1;                /* working pointers to strings    */
  194. char                *    str_ptr_2;
  195.  
  196. #if defined( __TURBOC__ )
  197. extern char            _video;                    /* Turbo C internal table            */
  198. *((char *)&_video + 10) = '\0';            /* disable CGA snow control        */
  199. #endif
  200.  
  201. /****
  202.     Force loading of the floating-point library.  This is a kludge
  203.     recommended by Borland, though there is no bug of course.
  204. ****/
  205.  
  206. user_val.user_dbl = sin( 1 );
  207.  
  208. work_buf = malloc( INCON_BUFFER + 1 );
  209. if ( work_buf == NULL )
  210.     {
  211.     cputs( "\n\aInsufficient memory..." );
  212.     exit( 1 );
  213.     }
  214.  
  215. clrscr();
  216.  
  217. attr = GetVideoAttr();                        /* get current video attribute    */
  218. help_attr =    ((attr & 0x07) << 4)    |        /*  and invert for help window    */
  219.                 ((attr & 0x70) >> 4)    |
  220.                 ( attr & 0x08)            ;
  221.  
  222. InHelp( help_attr | 0x8000 );                /* init help screen                    */
  223.  
  224. /****
  225.     Set up INDEMO's message blocks.
  226.     Note that, when addressing the message block as an array of
  227.     integers, the value that is stored at the higher address must
  228.     be shifted into the high byte for the assignment.
  229. ****/
  230.  
  231. a_block.iblock[0] =    FP_OFF( dPrompt  );    /* default input string field    */
  232. a_block.iblock[1] =    FP_SEG( dPrompt  );
  233. a_block.iblock[2] =    FP_OFF( xKeyList );
  234. a_block.iblock[3] =    FP_SEG( xKeyList );
  235. a_block.iblock[4] =     FLAG_ALPHA    |
  236.                             FLAG_CONFIRM|
  237.                             FLAG_XKEYS    ;
  238. a_block.iblock[5] =    ALPHA_WIDTH    | (ALPHA_PREC    << 8);
  239. a_block.iblock[6] =    VISIBLE_LEN    | (FIELD_ATTR    << 8);
  240. a_block.iblock[7] =    ALPHA_FILL    | (FIELD_PAD    << 8);
  241.  
  242. n_block.iblock[0] =    FP_OFF( work_buf );    /* numeric fields                    */
  243. n_block.iblock[1] =    FP_SEG( work_buf );
  244. n_block.iblock[2] =    FP_OFF( xKeyList );
  245. n_block.iblock[3] =    FP_SEG( xKeyList );
  246. n_block.iblock[4] =    FLAG_INTGR    |
  247.                             FLAG_RJUST    |
  248.                             FLAG_DISPLAY|
  249.                             FLAG_CONFIRM|
  250.                             FLAG_XKEYS    ;
  251. n_block.iblock[5] =    NUMER_WIDTH    | (NUMER_PREC    << 8);
  252. n_block.iblock[6] =    VISIBLE_LEN    | (FIELD_ATTR    << 8);
  253. n_block.iblock[7] =    NUMER_FILL    | (FIELD_PAD    << 8);
  254.  
  255. l_block.iblock[0] =    FP_OFF( work_buf );    /* logical (yes/no) fields        */
  256. l_block.iblock[1] =    FP_SEG( work_buf );
  257. l_block.iblock[2] =    FP_OFF( xKeyList );
  258. l_block.iblock[3] =    FP_SEG( xKeyList );
  259. #if (UPPER_LOWER)
  260. l_block.iblock[4] =    FLAG_DELIMIT|
  261.                             FLAG_XKEYS    ;
  262. #else
  263. l_block.iblock[4] =    FLAG_UPPER    |
  264.                             FLAG_DELIMIT|
  265.                             FLAG_XKEYS    ;
  266. #endif
  267. l_block.iblock[5] =    LOGIC_WIDTH    | (NUMER_PREC    << 8);
  268. l_block.iblock[6] =    VISIBLE_LEN    | (attr            << 8);
  269. l_block.iblock[7] =    NUMER_FILL    | (FIELD_PAD    << 8);
  270.  
  271. /****
  272.     Set up user message block values that are common to all calls.
  273.     The message blocks defined above are those used by InDemo itself.
  274.     The following message block is for testing and debugging InCon;
  275.     it gets filled in the input loop below.
  276. ****/
  277.  
  278. u_block.iblock[0] =    FP_OFF( ioBuf      );
  279. u_block.iblock[1] =    FP_SEG( ioBuf      );
  280. u_block.iblock[2] =    FP_OFF( xKeyList );
  281. u_block.iblock[3] =    FP_SEG( xKeyList );
  282.  
  283.  
  284. cputs( MainMenu );                            /* display menu                        */
  285. do                                                    /**** begin input loop            ****/
  286.     {
  287.     window( FULL_SCREEN );
  288.     gotoxy( INFO_LINE );
  289.     WriteMany( '─', attr, MAXCOL );
  290.     for ( i = 0 ; i < MENU_ITEMS ; i++ )
  291.         {
  292.         gotoxy( INFO_AT );
  293.         WriteMany( ' ', attr, MAXCOL );
  294.         cprintf( "%-.*s", MAXCOL - 1, MenuInfo[i] );
  295.         gotoxy( Field[i][0], Field[i][1] );
  296.         if ( i > 6 )
  297.             block_ptr = &l_block;
  298.         else if ( i )
  299.             block_ptr = &n_block;
  300.         else
  301.             block_ptr = &a_block;
  302.  
  303.         /****
  304.             In the following switch block, work receives values entered
  305.             into the menu.  Since work is unsigned, the tests of those
  306.             values need only check the upper bound of the valid range
  307.             (the lower bound is 0 in each case).  If work is changed
  308.             to a signed quantity, the tests would have to check both
  309.             upper and lower bounds (work < 0 || work > 255).
  310.         ****/
  311.  
  312.         switch ( i )
  313.             {
  314.  
  315.             case 0 :                                /* default input string                */
  316.  
  317.                 incon_ret = InCon( block_ptr );
  318.                 if ( incon_ret != 0 )                    /* if entry error            */
  319.                     strcpy( work_buf, dPrompt );        /*  reload default        */
  320.                 break;
  321.  
  322.             case 1 :                                /* field width                            */
  323.             case 2 :                                /* field precision                    */
  324.  
  325.                 work =    i == 1                                    ?
  326.                             LOBYTE(u_block.iblock[5])            :
  327.                             LOBYTE(u_block.iblock[5] >> 8)    ;
  328.                 itoa( work, work_buf, RADIX );
  329.                 incon_ret = InCon( block_ptr );
  330.                 work = atoi( work_buf );
  331.                 incon_ret |= (work > 255);                /* <---- work unsigned    */
  332.                 if ( incon_ret == 0 )
  333.                     {
  334.                     cputs( work_buf );
  335.                     u_block.iblock[5] =
  336.                             i == 1                                                ?
  337.                             HIBYTE(u_block.iblock[5]) | LOBYTE(work)    :
  338.                             LOBYTE(u_block.iblock[5]) | (work << 8)    ;
  339.                     }
  340.                 break;
  341.  
  342.             case 3 :                                /* scroll field visible length    */
  343.             case 4 :                                /* field attribute                    */
  344.  
  345.                 work =    i == 3                                    ?
  346.                             LOBYTE(u_block.iblock[6])            :
  347.                             LOBYTE(u_block.iblock[6] >> 8)    ;
  348.                 itoa( work, work_buf, RADIX );
  349.                 incon_ret = InCon( block_ptr );
  350.                 work = atoi( work_buf );
  351.                 incon_ret |= (work > 255);
  352.                 if ( incon_ret == 0 )
  353.                     {
  354.                     cputs( work_buf );
  355.                     u_block.iblock[6] =
  356.                             i == 3                                                ?
  357.                             HIBYTE(u_block.iblock[6]) | LOBYTE(work)    :
  358.                             LOBYTE(u_block.iblock[6]) | (work << 8)    ;
  359.                     }
  360.                 break;
  361.  
  362.             case 5 :                                /* field fill char                    */
  363.             case 6 :                                /* return string pad character    */
  364.  
  365.                 work =    i == 5                                    ?
  366.                             LOBYTE(u_block.iblock[7])            :
  367.                             LOBYTE(u_block.iblock[7] >> 8)    ;
  368.                 itoa( work, work_buf, RADIX );
  369.                 incon_ret = InCon( block_ptr );
  370.                 work = atoi( work_buf );
  371.                 incon_ret |= (work > 255);
  372.                 if ( incon_ret == 0 )
  373.                     {
  374.                     WriteMany( ' ', attr, 3 );
  375.                     if ( work == 32 || work == 255 )
  376.                         cprintf( "%3s", work == 32 ? "Sp" : "PSp" );
  377.                     else
  378.                         cprintf( "%2c", (BYTE) work );
  379.                     u_block.iblock[7] =
  380.                             i == 5                                                ?
  381.                             HIBYTE(u_block.iblock[7]) | LOBYTE(work)    :
  382.                             LOBYTE(u_block.iblock[7]) | (work << 8)    ;
  383.                     }
  384.                 break;
  385.  
  386.             case 7 :                                /* input type                            */
  387.             case 8 :                                /* output justify                        */
  388.  
  389.                 /****
  390.                     This block and the default block that follows first
  391.                     get the current value of the flag and use it to index
  392.                     the relevant string.  The indexed character is handed
  393.                     to InCon for display as default input.  The return
  394.                     value from InCon is then used to set the new value.
  395.                 ****/
  396.  
  397.                 str_ptr_2 = (i == 7) ? TypeStr : JustStr ;
  398.                 work = u_block.iblock[4];
  399.                 if ( i == 7 )
  400.                     {
  401.                     work &=    MASK_TYPE;
  402.                     work >>=    SHIFT_TYPE;
  403.                     }
  404.                 else
  405.                     {
  406.                     work &=    MASK_JUSTIFY;
  407.                     work >>=    SHIFT_JUSTIFY;
  408.                     }
  409.  
  410. #if (UPPER_LOWER)
  411.                 work <<= 1;                        /* index TypeStr or JustStr        */
  412.                 work++;
  413. #endif
  414.                 *((WORD *) work_buf) = str_ptr_2[work];     /* put char and 0    */
  415.                 incon_ret =        InCon( block_ptr );
  416.                 str_ptr_1 =        strchr( str_ptr_2, (int) *work_buf );
  417.                 incon_ret |=    (str_ptr_1 == NULL);
  418.                 if ( incon_ret == 0 )
  419.                     {
  420.                     work = str_ptr_1 - str_ptr_2;        /* convert ptr to index    */
  421.  
  422. #if (UPPER_LOWER)
  423.                     work >>= 1;                                /*   and index to flag    */
  424. #endif
  425.                     /****
  426.                         Clear current value of flag, shift new value into
  427.                         position, and store new value.
  428.                     ****/
  429.  
  430.                     if ( i == 7 )
  431.                         {
  432.                         u_block.iblock[4] &= ~MASK_TYPE;
  433.                         work <<= SHIFT_TYPE;
  434.                         }
  435.                     else
  436.                         {
  437.                         u_block.iblock[4] &= ~MASK_JUSTIFY;
  438.                         work <<= SHIFT_JUSTIFY;
  439.                         }
  440.                     u_block.iblock[4] |= work;
  441.                     }                                            /* if (incon_ret)            */
  442.                 break;
  443.  
  444.             default :                            /* all yes/no flags                    */
  445.  
  446.                 work =    u_block.iblock[4];            /* isolate flag            */
  447.                 work >>= (MENU_ITEMS - i - 1);
  448.                 work &=    1;
  449.  
  450. #if (UPPER_LOWER)
  451.                 work <<= 1;                                    /* index NoYes                */
  452.                 work++;
  453. #endif
  454.                 *((WORD *) work_buf) = NoYes[work];
  455.                 incon_ret =  InCon( block_ptr );
  456.                 str_ptr_1 =  strchr( NoYes, (int) *work_buf );
  457.                 incon_ret |= (str_ptr_1 == NULL);
  458.                 if ( incon_ret == 0 )
  459.                     {
  460.                     work = str_ptr_1 - NoYes;            /* convert ptr to index    */
  461.  
  462. #if (UPPER_LOWER)
  463.                     work >>= 1;                                /* make yes/no flag        */
  464. #endif
  465.                     /****
  466.                         First turn off each flag.  Then, at the end
  467.                         of the switch block, shift the value of the
  468.                         answer from above into position and combine
  469.                         it with the flags already in place.
  470.                     ****/
  471.  
  472.                     switch ( i )
  473.                         {
  474.                         case  9 :                                /* strip template        */
  475.                             u_block.iblock[4] &= ~MASK_STRIP;
  476.                             break;
  477.                         case 10 :                                /* run-time messages    */
  478.                             u_block.iblock[4] &= ~MASK_MESSAGE;
  479.                             break;
  480.                         case 11 :                                /* signed input        */
  481.                             u_block.iblock[4] &= ~MASK_SIGN;
  482.                             break;
  483.                         case 12 :                                /* display default    */
  484.                             u_block.iblock[4] &= ~MASK_DISPLAY;
  485.                             break;
  486.                         case 13 :                                /* confirm input        */
  487.                             u_block.iblock[4] &= ~MASK_CONFIRM;
  488.                             break;
  489.                         case 14 :                                /* field delimiters    */
  490.                             u_block.iblock[4] &= ~MASK_DELIMIT;
  491.                             break;
  492.                         case 15 :                                /* trap xKeys            */
  493.                             u_block.iblock[4] &= ~MASK_XKEYS;
  494.                             break;
  495.                         case 16 :                                /* scroll field        */
  496.                             u_block.iblock[4] &= ~MASK_SCROLL;
  497.                             break;
  498.                         case 17 :                                /* hidden input        */
  499.                             u_block.iblock[4] &= ~MASK_HIDE;
  500.                             break;
  501.                         case 18 :                                /* template field        */
  502.                             u_block.iblock[4] &= ~MASK_TEMPLATE;
  503.                             break;
  504.                         }                                            /* switch()                */
  505.                     work <<= (MENU_ITEMS - i - 1);
  506.                     u_block.iblock[4] |= work;                /* store the flag        */
  507.                     }                                                /* if (incon_ret)        */
  508.                 break;
  509.             }                                                        /* switch()                */
  510.  
  511.         /****
  512.             If InCon returned the F1 key, put up the help window.
  513.             If it returned [Tab], [Shift+Tab], one of the other
  514.             keys from xKeyList, or a value invalid for the current
  515.             field, do the menu-handling.  The return from DemoMenu()
  516.             must be decremented because i is incremented at the
  517.             bottom of the for() loop.
  518.         ****/
  519.  
  520.         if ( incon_ret != 0 )
  521.             {
  522.             if ( incon_ret == 59 )
  523.                 InHelp( help_attr );
  524.             i = DemoMenu( i, incon_ret, attr, block_ptr, work_buf );
  525.             --i;
  526.             }
  527.         }                                            /* for (i)                                */
  528.  
  529. /************************************************************************/
  530. /* Display the data that is being passed to InCon.  From this point on    */
  531. /* the message block is addressed as a structure.                                */
  532.  
  533. #define TEXT_WINDOW1        1, 16, 80, 25    /* text window coordinates            */
  534. #define TEXT_WINDOW2        1, 17, 80, 25
  535.  
  536.     window( TEXT_WINDOW1 );
  537.     clrscr();
  538.  
  539.     block_ptr = &u_block;                    /* load user message block            */
  540.     strcpy( ioBuf, dPrompt );                /* load default string                */
  541.  
  542.     flags = (BIT_FLAGS *)&block_ptr->sblock.Flags.bflags;
  543.  
  544.     /* extract pointer to i/o buffer from message block as further test    */
  545.  
  546.     str_ptr_1 = (char *)MK_FP(
  547.                         block_ptr->sblock.BufSeg, block_ptr->sblock.BufOff );
  548.  
  549.     cprintf( "\r\n%s", str_ptr_1 );        /* print default string, using    */
  550.                                                     /*  far pointer from above            */
  551.  
  552.     /**** Display window layout.
  553.  
  554. Test Field___________________
  555. User Input___________________
  556. _____________________________
  557. _____________________________
  558. _____________________________
  559.  ┌────────────────────────────────────────────────────────────────────────────┐
  560.  │ INDEMO 3.1                           Copyright (c) 1993-94, Richard Zigler │
  561.  │ ioBuf segment:offset = XXXX:XXXX       xKeyList segment:offset = XXXX:XXXX │
  562.  │ Width:  XX   Prec:  XX   Visible:  XX     Attr:  XX   Fill:  XX   Pad:  XX │
  563.  │ Flags:  B BBB BB B B B B B B B B B B     Use [Numpad 5] to toggle Stat Box │
  564.  └────────────────────────────────────────────────────────────────────────────┘
  565.  
  566.     ****/
  567.  
  568.  
  569.     /****
  570.         Build string of flags bit-values.  incon_ret is used as
  571.         an index here because it is free for the time being, and
  572.         it is a register variable.
  573.     ****/
  574.  
  575.     work = block_ptr->sblock.Flags.iflags;
  576.     for ( i = 0x8000, incon_ret = 0 ; StatsFlags[incon_ret] ; incon_ret++ )
  577.         {
  578.         if ( StatsFlags[incon_ret] == 'B' )
  579.             {
  580.             work_buf[incon_ret] = work & i ? '1' : '0' ;
  581.             (WORD) i >>= 1;                    /* need unsigned shift                */
  582.             }
  583.         else
  584.             work_buf[incon_ret] = ' ';
  585.         }
  586.     work_buf[incon_ret] = '\0';
  587.     Cursor( OFF );
  588.     gotoxy( 1, 5 );
  589.     cprintf                                        /* print stat box                        */
  590.         (
  591.         " ┌──────────────────────────────────────"
  592.         "──────────────────────────────────────┐ "
  593.         " │ %-37s%s │ "
  594.         " │ ioBuf segment:offset = %.4X:%.4X"
  595.         "       xKeyList segment:offset = %.4X:%.4X │ "
  596.         " │ Width:  %.2X   Prec:  %.2X   Visible:  %.2X"
  597.         "     Attr:  %.2X   Fill:  %.2X   Pad:  %.2X │ "
  598.         " │ Flags:  %-33sUse [Numpad 5] to toggle Stat Box │ "
  599.         " └──────────────────────────────────────"
  600.         "──────────────────────────────────────┘"
  601.         , ProgName                            , Copyright
  602.         , block_ptr->sblock.BufSeg        , block_ptr->sblock.BufOff
  603.         , block_ptr->sblock.KeySeg        , block_ptr->sblock.KeyOff
  604.         , block_ptr->sblock.Width        , block_ptr->sblock.Prec
  605.         , block_ptr->sblock.Visible    , block_ptr->sblock.Attr
  606.         , block_ptr->sblock.Fill        , block_ptr->sblock.Pad
  607.         , work_buf
  608.         );
  609.     Cursor( ON );
  610.  
  611.     /****
  612.         Enable INCON Stat Box, which shows changes made to
  613.         flags and parameters by field initialization.  INCON
  614.         displays its Stat Box only if INCON_STATS is non-zero
  615.         when INCON.C is compiled and the Debug flag is set.
  616.     ****/
  617.  
  618.     flags->Debug = YES;
  619.  
  620. /************************************************************************/
  621.     do                                                /**** begin output loop            ****/
  622.         {
  623.         int l;                                    /* return string length                */
  624.  
  625.         /****
  626.             Call InCon with far pointer to message block.  Put
  627.             the cursor where the input field is to appear; InCon
  628.             will determine the absolute cursor position for itself.
  629.             Turn off Debug flag when InCon returns so that repeated
  630.             calls to InCon from within this do...while block don't
  631.             trigger display of the Stat Box each time.  The __emit__
  632.             statement sets a breakpoint for the debugger; it has no
  633.             effect when the program is run from the command line.
  634.             While InCon returns the F1 key code, display help screen.
  635.         ****/
  636.  
  637.         window( TEXT_WINDOW1 );
  638.         __emit__( 0xCC );                                                /* Int 03h        */
  639.  
  640.         while ( (incon_ret = InCon( block_ptr )) == 59 )
  641.             InHelp( help_attr );
  642.         flags->Debug = NO;
  643.         window( TEXT_WINDOW2 );
  644.         clrscr();
  645.  
  646.         /****
  647.             Print the contents of the i/o buffer, using the far pointer
  648.             created above.  The buffer now contains either the user's
  649.             input (if there was no input error), or the original default
  650.             string.
  651.         ****/
  652.  
  653.         cputs( str_ptr_1 );
  654.         gotoxy( 1, 5 );                        /* print InCon return code and    */
  655.         cprintf                                    /*  length of input string            */
  656.             (
  657.             "InCon returned:  %d (%04Xh)\r\n"
  658.             "  Input length:  %d\r\n"
  659.             "   Input value:  "
  660.             , incon_ret, incon_ret, l = strlen( str_ptr_1 )
  661.             );
  662.  
  663.         /****
  664.             Determine whether or not field type is float, and print
  665.             value of return string.  InCon may convert an integer
  666.             field to float or an unsigned integer field to signed
  667.             (see INCON.DOC), so check for '.' or '-' in ioBuf.
  668.         ****/
  669.  
  670.         if ( !flags->Template && flags->Type & INTGR )
  671.             {
  672.             if ( strchr( ioBuf, '.' ) )
  673.                 {
  674.                 int p = block_ptr->sblock.Prec;    /* p may be 0 if integer    */
  675.                                                             /*  converted to float        */
  676.                 user_val.user_dbl = atof( ioBuf );
  677.                 cprintf( "%.*lf", p ? p : l, user_val.user_dbl );
  678.                 }
  679.             else
  680.                 {
  681.                 user_val.user_long = strtol( ioBuf, (char **) 0, RADIX );
  682.                 cprintf( "%ld", user_val.user_long );
  683.                 }
  684.             }
  685.         else
  686.             {
  687.             user_val.user_long = strtoul( ioBuf, (char **) 0, RADIX );
  688.             cprintf( "%lu", user_val.user_long );
  689.             }
  690.         strcpy( ioBuf, dPrompt );            /* reload default input string    */
  691.         gotoxy( 1, 9 );
  692.         cputs( "Quit this test (y/n)? " );
  693.         yn = LOBYTE(KEYREAD);
  694.         }
  695.     while ( yn != 'y' && yn != 'Y' );    /**** end output loop            ****/
  696. /************************************************************************/
  697.     window( TEXT_WINDOW1 );
  698.     clrscr();
  699.     gotoxy( 1, 10 );
  700.     cputs( "Quit all tests (y/n)? " );
  701.     yn = LOBYTE(KEYREAD);
  702.     clrscr();
  703.     }
  704. while ( yn != 'y' && yn != 'Y' );        /**** end input loop                ****/
  705. free( work_buf );
  706. }
  707.  
  708. /************************************************************************/
  709. /* DemoMenu() -- menu-handling for main().                                        */
  710.  
  711. static int pascal DemoMenu( int MenuItem, int InconRet,
  712.                                     int Attr, MBLOCK far * Block, char * String )
  713.     {
  714.     register int    i = MenuItem,
  715.                         work,
  716.                         field_width,
  717.                         delimit;
  718.  
  719.     delimit        = Block->sblock.Flags.bflags.Delimit;
  720.     field_width    = Block->sblock.Width + (delimit ? 2 : 0);
  721.  
  722.     switch( i )                                    /* reprint current field value    */
  723.         {
  724.         case  0:                                    /* default input string                */
  725.             clreol();
  726.             cprintf( "%-.*s", MAXCOL, String );
  727.             break;
  728.         case  1:                                    /* numeric fields                        */
  729.         case  2:
  730.         case  3:
  731.         case  4:
  732.             cprintf( "%*s", field_width, String );
  733.             break;
  734.         case  5:                                    /* fill character                        */
  735.         case  6:                                    /* pad character                        */
  736.             work = atoi( String );
  737.             WriteMany( ' ', Attr, 3 );
  738.             if ( work == 32 || work == 255 )
  739.                 cprintf( "%*s", field_width, work == 32 ? "Sp" : "PSp" );
  740.             else
  741.                 cprintf( "%2c", (BYTE)work );
  742.             break;
  743.         default:                                    /* Type, Justify, yes/no flags    */
  744.             if ( delimit )
  745.                 cprintf( "[%c]", *String );
  746.             else
  747.                 cprintf( "%*s", field_width, String );
  748.             break;
  749.         }
  750.  
  751.     /****
  752.         Now tell main() where to go.  Invalid entries stay
  753.         with current menu item.
  754.     ****/
  755.  
  756.     if ( InconRet == 9 )                        /* [Tab] -- go ahead                    */
  757.         {
  758.         if ( ++i >= MENU_ITEMS )            /* at last item                        */
  759.             i = 0;                                /* go to first                            */
  760.         }
  761.     else if ( InconRet == 15 )                /* [Shift+Tab] -- back up            */
  762.         {
  763.         if ( --i < 0 )                            /* at first item                        */
  764.             i += MENU_ITEMS;                    /* go to last                            */
  765.         }
  766.     return ( i );
  767.     }
  768.  
  769. /**** EOF:  INDEMO.C ****/
  770.