home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / qc / qc20 / chrtdemo.c next >
Encoding:
C/C++ Source or Header  |  1988-12-07  |  56.8 KB  |  1,995 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <bios.h>
  5. #include <conio.h>
  6. #include <graph.h>
  7. #include <pgchart.h>
  8. #include <stdarg.h>
  9. #include "chrtdemo.h"
  10.  
  11. /* Structures for system configuration and chart environment. */
  12. struct videoconfig vc;
  13. chartenv ce;
  14.  
  15. /* Category variables.  */
  16. short cCat;
  17. char far * aCat[MAXVALUES];
  18.  
  19. /* Series variables.  */
  20. short cSeries;
  21. short far acSeries[MAXSERIES];
  22. char far * aSeriesName[MAXSERIES];
  23.  
  24. /* Temporary holding array for all data. Data values for multi-series
  25.  * bar, column, and line charts remain here. Data for other kinds of
  26.  * charts are transferred to the arrays below.
  27.  */
  28. float far aValue[MAXSERIES][MAXVALUES];
  29.  
  30. /* Data values for single-series charts. First array is used for
  31.  * bar, column, line, and pie. First and second are both used for
  32.  * single-series scatter.
  33.  */
  34. float far axValue[MAXVALUES];
  35. float far ayValue[MAXVALUES];
  36.  
  37. /* Data values for multi-series scatter charts.  */
  38. float far axValueMS[MAXVALUES][MAXVALUES];
  39. float far ayValueMS[MAXVALUES][MAXVALUES];
  40.  
  41. /* Exploded flags for pie chart.  */
  42. short far aExplode[MAXVALUES];
  43.  
  44. /* Variables used to track control and screen position.  */
  45. struct SCREENINFO
  46. {
  47.     int  top;                        /* Row under top form line      */
  48.     int  bot;                        /* Row above bottom form line   */
  49.     int  mid;                        /* Middle line of form          */
  50.     int  help;                       /* Line number of help line     */
  51.     int  mode;                       /* Current screen mode          */
  52.     int  xMax;
  53.     int  yMax;
  54.     BOOL fColor;
  55. } si;
  56.  
  57. /* These variables hold either the constants #defined for color
  58.  * graphics adaptors (those that are formed: C_xxxxxCOLOR) or those
  59.  * #defined for monochrome graphics adaptors (those that are formed:
  60.  * M_xxxxxCOLOR).  They do NOT control the color of the presentation
  61.  * graphics -- just the color of the menus and prompts.
  62.  */
  63. struct tagColor
  64. {
  65.     short InputColor;                /* Color for input requests     */
  66.     short HiliteColor;               /* Color for prompt highlights  */
  67.     short FormColor;                 /* Color for input forms/menus  */
  68.     short TitleColor;                /* Color for titles             */
  69.     short ErrorColor;                /* Color for error messages     */
  70.     short InfoColor;                 /* Color for informations msgs. */
  71. } co;
  72.  
  73.  
  74. /* Constants that identify typefaces to ChooseFont. */
  75.  
  76. enum tagTypeFace
  77. {
  78.     COURIER,
  79.     HELV,
  80.     TMS_RMN,
  81.     MODERN,
  82.     SCRIPT,
  83.     ROMAN
  84. };
  85.  
  86.  
  87. /* Flags to indicate whether to use imported or default data.  */
  88. BOOL fDefault = TRUE;
  89.  
  90. /* Arrays of strings used by the Menu function. The first string is the
  91.  * menu title. The next non-null strings are the menu selections. A null
  92.  * string indicates the end of the list.
  93.  */
  94. char *pszAxes[] =
  95.     { "Axis", "X Axis", "Y Axis", "" };
  96.  
  97. char *pszAxis[] =
  98.     { "? Options", "Grid", "Axis Title", "Color",
  99.       "Range Type", "Scale", "Tic Marks", "" };
  100.  
  101. char *pszAuto[] =
  102.     { "Auto", "Auto", "Manual", "" };
  103.  
  104. char *pszBorder[] =
  105.     { "Type", "Color", "Style", "" };
  106.  
  107. char *pszChartOpt[] =
  108.     { "Options", "Screen Mode", "Windows", "Titles",
  109.       "Axis (X and Y)", "Legend", "Fonts", "Reset", "" };
  110.  
  111. char *pszChartType[] =
  112.     { "Type", "Bar", "Column", "Line", "Scatter", "Pie", "" };
  113.  
  114. char *pszChartWindow[] =
  115.     { "Chart", "Size", "Color (Background)", "Border", "" };
  116.  
  117. char *pszDataWindow[] =
  118.     { "Data", "Color (Background)", "Border", "" };
  119.  
  120. char * pszFontOpt[] =
  121.     { "Font Options", "Change Typeface", "Set Character Size", "" };
  122.  
  123. char *pszJustify[] =
  124.     { "Justify", "Left", "Center", "Right", "" };
  125.  
  126. char *pszLegendWindow[] =
  127.     { "Options", "Place", "Text Color", "Size", "Color (Background)",
  128.       "Border", "" };
  129.  
  130. char *pszMainMenu[] =
  131.     { "Main Menu", "Demo", "View Chart", "Chart Type", "Options",
  132.       "Show Chart Data", "Quit", "" };
  133.  
  134. char *pszPlace[] =
  135.     { "Place", "Right", "Bottom", "Overlay", "" };
  136.  
  137. char *pszScale[] =
  138.     { "Scale", "Low (Min)", "High (Max)", "Scale Factor", "Title", "" };
  139.  
  140. char *pszSize[] =
  141.     { "Size", "Top", "Left", "Bottom", "Right", "" };
  142.  
  143. char *pszTic[] =
  144.     { "Tic Type", "Interval", "Format", "Decimals", "" };
  145.  
  146. char *pszTitleOpt[] =
  147.     { "", "Text", "Color", "Justify", "" };
  148.  
  149. char *pszTitles[] =
  150.     { "Title", "Main Title", "Sub Title", "" };
  151.  
  152. char *pszTypeface[] =
  153.     { "Type Faces", "Courier", "Helv", "Tms Rmn", "Modern", "Script",
  154.            "Roman", "None", "" };
  155.  
  156. char *pszWindows[] =
  157.     { "Window", "Chart Window", "Data Window", "" };
  158.  
  159. /* Sample data.  */
  160. #define O_JUICE 0
  161. #define I_TEA   1
  162. #define H_CHOC  2
  163. #define TEMPERATURE  3
  164.  
  165. char far * aQuarters[] =
  166.     { "First", "Second", "Third", "Fourth" };
  167.  
  168. char far * aMonths[] =
  169.     { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  170.       "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
  171.  
  172. float far aSales[3][12] =
  173. {
  174.     {  3.6,  3.2,  3.3,  3.4,  3.1,  2.9,  3.0,  3.6,  3.2,  3.3,  3.5,  3.9 },
  175.     {  1.0,  1.3,  1.4,  1.7,  2.2,  2.9,  2.9,  3.1,  2.6,  1.8,  1.1,  1.2 },
  176.     {  2.4,  2.3,  2.0,  1.6,  1.3,  1.0,  0.9,  0.8,  1.1,  1.4,  1.9,  2.5 }
  177. };
  178.   
  179. float far aTemperature[12] =
  180.     {  2.9,  3.2,  3.9,  4.8,  6.0,  6.5,  7.0,  7.2,  6.0,  4.7,  4.1,  3.0 };
  181.  
  182. char far * aSalesTitles[] =
  183.     { "Orange Juice Sales", "Iced Tea Sales", "Hot Chocolate Sales" };
  184.  
  185. char *TempTitle = "Average Temperature";
  186.  
  187. int main()
  188. {
  189.     Initialize();
  190.     MainMenu();
  191.  
  192.     /* Reset the video mode and screen colors prior to leaving. */
  193.     _setvideomode( _DEFAULTMODE );
  194.     _settextcolor( co.InfoColor );
  195.     _clearscreen( _GCLEARSCREEN );
  196.  
  197.     return 0;
  198. }
  199.  
  200. /*  Axes - Selects X or Y axis.
  201.  *
  202.  *  Params: none
  203.  */
  204. void Axes()
  205. {
  206.     int iChoice;
  207.     static axistype *patAxis[2] = { &ce.xaxis, &ce.yaxis };
  208.  
  209.     /* Get menu choice and call appropriate axis Menu. */
  210.     PushTitle( pszAxes[0] );
  211.     Help( "Choose 'X' or 'Y' Axis", co.InputColor );
  212.     while( (iChoice = Menu( pszAxes )) != ESCAPE )
  213.     {
  214.         /* Modify axis title, depending on choice. */
  215.         pszAxis[0][0] = (--iChoice == 0) ? 'X' : 'Y';
  216.  
  217.         /* Obtain axis information for appropriate axis. */
  218.         Axis( patAxis[iChoice] );
  219.     }
  220.     PopTitle();
  221. }
  222.  
  223. /*  Axis - Selects axis options.
  224.  *
  225.  *  Params: pat - Pointer to axistype variable
  226.  */
  227. void Axis( axistype *pat )
  228. {
  229.     int iChoice;
  230.  
  231.     PushTitle( pszAxis[0] );
  232.     while( (iChoice = Menu( pszAxis )) != ESCAPE )
  233.     {
  234.  
  235.         /* Get Axis option.  */
  236.         switch( iChoice )
  237.         {
  238.             case 1:
  239.                 /* Grid or not? */
  240.                 iChoice = BlankMenu( "Grid", "Grid", "No Grid" );
  241.                 switch( iChoice )
  242.                 {
  243.  
  244.                     case 1:
  245.                         /* If yes, set grid flag and get the grid style. */
  246.                         pat->grid = TRUE;
  247.                         Help( "Enter a number in the range 0-10.",
  248.                             co.InputColor );
  249.                         pat->gridstyle =
  250.                             InputInt( "Grid Style? ", pat->gridstyle, 0, 10 );
  251.                         break;
  252.  
  253.                     case 2:
  254.                         /* If no, clear grid flag.  */
  255.                         pat->grid = FALSE;
  256.                 }
  257.                 PopTitle();
  258.                 break;
  259.  
  260.             case 2:
  261.                 /* Select axis title options. */
  262.                 pszTitleOpt[0] = "Axis Title";
  263.                 TitleOpt( &pat->axistitle );
  264.                 break;
  265.  
  266.             case 3:
  267.                 /* Select color. */
  268.                 Help( "Enter a number in the range 0-15.", co.InputColor );
  269.                 pat->axiscolor =
  270.                     InputInt( "Axis Color? ", pat->axiscolor, 0, 15 );
  271.                 break;
  272.  
  273.             case 4:
  274.                 /* Get the axis range.  */
  275.                 AxisRange( pat );
  276.                 break;
  277.  
  278.             case 5:
  279.                 /* Get the axis scale.  */
  280.                 AxisScale( pat );
  281.                 break;
  282.  
  283.             case 6:
  284.                 /* Get axis tic mark options.  */
  285.                 AxisTics( pat );
  286.                 break;
  287.  
  288.         }
  289.     }
  290.     PopTitle();
  291. }
  292.  
  293. /*  AxisRange - Selects range for an axis.
  294.  *
  295.  *  Params: pat - pointer to axistype variable
  296.  */
  297. void AxisRange( axistype *pat )
  298. {
  299.     int iChoice;
  300.  
  301.     iChoice = BlankMenu( "Range Type", "Normal", "Log" );
  302.     switch( iChoice )
  303.     {
  304.         case 1:
  305.             /* Set range type to linear.  */
  306.             pat->rangetype = _PG_LINEARAXIS;
  307.             break;
  308.  
  309.         case 2:
  310.             /* Set range type to log, then query for log base.  */
  311.             pat->rangetype = _PG_LOGAXIS;
  312.             Help( "Enter a value greater than or equal 2.", co.InputColor );
  313.             pat->logbase = InputInt( "Log base? ", (int)pat->logbase, 2, 0 );
  314.             break;
  315.     }
  316.     PopTitle();
  317. }
  318.  
  319. /*  AxisScale - Selects scale options for an axis.
  320.  *
  321.  *  Params: pat - pointer to axistype variable
  322.  */
  323. void AxisScale( axistype *pat )
  324. {
  325.     int iChoice;
  326.  
  327.     PushTitle( pszAuto[0] );
  328.     iChoice = Menu( pszAuto );
  329.     switch( iChoice )
  330.     {
  331.  
  332.         case 1:
  333.             /* Set AutoScale flag.  */
  334.             pat->autoscale = TRUE;
  335.             break;
  336.  
  337.         case 2:
  338.  
  339.             /* Clear AutoScale flag and get scale options.  */
  340.             pat->autoscale = FALSE;
  341.             PushTitle( pszScale[0] );
  342.             while( (iChoice = Menu( pszScale )) != ESCAPE )
  343.             {
  344.  
  345.                 switch( iChoice )
  346.                 {
  347.  
  348.                     case 1:  
  349.                         /* Query for scale minimum.  */
  350.                         Help( "Enter the range minimum value.", co.InputColor );
  351.                         pat->scalemin =
  352.                             InputInt( "Minimum? ", pat->scalemin, 1, 0 );
  353.                         break;
  354.  
  355.                     case 2:  
  356.                         /* Query for scale maximum.  */
  357.                         Help( "Enter the range maximum value.", co.InputColor );
  358.                         pat->scalemax =
  359.                             InputInt( "Maximum? ", pat->scalemax, 1, 0 );
  360.                         break;
  361.  
  362.                     case 3:
  363.                         /* Query for scale factor.  */
  364.                         Help( "Enter scale factor (must be 1 or greater).",
  365.                                  co.InputColor );
  366.                         pat->scalefactor =
  367.                             InputInt( "Scale Factor? ", pat->scalefactor,
  368.                                        1, 0 );
  369.                         break;
  370.  
  371.                     case 4:  
  372.                         /* Modify scale title, then use menu to get
  373.                          * title options.
  374.                          */
  375.                         pszTitleOpt[0] = "Scale Title";
  376.                         TitleOpt( &pat->scaletitle );
  377.  
  378.                 }
  379.             }
  380.             PopTitle();
  381.     }
  382.     PopTitle();
  383. }
  384.  
  385. /*  AxisTics - Selects tic options for an axis.
  386.  *
  387.  *  Params: pat - pointer to axistype variable
  388.  */
  389. void AxisTics( axistype *pat )
  390. {
  391.     int iChoice;
  392.  
  393.     PushTitle( pszTic[0] );
  394.     while( (iChoice = Menu( pszTic )) != ESCAPE )
  395.     {
  396.         switch( iChoice )
  397.         {
  398.  
  399.             case 1:
  400.                 /* Query for tic interval.  */
  401.                 Help( "Enter distance in data units.", co.InputColor );
  402.                 pat->ticinterval =
  403.                     InputFloat( "Distance between tic marks? ",
  404.                                pat->ticinterval );
  405.                 pat->autoscale = FALSE;
  406.                 break;
  407.  
  408.             case 2:
  409.                 /* Query for tic format.  */
  410.                 iChoice = BlankMenu( "Tic Format", "Normal", "Log" );
  411.                 if( iChoice != ESCAPE )
  412.                     pat->ticformat = iChoice;
  413.                 break;
  414.  
  415.             case 3:
  416.                 /* Query for number of decimal places per tic.  */
  417.                 pat->ticdecimals =
  418.                     InputInt( "Enter decimal places (0 to 9). ",
  419.                                pat->ticdecimals, 0, 9 );
  420.                 pat->autoscale = FALSE;
  421.                 break;
  422.         }
  423.  
  424.     }
  425.     PopTitle();
  426. }
  427.  
  428. /*  Border - Specifies border information for a window.
  429.  *
  430.  *  Params: pwt - Pointer to windowtype variable
  431.  */
  432. void Border( windowtype *pwt )
  433. {
  434.     int iChoice;
  435.  
  436.     /* Ask whether a border is wanted.  */
  437.     iChoice = BlankMenu( "Border", "Border", "No Border" );
  438.     switch( iChoice )
  439.     {
  440.  
  441.         case 1:
  442.  
  443.             /* If border, set Border flag and query for border options.  */
  444.             pwt->border= TRUE;
  445.             PushTitle( pszBorder[0] );
  446.             while( (iChoice = Menu( pszBorder )) != ESCAPE )
  447.             {
  448.                 switch( iChoice )
  449.                 {
  450.                     case 1:
  451.                         /* Query for border color.  */
  452.                         Help( "Enter a color in the range 0-15.",
  453.                             co.InputColor );
  454.                         pwt->bordercolor =
  455.                             InputInt( "Border color? ",
  456.                                        pwt->bordercolor, 0, 15 );
  457.                         break;
  458.  
  459.                     case 2:
  460.                         /* Query for border style.  */
  461.                         Help( "Enter a style in the range 0-10.", co.InputColor );
  462.                         pwt->borderstyle =
  463.                             InputInt( "Border style? ",
  464.                                        pwt->borderstyle, 0, 10 );
  465.                 }
  466.             }
  467.             PopTitle();
  468.             break;
  469.  
  470.         case 2:
  471.             /* If no border, clear Border flag.  */
  472.             pwt->border= FALSE;
  473.     }
  474.     PopTitle();
  475. }
  476.  
  477. /*  ChangeTypeface - Allow the user to specify a new type face.
  478.  *
  479.  *  Params: None
  480.  */
  481.  
  482. void ChangeTypeface()
  483. {
  484.     int iChoice;
  485.     struct _fontinfo fd;
  486.     static BOOL FontsRegistered = FALSE;    /* state of font package */
  487.  
  488.     /* Get menu choice and call appropriate axis Menu. */
  489.     PushTitle( pszFontOpt[0] );
  490.     Help( "Choose one of the type faces listed.", co.InputColor );
  491.  
  492.     if( (iChoice = Menu( pszTypeface )) != ESCAPE )
  493.     {
  494.         /* If the user wants the system font, unregister the other fonts. */
  495.         if( iChoice == 7 )
  496.         {
  497.             _unregisterfonts();
  498.             FontsRegistered = FALSE;
  499.         }
  500.  
  501.         /* If the user wants any font but the system font, make sure the
  502.          *   fonts are registered.
  503.          */
  504.         else
  505.         {
  506.             if( !FontsRegistered )
  507.             {
  508.                 if( _registerfonts( "*.FON" ) < 0 )
  509.                 {
  510.                     ErrorMsg( "Unable to register fonts" );
  511.                     return;
  512.                 }
  513.                 else
  514.                     FontsRegistered = TRUE; /* Reset the state to registered */
  515.             }
  516.  
  517.             /* Get the previous font settings */
  518.             _getfontinfo( &fd );
  519.  
  520.             ChooseFont( iChoice - 1, fd.pixheight );
  521.         }
  522.     }
  523.  
  524.     PopTitle();
  525. }
  526.  
  527. /*  ChartOptions - Gets chart options.
  528.  *
  529.  *  Params: None
  530.  */
  531. void ChartOptions()
  532. {
  533.     int iChoice;
  534.  
  535.     PushTitle( pszChartOpt[0] );
  536.     while( (iChoice = Menu( pszChartOpt )) != ESCAPE )
  537.     {
  538.  
  539.         /* Get chart options.  */
  540.         switch( iChoice )
  541.         {
  542.  
  543.             /* Branch to the appropriate menu.  */
  544.             case 1:
  545.                 ScreenMode();
  546.                 break;
  547.  
  548.             case 2:
  549.                 Windows();
  550.                 break;
  551.  
  552.             case 3:
  553.                 Titles();
  554.                 break;
  555.  
  556.             case 4:
  557.                 Axes();
  558.                 break;
  559.  
  560.             case 5:
  561.                 Legend();
  562.                 break;
  563.  
  564.             case 6:
  565.                 FontOptions();
  566.                 break;
  567.  
  568.             case 7:
  569.                 ResetOptions();
  570.                 break;
  571.  
  572.         }
  573.     }
  574.     PopTitle();
  575. }
  576.  
  577. /*  ChartType - Gets chart type.
  578.  *
  579.  *  Params: None
  580.  */
  581. void ChartType()
  582. {
  583.     int iChoice;
  584.  
  585.     /* Get chart type.  */
  586.     PushTitle( pszChartType[0] );
  587.     iChoice = Menu( pszChartType );
  588.  
  589.     if( iChoice != ESCAPE )
  590.     {
  591.         /* Set the chart type, and get the chart style.  */
  592.         ce.charttype = iChoice;
  593.         switch( iChoice )
  594.         {
  595.  
  596.             case 1:
  597.             case 2:
  598.                 iChoice = BlankMenu( "Style", "Plain Bars", "Stacked Bars" );
  599.                 break;
  600.  
  601.             case 3:
  602.             case 4:
  603.                 iChoice = BlankMenu( "Style", "Lines-Points", "Points Only" );
  604.                 break;
  605.  
  606.             case 5:
  607.                 iChoice = BlankMenu( "Style", "Percent", "No Percent" );
  608.         }
  609.  
  610.         if( iChoice != ESCAPE)
  611.             ce.chartstyle = iChoice;
  612.  
  613.         /* Set default data without changing environment defaults.  */
  614.         DefaultData( ce.charttype, ce.chartstyle, FALSE );
  615.         PopTitle();
  616.     }
  617.     PopTitle();
  618. }
  619.  
  620. /*  ChooseFont - Chooses a font from the font library.
  621.  *
  622.  *  Params: WhichFont - A member of the set [COURIER, HELV, TMS_RMN,
  623.  *                        MODERN, SCRIPT, ROMAN]
  624.  *          Height    - The desired height of the text (in pixels)
  625.  */
  626.  
  627. void ChooseFont( int WhichFont, int Height )
  628. {
  629.     static char *FontIds[] =
  630.     {
  631.         "courier", "helv", "tms rmn", "modern", "script", "roman"
  632.     };
  633.     char SetCommand[21];
  634.  
  635.  
  636.     /* Construct the command to send to _setfont. */
  637.  
  638.     sprintf( SetCommand, "t'%s'h%dw0b", FontIds[WhichFont], Height );
  639.  
  640.     if( _setfont( SetCommand ) )
  641.     {
  642.         _outtext( "Could not set font to " );
  643.         _outtext( FontIds[WhichFont] );
  644.         _outtext( "." );
  645.         getch();
  646.     }
  647. }
  648.  
  649.  
  650. /*  ChartWindow - Gets chart window information.
  651.  *
  652.  *  Params: None
  653.  */
  654. void ChartWindow()
  655. {
  656.     int iChoice;
  657.  
  658.     PushTitle( pszChartWindow[0] );
  659.     while( (iChoice = Menu( pszChartWindow )) != ESCAPE )
  660.     {
  661.  
  662.         /* Get window options.  */
  663.         switch( iChoice )
  664.         {
  665.  
  666.             case 1:
  667.                 /* Get window size.  */
  668.                 WindowSize( &ce.chartwindow );
  669.                 break;
  670.  
  671.             case 2:
  672.                 /* Query for background color.  */
  673.                 Help( "Enter a number in the range 0-15", co.InputColor );
  674.                 ce.chartwindow.background =
  675.                     InputInt( "Background Color? ", ce.chartwindow.background,
  676.                               0, 15 );
  677.                 break;
  678.  
  679.             case 3:
  680.  
  681.                 /* Get border options.  */
  682.                 Border( &ce.chartwindow );
  683.  
  684.         }
  685.     }
  686.     PopTitle();
  687. }
  688.  
  689. /*  ClearData - Clears category and value data.
  690.  *
  691.  *  Params: fConfirm - flag specifying whether to query for confirmation
  692.  */
  693. void ClearData( BOOL fConfirm )
  694. {
  695.     char chResponse = 'Y';
  696.     int iCat;
  697.  
  698.     WrtForm( 18 );
  699.  
  700.     /* Query for confirmation.  */
  701.     if( fConfirm )
  702.         chResponse = InputCh( "Are you sure? ", "YN\x1b" );
  703.  
  704.     if( chResponse == 'Y' )
  705.     {
  706.  
  707.         /* Clear all relevant data.  */
  708.         for( iCat = 0; iCat < cCat; iCat++ )
  709.             aCat[iCat] = NULL;
  710.         cCat = 0;
  711.         cSeries = 0;
  712.     }
  713. }
  714.  
  715. /*  DataWindow - Geta data window information.
  716.  *
  717.  *  Params: None
  718.  */
  719. void DataWindow()
  720. {
  721.     int iChoice;
  722.  
  723.     PushTitle( pszDataWindow[0] );
  724.     while( (iChoice = Menu( pszDataWindow )) != ESCAPE )
  725.     {
  726.  
  727.         /* Get data window menu options.  */
  728.         switch( iChoice )
  729.         {
  730.  
  731.             case 1: 
  732.                 /* Query for background color.  */
  733.                 Help( "Enter a number in the range 0-15", co.InputColor );
  734.                 ce.datawindow.background =
  735.                     InputInt( "Background Color? ",
  736.                                ce.datawindow.background,
  737.                                0, 15 );
  738.                 break;
  739.  
  740.             case 2:
  741.                 /* Get border options.  */
  742.                 Border( &ce.datawindow );
  743.                 break;
  744.  
  745.         }
  746.     }
  747.     PopTitle();
  748. }
  749.  
  750. /*  DefaultData - Initializes default data for each kind of chart.
  751.  *
  752.  *  Params: iType - Chart type to be initialized
  753.  *          iStyle - Chart style
  754.  *          fClear - Signal to clear all defaults
  755.  */
  756. void DefaultData( short iType, short iStyle, BOOL fClear )
  757. {
  758.     int iCat, iValue, iSubValue, iSeries;
  759.  
  760.     /* Call default chart to clear old values.  */
  761.     if( fClear )
  762.         _pg_defaultchart( &ce, iType, iStyle );
  763.  
  764.     /* Initialize category titles.  */
  765.     cCat = 12;
  766.     for( iCat = 0; iCat < cCat; iCat++ )
  767.         aCat[iCat] = aMonths[iCat];
  768.  
  769.     switch( ce.charttype )
  770.     {
  771.  
  772.         /* Initialize data for each chart type.  */
  773.         case _PG_BARCHART:
  774.         
  775.             strcpy( ce.maintitle.title, "Orange Juice and Iced Tea Sales" );
  776.             cSeries = 2;
  777.             for( iSeries = 0; iSeries < cSeries; iSeries++ )
  778.             {
  779.                 aSeriesName[iSeries] = aSalesTitles[iSeries];
  780.                 acSeries[iSeries] = cCat;
  781.                 for( iValue = 0; iValue < cCat; iValue++ )
  782.                     aValue[iSeries][iValue]  = (float)aSales[iSeries][iValue];
  783.             }
  784.             break;
  785.  
  786.         case _PG_COLUMNCHART:
  787.        
  788.             strcpy( ce.maintitle.title, "Orange Juice Sales" );
  789.             cSeries = 1;
  790.             for( iSeries = 0; iSeries < cSeries; iSeries++ )
  791.             {
  792.                 aSeriesName[iSeries] = aSalesTitles[iSeries];
  793.                 acSeries[iSeries] = cCat;
  794.                 for( iValue = 0; iValue < cCat; iValue++ )
  795.                     aValue[iSeries][iValue]  = (float)aSales[iSeries][iValue];
  796.             }
  797.             break;
  798.  
  799.         case _PG_LINECHART:
  800.  
  801.             strcpy( ce.maintitle.title, "Beverage Sales" );
  802.             cSeries = 3;
  803.             for( iSeries = 0; iSeries < cSeries; iSeries++ )
  804.             {
  805.                 aSeriesName[iSeries] = aSalesTitles[iSeries];
  806.                 acSeries[iSeries] = cCat;
  807.                 for( iValue = 0; iValue < cCat; iValue++ )
  808.                     aValue[iSeries][iValue] = (float)aSales[iSeries][iValue];
  809.             }
  810.             break;
  811.  
  812.         case _PG_SCATTERCHART:
  813.  
  814.             strcpy( ce.maintitle.title,
  815.                     "Average Temperature Compared to Beverage Sales" );
  816.             /* ce.chartstyle = _PG_POINTONLY; */
  817.             cSeries = 4;
  818.  
  819.             aSeriesName[0] = aSalesTitles[I_TEA];
  820.             aSeriesName[2] = aSalesTitles[H_CHOC];
  821.             acSeries[0] = acSeries[1] = acSeries[2] = acSeries[3] = 12;
  822.             for( iValue = 0; iValue < 12; iValue++ )
  823.             {
  824.                 aValue[0][iValue]  = (float)aSales[I_TEA][iValue] ;
  825.                 aValue[1][iValue]  = (float)aSales[TEMPERATURE][iValue] ;
  826.                 aValue[2][iValue]  = (float)aSales[H_CHOC][iValue] ;
  827.                 aValue[3][iValue]  = (float)aSales[TEMPERATURE][iValue] ;
  828.             }
  829.             break;
  830.            
  831.         case _PG_PIECHART:
  832.         default:
  833.  
  834.             strcpy( ce.maintitle.title, "Iced Tea Sales" );
  835.             cCat = 4;
  836.             for( iCat = 0; iCat < cCat; iCat++ )
  837.                 aCat[iCat] = aQuarters[iCat];
  838.  
  839.             cSeries = 1;
  840.             aSeriesName[0] = aSalesTitles[I_TEA];
  841.             acSeries[0] = cCat;
  842.  
  843.             for( iValue = 0; iValue < cCat; iValue++ )
  844.             {
  845.                 aValue[0][iValue] = 0.0;
  846.                 for( iSubValue = 0; iSubValue < 3; iSubValue++ )
  847.                     aValue[0][iValue] += (float)aSales[I_TEA][iSubValue * iValue];
  848.             }
  849.             aExplode[3] = 1;
  850.             break;
  851.     }
  852. }
  853.  
  854. /*  Demo - Displays a series of sample charts.
  855.  *
  856.  *  Params: None
  857.  */
  858. void Demo()
  859. {
  860.     int  cValue;
  861.     palettetype palette_struct;
  862.  
  863.     /* Display the sample data in spreadsheet form. */
  864.     ShowSampleData();
  865.  
  866.     DefaultData( _PG_PIECHART, _PG_NOPERCENT, TRUE );
  867.  
  868.     /* Set video mode and draw charts. For each chart, set default
  869.      * data and modify any desired environment fields. If error,
  870.      * terminate demo.
  871.      */
  872.     _setvideomode( si.mode );
  873.  
  874.     cValue = 4;
  875.     strcpy( ce.subtitle.title, "Default Pie Chart" );
  876.     if( ViewChart() )
  877.         return;
  878.     else
  879.         _clearscreen( _GCLEARSCREEN );
  880.  
  881.     strcpy( ce.subtitle.title, "Customized Pie Chart" );
  882.     ce.chartstyle = _PG_PERCENT;
  883.     ce.legend.place = _PG_BOTTOM;
  884.     if (si.fColor)
  885.     {
  886.         ce.maintitle.titlecolor = ce.subtitle.titlecolor = 0;
  887.         ce.chartwindow.background = 1;
  888.         ce.datawindow.background = ce.legend.legendwindow.background = 6;
  889.         ce.legend.textcolor = 1;
  890.     }
  891.     if( ViewChart() )
  892.         return;
  893.     else
  894.         _clearscreen( _GCLEARSCREEN );
  895.  
  896.     cValue = 12;
  897.     DefaultData( _PG_BARCHART, _PG_PLAINBARS, TRUE );
  898.     strcpy( ce.subtitle.title, "Default Bar Chart" );
  899.     if( ViewChart() )
  900.         return;
  901.     else
  902.         _clearscreen( _GCLEARSCREEN );
  903.  
  904.     strcpy( ce.subtitle.title, "Customized Stacked Bar Chart" );
  905.     strcpy( ce.xaxis.axistitle.title, "Sales in Thousands" );
  906.     strcpy( ce.yaxis.axistitle.title, "Month" );
  907.     ce.chartstyle = _PG_STACKEDBARS;
  908.     ce.legend.place = _PG_RIGHT;
  909.     ce.xaxis.ticdecimals = 2;
  910.     if (si.fColor)
  911.     {
  912.         ce.maintitle.titlecolor = ce.subtitle.titlecolor = 12;
  913.         ce.chartwindow.background = 7;
  914.         ce.datawindow.background = 8;
  915.         ce.legend.textcolor = 0;
  916.         ce.legend.legendwindow.background = 8;
  917.         ce.legend.autosize = FALSE;
  918.         ce.legend.legendwindow.y1 = vc.numypixels - 85;
  919.         ce.legend.legendwindow.y2 = vc.numypixels - 45;
  920.     }
  921.     if( ViewChart() )
  922.         return;
  923.     else
  924.         _clearscreen( _GCLEARSCREEN );
  925.  
  926.     DefaultData( _PG_COLUMNCHART, _PG_PLAINBARS, TRUE );
  927.     strcpy( ce.subtitle.title, "Default Column Chart" );
  928.     if( ViewChart() )
  929.         return;
  930.     else
  931.         _clearscreen( _GCLEARSCREEN );
  932.  
  933.     strcpy( ce.subtitle.title, "Customized Column Chart" );
  934.     strcpy( ce.xaxis.axistitle.title, "Month" );
  935.     strcpy( ce.yaxis.axistitle.title, "Sales in Thousands" );
  936.     ce.legend.place = _PG_BOTTOM;
  937.     if (si.fColor)
  938.     {
  939.         ce.maintitle.titlecolor     = 0;
  940.         ce.subtitle.titlecolor     = 0;
  941.         ce.chartwindow.background = 8;
  942.         ce.datawindow.background = 2;
  943.         ce.legend.legendwindow.background = 10;
  944.     }
  945.     if( ViewChart() )
  946.         return;
  947.     else
  948.         _clearscreen( _GCLEARSCREEN );
  949.  
  950.     DefaultData( _PG_LINECHART, _PG_POINTANDLINE, TRUE );
  951.     strcpy( ce.subtitle.title, "Default Line Chart" );
  952.     if( ViewChart() )
  953.         return;
  954.     else
  955.         _clearscreen( _GCLEARSCREEN );
  956.  
  957.     strcpy( ce.subtitle.title, "Customized Line Chart" );
  958.     strcpy( ce.xaxis.axistitle.title, "Month" );
  959.     strcpy( ce.yaxis.axistitle.title, "Sales in Thousands" );
  960.     ce.legend.place = _PG_RIGHT;
  961.     if (si.fColor)
  962.     {
  963.         ce.maintitle.titlecolor = 1;
  964.         ce.subtitle.titlecolor = 1;
  965.         ce.chartwindow.background = 3;
  966.         ce.datawindow.background = 7;
  967.         ce.legend.legendwindow.background = 7;
  968.         ce.legend.autosize = FALSE;
  969.         ce.legend.legendwindow.y1 = vc.numypixels - 85;
  970.         ce.legend.legendwindow.y2 = vc.numypixels - 45;
  971.     }
  972.     if( ViewChart() )
  973.         return;
  974.     else
  975.         _clearscreen( _GCLEARSCREEN );
  976.  
  977.     DefaultData( _PG_SCATTERCHART, _PG_POINTONLY, TRUE );
  978.     strcpy( ce.subtitle.title, "Default Scatter Chart" );
  979.     if( ViewChart() )
  980.         return;
  981.     else
  982.         _clearscreen( _GCLEARSCREEN );
  983.  
  984.     cSeries = 4;
  985.     strcpy( ce.subtitle.title, "Customized Scatter Chart" );
  986.     strcpy( ce.xaxis.axistitle.title, "Sales in Thousands" );
  987.     strcpy( ce.yaxis.axistitle.title, "Average Temperature" );
  988.     ce.legend.place = _PG_RIGHT;
  989.     if (si.fColor)
  990.     {
  991.         ce.maintitle.titlecolor = 0;
  992.         ce.subtitle.titlecolor = 0;
  993.         ce.chartwindow.background = 4;
  994.         ce.datawindow.background = 8;
  995.         ce.legend.legendwindow.background = 8;
  996.         ce.legend.autosize = FALSE;
  997.         ce.legend.legendwindow.y1 = vc.numypixels - 85;
  998.         ce.legend.legendwindow.y2 = vc.numypixels - 45;
  999.     }
  1000.     if( ViewChart() )
  1001.         return;
  1002.     else
  1003.         _clearscreen( _GCLEARSCREEN );
  1004.  
  1005.     DefaultData( _PG_BARCHART, _PG_PERCENT, TRUE );
  1006. }
  1007.  
  1008. /*  FindVideoMode - Finds the "best" video mode for the adaptor in use.
  1009.  *
  1010.  *  Params: vc - structure of type struct videoconfig
  1011.  *
  1012.  *  Returns: Best mode
  1013.  */
  1014. int FindVideoMode( struct videoconfig vc )
  1015. {
  1016.     switch( vc.adapter )
  1017.     {
  1018.         case _CGA:
  1019.         case _OCGA:
  1020.             return _HRESBW;
  1021.         case _EGA:
  1022.         case _OEGA:
  1023.             return( vc.monitor == _MONO ) ? _ERESNOCOLOR : _ERESCOLOR;
  1024.         case _VGA:
  1025.         case _OVGA:
  1026.         case _MCGA:
  1027.             return _VRES16COLOR;
  1028.         case _HGC:
  1029.             return _HERCMONO;
  1030.         default:
  1031.             return _DEFAULTMODE;
  1032.     }
  1033. }
  1034.  
  1035. /*  FontOptions - Allows the user to modify the font used for display.
  1036.  *
  1037.  *  Params: None
  1038.  */
  1039.  
  1040. void FontOptions()
  1041. {
  1042.     int iChoice;
  1043.     int iTypeSize;
  1044.     int iFaceIndex;
  1045.     struct _fontinfo fd;
  1046.  
  1047.     /* Get menu choice and call appropriate axis Menu. */
  1048.     PushTitle( pszFontOpt[0] );
  1049.  
  1050.     while( (iChoice = Menu( pszFontOpt )) != ESCAPE )
  1051.     {
  1052.         /* Get the current font information. */
  1053.         _getfontinfo( &fd );
  1054.  
  1055.         switch( iChoice )
  1056.         {
  1057.             /* Change Typeface. */
  1058.             case 1:
  1059.                 ChangeTypeface();
  1060.                 break;
  1061.  
  1062.             /* Change Type Size. */
  1063.             case 2:
  1064.                 iTypeSize = InputInt( "Enter a type size. ", fd.pixheight,
  1065.                                          8, 128 );
  1066.  
  1067.                 for( iFaceIndex = 0; iFaceIndex < 6; ++iFaceIndex )
  1068.                     if( !strcmpi( fd.facename, pszTypeface[iFaceIndex + 1] ) )
  1069.                         break;
  1070.  
  1071.                 ChooseFont( iFaceIndex, iTypeSize );
  1072.                 break;
  1073.  
  1074.             default:
  1075.                 break;
  1076.         }
  1077.     }
  1078.     PopTitle();
  1079. }
  1080.  
  1081. /*  Initialize - Does various initialization tasks.
  1082.  *
  1083.  *  Params: None
  1084.  */
  1085. void Initialize( void )
  1086. {
  1087.     int iSeries, iValue;
  1088.  
  1089.     /* Initialize all value arrays to missing.  */
  1090.     for( iSeries = 0; iSeries < MAXSERIES; iSeries++ )
  1091.     {
  1092.  
  1093.         axValue[iSeries] = _PG_MISSINGVALUE;
  1094.         ayValue[iSeries] = _PG_MISSINGVALUE;
  1095.  
  1096.         for( iValue = 0; iValue < MAXVALUES; iValue++ )
  1097.             aValue[iSeries][iValue] = _PG_MISSINGVALUE;
  1098.  
  1099.         for( iValue = 0; iValue < MAXVALUES; iValue++ )
  1100.         {
  1101.             axValueMS[iSeries][iValue] = _PG_MISSINGVALUE;
  1102.             ayValueMS[iSeries][iValue] = _PG_MISSINGVALUE;
  1103.         }
  1104.     }
  1105.  
  1106.     /* Initialize zero sets. */
  1107.     cSeries = 0;
  1108.  
  1109.     /* Initialize default chart environment, screen mode, and data.  */
  1110.     _pg_initchart();
  1111.     _getvideoconfig( &vc );
  1112.  
  1113.     /* Find the best available mode for display.
  1114.      * Don't set 256 color, medium resolution (_MRES256COLOR).
  1115.      */
  1116.     si.mode = FindVideoMode( vc );
  1117.  
  1118.     if( si.mode == _TEXTMONO )
  1119.     {
  1120.         _clearscreen( _GCLEARSCREEN );
  1121.         _outtext( "No graphics available.  Can't run chart demo." );
  1122.         exit( 1 );
  1123.     }
  1124.  
  1125.     SetDisplayColors();
  1126.  
  1127.     SetGraphMode( si.mode );
  1128.     DefaultData( _PG_BARCHART, _PG_PLAINBARS, TRUE );
  1129.  
  1130.     _setvideomode( _DEFAULTMODE );
  1131.  
  1132.  
  1133. }
  1134.  
  1135. /*  Justify - Gets title justification option.
  1136.  *
  1137.  *  Params: Pointer to titletype variable
  1138.  */
  1139. void Justify( titletype *ptt )
  1140. {
  1141.     int iChoice;
  1142.  
  1143.     PushTitle( pszJustify[0] );
  1144.     iChoice = Menu( pszJustify );
  1145.     switch( iChoice )
  1146.     {
  1147.  
  1148.         /* Set justification.  */
  1149.         case 1:
  1150.         case 2:
  1151.         case 3:
  1152.             ptt->justify = iChoice;
  1153.     }
  1154.     PopTitle();
  1155. }
  1156.  
  1157. /*  Legend - Asks whether a legend is desired, and if so, gets
  1158.  *  legend options.
  1159.  *
  1160.  *  Params: None
  1161.  */
  1162. void Legend()
  1163. {
  1164.     int iChoice;
  1165.  
  1166.     /* Is legend desired?  */
  1167.     iChoice = BlankMenu( "Legend", "Legend", "No Legend" );
  1168.     switch( iChoice )
  1169.     {
  1170.         case 1:
  1171.             /* If legend, set legend flag and get options.  */
  1172.             ce.legend.legend = TRUE;
  1173.             PushTitle( pszLegendWindow[0] );
  1174.             do
  1175.             {
  1176.                 iChoice = Menu( pszLegendWindow );
  1177.                 switch( iChoice )
  1178.                 {
  1179.  
  1180.                     case 1:
  1181.                         /* Get legend place.  */
  1182.                         LegendPlace();
  1183.                         break;
  1184.  
  1185.                     case 2:
  1186.                         /* Query for legend color.  */
  1187.                         Help( "Enter a number in the range 0-15.", co.InputColor );
  1188.                         ce.legend.textcolor =
  1189.                             InputInt( "Text color? ",
  1190.                                        ce.legend.textcolor,
  1191.                                        0, 15 );
  1192.                         break;
  1193.  
  1194.                     case 3:
  1195.                         /* Get auto or manual sizing.  */
  1196.                         PushTitle( "Auto Legend" );
  1197.                         iChoice = Menu( pszAuto );
  1198.  
  1199.                         /* Set or clear the autosize flag. If manual
  1200.                          * sizing was selected, get legend size.
  1201.                          */
  1202.                         switch( iChoice )
  1203.                         {
  1204.                             case 1:
  1205.                                 ce.legend.autosize = TRUE;
  1206.                                 break;
  1207.  
  1208.                             case 2:
  1209.                                 ce.legend.autosize = FALSE;
  1210.                                 WindowSize( &ce.legend.legendwindow );
  1211.                         }
  1212.                         PopTitle();
  1213.                         break;
  1214.  
  1215.                     case 4:
  1216.                         /* Query for background color.  */
  1217.                         Help( "Type a number in the range 0-15.", co.InputColor );
  1218.                         ce.legend.legendwindow.background =
  1219.                             InputInt( "Background color? ",
  1220.                                        ce.legend.legendwindow.background,
  1221.                                        0, 15 );
  1222.                         break;
  1223.  
  1224.                     case 5:
  1225.                         /* Get border options for legend window.  */
  1226.                         Border( &ce.legend.legendwindow );
  1227.                 }
  1228.  
  1229.             } while( iChoice != ESCAPE );
  1230.             PopTitle();
  1231.             break;
  1232.  
  1233.         case 2:
  1234.             /* If no legend wanted, clear flag.  */
  1235.             ce.legend.legend = FALSE;
  1236.  
  1237.     }
  1238.     PopTitle();
  1239. }
  1240.  
  1241. /*  LegendPlace - Gets legend placement option.
  1242.  *
  1243.  *  Params: None
  1244.  */
  1245. void LegendPlace()
  1246. {
  1247.     int iChoice;
  1248.  
  1249.     /* Get legend placement.  */
  1250.     PushTitle( pszPlace[0] );
  1251.     iChoice = Menu( pszPlace );
  1252.     switch( iChoice )
  1253.     {
  1254.  
  1255.         case 1:
  1256.             ce.legend.place = _PG_RIGHT;
  1257.             break;
  1258.  
  1259.         case 2:
  1260.             ce.legend.place = _PG_BOTTOM;
  1261.             break;
  1262.  
  1263.         case 3:
  1264.             ce.legend.place = _PG_OVERLAY;
  1265.     }
  1266.     PopTitle();
  1267. }
  1268.  
  1269. /*  MainMenu - Manages the main menu.
  1270.  *
  1271.  *  Params: None
  1272.  */
  1273. void MainMenu( void )
  1274. {
  1275.     int iChoice;
  1276.     char chResponse = 'Y';
  1277.     char chVerify;
  1278.  
  1279.     PushTitle( pszMainMenu[0] );
  1280.     do
  1281.     {
  1282.         /* If the user selects Quit, iChoice will contain 6.  If the
  1283.          *   user presses ESCAPE, iChoice will be ESCAPE, which is
  1284.          *   equal to 27.  In any case, we can test both conditions
  1285.          *   by checking to see whether iChoice is less than 6.
  1286.          */
  1287.         while( (iChoice = Menu( pszMainMenu )) < 6 )
  1288.         {
  1289.             /* Get main menu selection.  */
  1290.             switch( iChoice )
  1291.             {
  1292.  
  1293.                 case 1:
  1294.                     /* Display demo charts.  */
  1295.                     Demo();
  1296.                     _setvideomode( _DEFAULTMODE );
  1297.                     break;
  1298.  
  1299.                 case 2:
  1300.                     /* Set graphics video mode, display current chart,
  1301.                      * and restore text video mode.
  1302.                      */
  1303.                     _setvideomode( si.mode );
  1304.                     ViewChart();
  1305.                     _setvideomode( _DEFAULTMODE );
  1306.                     break;
  1307.  
  1308.                 case 3:
  1309.                     /* Get chart type and style.  */
  1310.                     ChartType();
  1311.                     break;
  1312.  
  1313.                 case 4:
  1314.                     /* Get chart options.  */
  1315.                     ChartOptions();
  1316.                     break;
  1317.                 case 5:
  1318.                     /* Show chart data. */
  1319.                     ShowChartData();
  1320.                     break;
  1321.  
  1322.             }
  1323.  
  1324.         }
  1325.  
  1326.         /* If the user is trying to leave the program using the ESCAPE
  1327.          *   key, we must verify the choice.  This is done to prevent
  1328.          *   an eager typist from pressing ESCAPE one time too often
  1329.          *   and exiting at an unanticipated point.
  1330.          */
  1331.         if( iChoice == ESCAPE )
  1332.         {
  1333.             Help( "Press \"Q\" to Actually Quit", co.InputColor );
  1334.  
  1335.             putchar( BEEP );
  1336.             _settextposition( si.help - 1, 32 );
  1337.             chVerify = getch();
  1338.             if( tolower( chVerify ) != 'q' )
  1339.                 iChoice = 0;
  1340.             else
  1341.                 iChoice = 6;
  1342.         }
  1343.  
  1344.     } while( iChoice != 6 );
  1345.     PopTitle();
  1346. }
  1347.  
  1348. /*  ResetOptions - After confirmation, resets chart options to default.
  1349.  *
  1350.  *  Params: None
  1351.  */
  1352. void ResetOptions()
  1353. {
  1354.     char chResponse;
  1355.  
  1356.     /* Prompt for confirmation before setting default environment.  */
  1357.     ClrForm();
  1358.     Help( "Type  'Y' to reset all options, 'N' to keep them.", co.InputColor );
  1359.     chResponse = InputCh( "Are you sure? ", "YN\x1b" );
  1360.     if( chResponse == 'Y' )
  1361.         _pg_defaultchart( &ce, 1, 1 );
  1362.  
  1363. }
  1364.  
  1365. /*  ScreenMode - Gets a new screen mode.
  1366.  *
  1367.  *  Params: None
  1368.  */
  1369. void ScreenMode()
  1370. {
  1371.     int iMode, i;
  1372.     char szTmp[80], szHlp[80];
  1373.     static int iLegal[5][11] =
  1374.     {
  1375.         { 3, 4, 5, 6 },
  1376.         { 4, 4, 5, 6, 64 },
  1377.         { 4, 4, 5, 6, 19 },
  1378.         { 7, 4, 5, 6, 13, 14, 15, 16 },
  1379.         { 10, 4, 5, 6, 13, 14, 15, 16, 17, 18, 19 }
  1380.     };
  1381.     int iAdaptor;
  1382.  
  1383.     PushTitle( "Screen Mode" );
  1384.  
  1385.     /* Show appropriate help line for adaptor.  */
  1386.     switch( vc.adapter )
  1387.     {
  1388.         case _HGC:
  1389.             PopTitle();
  1390.             return;
  1391.         case _CGA:
  1392.             iAdaptor = 0;
  1393.             break;
  1394.         case _OCGA:
  1395.             iAdaptor = 1;
  1396.             break;
  1397.         case _MCGA:
  1398.             iAdaptor = 2;
  1399.             break;
  1400.         case _EGA:
  1401.         case _OEGA:
  1402.             if( vc.adapter == _MONO )
  1403.             {
  1404.                 PopTitle();
  1405.                 return;
  1406.             }
  1407.             else
  1408.                 iAdaptor = 3;
  1409.             break;
  1410.         case _VGA:
  1411.         case _OVGA:
  1412.             iAdaptor = 4;
  1413.             break;
  1414.     }
  1415.  
  1416.     /* Form the help line (which gives the choices legal for
  1417.      * the adaptor sensed in the user's machine).
  1418.      */
  1419.     for( iMode = 0, szHlp[0] = '\0'; iMode <= iLegal[iAdaptor][0]; ++iMode )
  1420.     {
  1421.         if( iMode == 0 )
  1422.             strcpy( szTmp, "Enter " );
  1423.         else if( iMode < iLegal[iAdaptor][0] )
  1424.             sprintf( szTmp, "%d, ", iLegal[iAdaptor][iMode] );
  1425.         else
  1426.             sprintf( szTmp, "or %d", iLegal[iAdaptor][iMode] );
  1427.         strcat( szHlp, szTmp );
  1428.     }
  1429.  
  1430.     WrtForm( 18 );
  1431.     Help( szHlp, co.InputColor );
  1432.  
  1433.     /* Query for screen mode. */
  1434.     for( ;; )
  1435.     {
  1436.         iMode = InputInt( "Screen Mode? ", si.mode, 1, 64 );
  1437.         for( i = 1; i <= iLegal[iAdaptor][0]; ++i ) /* Test legal values    */
  1438.             if( iMode == iLegal[iAdaptor][i] )      /* If a match is found  */
  1439.                 break;                              /* Terminate for loop   */
  1440.         if( iMode == iLegal[iAdaptor][i] )          /* If it's a match,     */
  1441.             break;                                  /* terminate do loop,   */
  1442.         else                                        /* otherwise BEEP, and  */
  1443.             putchar( BEEP );                        /* solicit correct data */
  1444.     }
  1445.  
  1446.     PopTitle();
  1447.     if( SetGraphMode( iMode ) )
  1448.         _setvideomode( _DEFAULTMODE );
  1449.     else
  1450.         ShowError( _PG_BADSCREENMODE );
  1451.  
  1452.     /* Force rescaling of the chart by resetting the window
  1453.      * rectangles for the chart and data windows to zero size.
  1454.      */
  1455.     ce.chartwindow.x1 = ce.chartwindow.x2 = ce.chartwindow.y1 =
  1456.         ce.chartwindow.y2 = 0;
  1457.     ce.datawindow = ce.chartwindow;
  1458. }
  1459.  
  1460. /*  SetGraphMode - Tests the specified graphics mode and sets the xMax
  1461.  *  and yMax values in the si (Screen Information) structure.
  1462.  *
  1463.  *  Params: mode number
  1464.  *
  1465.  *  Return: FALSE if mode invalid, TRUE if valid
  1466.  */
  1467. BOOL SetGraphMode(int mode)
  1468. {
  1469.     if (!_setvideomode( mode ) )
  1470.         return FALSE;
  1471.     else
  1472.     {
  1473.         _getvideoconfig ( &vc );
  1474.         if( !vc.numxpixels )
  1475.             return FALSE;
  1476.         si.xMax = vc.numxpixels;
  1477.         si.yMax = vc.numypixels;
  1478.         si.mode = mode;
  1479.  
  1480.         /* Set flag to indicate whether multiple colors are available.  */
  1481.         si.fColor = iscolor( mode );
  1482.  
  1483.         return TRUE;
  1484.     }
  1485. }
  1486.  
  1487. /*  ShowChartData - Displays the data in the chart environment.
  1488.  *
  1489.  *  Params: None
  1490.  */
  1491. void ShowChartData()
  1492. {
  1493.     int iRow = 2;
  1494.     static char *szContinue =
  1495.         "Press any key to continue, ESC to return to the menu.";
  1496.  
  1497.     _clearscreen( _GCLEARSCREEN );
  1498.     SprintAt( iRow++, 1, "short      charttype =  %d", ce.charttype );
  1499.     SprintAt( iRow++, 1, "short      chartstyle = %d", ce.chartstyle );
  1500.     SprintAt( iRow++, 1, "windowtype chartwindow =" );
  1501.     iRow = ShowWindowType( iRow, 1, ce.chartwindow );
  1502.     SprintAt( iRow++, 1, "windowtype datawindow =" );
  1503.     iRow = ShowWindowType( iRow, 1, ce.datawindow );
  1504.     SprintAt( ++iRow, 1, szContinue );
  1505.     if( getch() == ESCAPE )
  1506.         return;
  1507.  
  1508.     iRow = 2;
  1509.     _clearscreen( _GCLEARSCREEN );
  1510.     SprintAt( iRow++, 1, "titletype  maintitle =" );
  1511.     iRow = ShowTitleType( iRow, 1, ce.maintitle );
  1512.     SprintAt( iRow++, 1, "titletype   subtitle =" );
  1513.     iRow = ShowTitleType( iRow, 1, ce.subtitle );
  1514.     SprintAt( ++iRow, 1, szContinue );
  1515.     if( getch() == ESCAPE )
  1516.         return;
  1517.  
  1518.     iRow = 2;
  1519.     _clearscreen( _GCLEARSCREEN );
  1520.     SprintAt( iRow++, 1, "axistype       xaxis =" );
  1521.     iRow = ShowAxisType( iRow, 1, ce.xaxis );
  1522.     SprintAt( ++iRow, 1, szContinue );
  1523.     if( getch() == ESCAPE )
  1524.         return;
  1525.  
  1526.     iRow = 2;
  1527.     _clearscreen( _GCLEARSCREEN );
  1528.     SprintAt( iRow++, 1, "axistype       yaxis =" );
  1529.     iRow = ShowAxisType( iRow, 1, ce.yaxis );
  1530.     SprintAt( ++iRow, 1, szContinue );
  1531.     if( getch() == ESCAPE )
  1532.         return;
  1533.  
  1534.     iRow = 2;
  1535.     _clearscreen( _GCLEARSCREEN );
  1536.     SprintAt( iRow++, 1, "legendtype     legend =" );
  1537.     iRow = ShowLegendType( iRow, 1, ce.legend );
  1538.     SprintAt( ++iRow, 1, "Press any key to continue . . ." );
  1539.     getch();
  1540. }
  1541.  
  1542. /*  ShowAxisType - Displays data in a variable of type "axistype".
  1543.  *
  1544.  *  Params: iRow - Row at which to start
  1545.  *          iCol - Column from which to indent
  1546.  *          theAxis - Variable of type "axistype" to display
  1547.  *
  1548.  *  Return: Next available row
  1549.  */
  1550. int ShowAxisType( int iRow, int iCol, axistype theAxis )
  1551. {
  1552.     SprintAt( iRow++, iCol + 5, "short        .grid = %d", theAxis.grid );
  1553.     SprintAt( iRow++, iCol + 5, "short   .gridstyle = %d", theAxis.gridstyle );
  1554.     SprintAt( iRow++, iCol + 5, "titletype axistitle=" );
  1555.     iRow = ShowTitleType( iRow, iCol + 5, theAxis.axistitle );
  1556.     SprintAt( iRow++, iCol + 5, "short   .axiscolor = %d", theAxis.axiscolor );
  1557.     SprintAt( iRow++, iCol + 5, "short     .labeled = %s",
  1558.         (theAxis.labeled) ? "TRUE" : "FALSE" );
  1559.     SprintAt( iRow++, iCol + 5, "short   .rangetype = %d", theAxis.rangetype );
  1560.     SprintAt( iRow++, iCol + 5, "float     .logbase = %f", theAxis.logbase );
  1561.     SprintAt( iRow++, iCol + 5, "short   .autoscale = %s",
  1562.         (theAxis.autoscale) ? "TRUE" : "FALSE" );
  1563.     SprintAt( iRow++, iCol + 5, "float    .scalemin = %f", theAxis.scalemin );
  1564.     SprintAt( iRow++, iCol + 5, "float    .scalemax = %f", theAxis.scalemax );
  1565.     SprintAt( iRow++, iCol + 5, "float .scalefactor = %f", theAxis.scalefactor );
  1566.     iRow = ShowTitleType( iRow, iCol + 5, theAxis.scaletitle );
  1567.     SprintAt( iRow++, iCol + 5, "float  .ticinterval = %f", theAxis.ticinterval );
  1568.     SprintAt( iRow++, iCol + 5, "short    .ticformat = %d", theAxis.ticformat );
  1569.     SprintAt( iRow++, iCol + 5, "short  .ticdecimals = %d", theAxis.ticdecimals );
  1570.  
  1571.     return iRow;
  1572. }
  1573.  
  1574. /*  ShowLegendType - Displays data in a variable of type "legendtype".
  1575.  *
  1576.  *  Params: iRow - Row at which to start
  1577.  *          iCol - Column from which to indent
  1578.  *          theLegend - Variable of type "legendtype" to display
  1579.  *
  1580.  *  Return: Next available row
  1581.  */
  1582. int ShowLegendType( int iRow, int iCol, legendtype theLegend )
  1583. {
  1584.     SprintAt( iRow++, iCol + 5, "short      .legend = %s",
  1585.               (theLegend.legend) ? "TRUE" : "FALSE" );
  1586.     SprintAt( iRow++, iCol + 5, "short       .place = %d", theLegend.place );
  1587.     SprintAt( iRow++, iCol + 5, "short   .textcolor = %d", theLegend.textcolor );
  1588.     SprintAt( iRow++, iCol + 5, "short    .autosize = %d", theLegend.autosize );
  1589.     SprintAt( iRow++, iCol + 5, "windowtype legendwindow =" );
  1590.     iRow = ShowWindowType( iRow, iCol + 5, theLegend.legendwindow );
  1591.  
  1592.     return iRow;
  1593. }
  1594.  
  1595. /*  ShowSampleData - Displays the sample data for the demo.
  1596.  *
  1597.  *  Params: None
  1598.  */
  1599. void ShowSampleData()
  1600. {
  1601.     int  iCat, y, iSeries, iValue;
  1602.     char szTmp[80];
  1603.  
  1604.     /* Display data in table format. */
  1605.     _clearscreen( _GCLEARSCREEN );
  1606.     PrintAt( 1, 40 - strlen(szTmp) / 2, "Data in Table Format", -1L );
  1607.  
  1608.     /* Write titles and draw separator line. */
  1609.     y = 3;
  1610.     for( iCat = 1; iCat <= 12; iCat++ )
  1611.     PrintAt( y, iCat * 6, aMonths[iCat - 1], -1L );
  1612.  
  1613.     memset( szTmp, '-', 69 );
  1614.     szTmp[69] = 0;
  1615.     PrintAt( ++y, 6, szTmp, -1L );
  1616.  
  1617.     /* Write data. */
  1618.     for( iSeries = 1; iSeries <= 3; iSeries++ )
  1619.     {
  1620.         PrintAt( y += 2, 4, aSalesTitles[iSeries - 1], -1L );
  1621.         y += 2;
  1622.         for( iValue = 1; iValue <= 12; iValue++ )
  1623.         {
  1624.             sprintf( szTmp, "%#3.2f", aSales[iSeries - 1][iValue - 1] );
  1625.             PrintAt( y, iValue * 6, (char far *)szTmp, -1L );
  1626.         }
  1627.     }
  1628.     PrintAt( y += 2, 4, TempTitle, -1L );
  1629.     y += 2;
  1630.     for( iValue = 1; iValue <= 12; iValue++ )
  1631.     {
  1632.         sprintf( szTmp, "%#3.1f", aTemperature[iValue - 1] );
  1633.         PrintAt( y, iValue * 6, szTmp, -1L );
  1634.     }
  1635.  
  1636.     PrintAt( y += 2, 1, "Press any key to continue . . .", -1L );
  1637.     getche();
  1638. }
  1639.  
  1640. /*  ShowTitleType - Displays data in a variable of type "titletype".
  1641.  *
  1642.  *  Params: iRow - Row at which to start
  1643.  *          iCol - Column from which to indent
  1644.  *          theTitle - Variable of type "titletype" to display
  1645.  *
  1646.  *  Return: Next available row
  1647.  */
  1648. int ShowTitleType( int iRow, int iCol, titletype theTitle )
  1649. {
  1650.     SprintAt( iRow++, iCol + 5, "char    .title[%d] = \"%s\"", _PG_TITLELEN,
  1651.                  theTitle.title );
  1652.     SprintAt( iRow++, iCol + 5, "short  .titlecolor = %d", theTitle.titlecolor );
  1653.     SprintAt( iRow++, iCol + 5, "short     .justify = %d", theTitle.justify );
  1654.  
  1655.     return iRow;
  1656. }
  1657.  
  1658. /*  ShowWindowType - Displays data in a variable of type "windowtype".
  1659.  *
  1660.  *  Params: iRow - Row at which to start
  1661.  *          iCol - Column from which to indent
  1662.  *          theWindow - Variable of type "windowtype" to display
  1663.  *
  1664.  *  Return: Next available row
  1665.  */
  1666. int ShowWindowType( int iRow, int iCol, windowtype theWindow )
  1667. {
  1668.     SprintAt( iRow++, iCol + 5, "short          .x1 = %d", theWindow.x1 );
  1669.     SprintAt( iRow++, iCol + 5, "short          .y1 = %d", theWindow.y1 );
  1670.     SprintAt( iRow++, iCol + 5, "short          .x2 = %d", theWindow.x2 );
  1671.     SprintAt( iRow++, iCol + 5, "short          .y2 = %d", theWindow.y2 );
  1672.     SprintAt( iRow++, iCol + 5, "short      .border = %d", theWindow.border );
  1673.     SprintAt( iRow++, iCol + 5, "short  .background = %d", theWindow.background );
  1674.     SprintAt( iRow++, iCol + 5, "short .borderstyle = %d", theWindow.borderstyle );
  1675.     SprintAt( iRow++, iCol + 5, "short .bordercolor = %d", theWindow.bordercolor );
  1676.  
  1677.     return iRow;
  1678. }
  1679.  
  1680. /*  ShowError - Displays error message for one of the chart library
  1681.  *  errors.
  1682.  *
  1683.  *  Params: iErr - Error number
  1684.  */
  1685. void ShowError( int iErr )
  1686. {
  1687.     char szTmp[50];
  1688.  
  1689.     /* Change to text screen.  */
  1690.     _setvideomode( _DEFAULTMODE );
  1691.  
  1692.     /* Select the error text.  */
  1693.     switch( iErr )
  1694.     {
  1695.         case _PG_NOTINITIALIZED:
  1696.             strcpy( szTmp, "Chart Library Not Initialized" );
  1697.             break;
  1698.         case _PG_BADSCREENMODE:
  1699.             strcpy( szTmp, "Invalid Screen Mode" );
  1700.             break;
  1701.         case _PG_BADCHARTTYPE:
  1702.             strcpy( szTmp, "Invalid Chart Type" );
  1703.             break;
  1704.         case _PG_BADCHARTSTYLE:
  1705.             strcpy( szTmp, "Invalid Chart Style" );
  1706.             break;
  1707.         case _PG_BADLEGENDWINDOW:
  1708.             strcpy( szTmp, "Invalid Legend Window" );
  1709.             break;
  1710.         case _PG_BADDATAWINDOW:
  1711.             strcpy( szTmp, "No Room for Data window" );
  1712.             break;
  1713.         case _PG_BADCHARTWINDOW:
  1714.             strcpy( szTmp, "Invalid Chart window coordinates" );
  1715.             break;
  1716.         case _PG_NOMEMORY:
  1717.             strcpy( szTmp, "Not Enough Memory for Data Arrays" );
  1718.             break;
  1719.         case _PG_BADLOGBASE:
  1720.             strcpy( szTmp, "X or Y log base <= 0" );
  1721.             break;
  1722.         case _PG_BADSCALEFACTOR:
  1723.             strcpy( szTmp, "X or Y scale factor = 0" );
  1724.             break;
  1725.         case _PG_TOOSMALLN:
  1726.             strcpy( szTmp, "Too few data values" );
  1727.             break;
  1728.         case _PG_TOOFEWSERIES:
  1729.             strcpy( szTmp, "No data series specified" );
  1730.             break;
  1731.         default:
  1732.             strcpy( szTmp, "Unknown error" );
  1733.     }
  1734.  
  1735.     ErrorMsg( szTmp );
  1736. }
  1737.  
  1738. /*  TitleOpt - Gets title options.
  1739.  *
  1740.  *  Params: ptt - Pointer to titletype variable
  1741.  */
  1742. void TitleOpt( titletype *ptt )
  1743. {
  1744.     int iChoice;
  1745.  
  1746.     PushTitle( pszTitleOpt[0] );
  1747.     do
  1748.     {
  1749.         iChoice = Menu( pszTitleOpt );
  1750.         switch( iChoice )
  1751.         {
  1752.  
  1753.             case 1: 
  1754.                 /* Query for title text.  */
  1755.                 Help( "70 characters maximum length.", co.InputColor );
  1756.                 InputStr( "Enter Text: ", ptt->title );
  1757.                 break;
  1758.  
  1759.             case 2: 
  1760.                 /* Query for title color color.  */
  1761.                 Help( "Enter a number in the range 0-15.", co.InputColor );
  1762.                 ptt->titlecolor =
  1763.                     InputInt( "Title Color? ", ptt->titlecolor, 0, 15 );
  1764.                 break;
  1765.  
  1766.             case 3:
  1767.                 /* Get justify option.  */
  1768.                 Justify( ptt );
  1769.         }
  1770.         ClrHelp();
  1771.  
  1772.     } while( iChoice != ESCAPE );
  1773.     PopTitle();
  1774. }
  1775.  
  1776. /*  Titles - Manages Main and Sub title menus.
  1777.  *
  1778.  *  Params: None
  1779.  */
  1780. void Titles()
  1781. {
  1782.     int iChoice;
  1783.  
  1784.     PushTitle( pszTitles[0] );
  1785.     do
  1786.     {
  1787.         iChoice = Menu( pszTitles );
  1788.         switch( iChoice )
  1789.         {
  1790.  
  1791.             case 1:
  1792.                 /* Fix menu title and get options for main title.  */
  1793.                 pszTitleOpt[0] = "MainTitle";
  1794.                 TitleOpt( &ce.maintitle );
  1795.                 break;
  1796.  
  1797.             case 2:
  1798.                 /* Fix menu title and get options for subtitle.  */
  1799.                 pszTitleOpt[0] = "Sub Title";
  1800.                 TitleOpt( &ce.subtitle );
  1801.         }
  1802.     } while( iChoice != ESCAPE );
  1803.     PopTitle();
  1804. }
  1805.  
  1806. /*  ViewChart - Draws the current chart.
  1807.  *
  1808.  *  Params: None
  1809.  */
  1810. int ViewChart()
  1811. {
  1812.     int cValue, iValue, iSeries, iErr;
  1813.  
  1814.     /* Make sure some data exists.  */
  1815.     if( cSeries <= 0 )
  1816.     {
  1817.         fDefault = TRUE;
  1818.         DefaultData( ce.charttype, ce.chartstyle, FALSE );
  1819.     }
  1820.  
  1821.     /* Find the longest series.  */
  1822.     cValue = 0;
  1823.     for( iSeries = 0; iSeries < cSeries; iSeries++ )
  1824.         if( acSeries[iSeries] > cValue )
  1825.             cValue = acSeries[iSeries];
  1826.  
  1827.     _setvideomode( si.mode );
  1828.  
  1829.  
  1830.     /* Process depending on the type of chart.  */
  1831.     switch( ce.charttype )
  1832.     {
  1833.  
  1834.         case _PG_PIECHART:
  1835.         case _PG_BARCHART:
  1836.         case _PG_COLUMNCHART:
  1837.         case _PG_LINECHART:
  1838.  
  1839.             /* Initialize data and draw pie chart or single-series bar,
  1840.              * column, or line chart.
  1841.              */
  1842.             if( (cSeries == 1) ||( ce.charttype == _PG_PIECHART) )
  1843.             {
  1844.  
  1845.                 /* Transfer data into a single-dimension array.  */
  1846.                 for( iValue = 0; iValue < cValue; iValue++ )
  1847.                    axValue[iValue] = aValue[0][iValue];
  1848.  
  1849.                 /* Draw chart.  */
  1850.                 if( ce.charttype == _PG_PIECHART )
  1851.                     iErr = _pg_chartpie( &ce, aCat, axValue,
  1852.                                          aExplode, cValue );
  1853.                 else
  1854.                     iErr = _pg_chart( &ce, aCat, axValue, cValue );
  1855.             }
  1856.             /* If multiple-series, then data is OK. Just draw chart.  */
  1857.             else
  1858.                 iErr = _pg_chartms( &ce, aCat, (float far *)aValue,
  1859.                                     cSeries, cValue, cValue, aSeriesName );
  1860.             break;
  1861.  
  1862.         case _PG_SCATTERCHART:
  1863.  
  1864.             /* Make sure there are enough data sets.  */
  1865.             if( cSeries == 1 )
  1866.             {
  1867.                 _setvideomode( _DEFAULTMODE );
  1868.                 si.help = 10;
  1869.                 ErrorMsg( "Too few value data columns for scatter chart." );
  1870.                 return 1;
  1871.  
  1872.             }
  1873.             /* If it's a single-series scatter, transfer data to one-
  1874.              * dimensional arrays and make chart call.
  1875.              */
  1876.             else if( cSeries == 2 )
  1877.             {
  1878.                 for( iValue = 0; iValue < cValue; iValue++ )
  1879.                 {
  1880.                     axValue[iValue] = aValue[0][iValue];
  1881.                     ayValue[iValue] = aValue[1][iValue];
  1882.                 }
  1883.                 cSeries = 1;
  1884.                 iErr = _pg_chartscatter( &ce, axValue, ayValue, cValue );
  1885.  
  1886.             }
  1887.             /* If it's a multiple-series scatter, transfer odd columns to
  1888.              * X-axis data array and even columns to Y-axis array and make
  1889.              * chart call.
  1890.              */
  1891.             else
  1892.             {
  1893.  
  1894.                 for( iSeries = 1; iSeries < cSeries; iSeries += 2 )
  1895.                 {
  1896.                     aSeriesName[iSeries / 2] = aSeriesName[iSeries - 1];
  1897.                     for( iValue = 0; iValue < cValue; iValue++ )
  1898.                     {
  1899.                         axValueMS[iSeries / 2][iValue] =
  1900.                             aValue[iSeries - 1][iValue];
  1901.                         ayValueMS[iSeries / 2][iValue] =
  1902.                             aValue[iSeries][iValue];
  1903.                     }
  1904.                 }
  1905.                 cSeries /= 2;
  1906.  
  1907.                 iErr = _pg_chartscatterms( &ce, (float far *)axValueMS,
  1908.                                            (float far *)ayValueMS,
  1909.                                            cSeries, cValue, cValue,
  1910.                                            aSeriesName );
  1911.             }
  1912.     }
  1913.  
  1914.     if( !fDefault )
  1915.         ClearData( FALSE );
  1916.  
  1917.     /* If error, show it, else wait for keypress with chart on screen.  */
  1918.     if( iErr )
  1919.     {
  1920.         ShowError( iErr );
  1921.         return iErr;
  1922.     }
  1923.     else
  1924.         return ( getch() == ESCAPE );   /* ESCAPE means stop demo */
  1925. }
  1926.  
  1927. /*  Windows - Selects chart or data window, and gets options for either.
  1928.  *
  1929.  *  Params: None
  1930.  */
  1931. void Windows()
  1932. {
  1933.     int iChoice;
  1934.  
  1935.     PushTitle( pszWindows[0] );
  1936.     do
  1937.     {
  1938.  
  1939.         /* Select window and get options for it.  */
  1940.         iChoice = Menu( pszWindows );
  1941.         switch( iChoice )
  1942.         {
  1943.  
  1944.             case 1:
  1945.                 ChartWindow();
  1946.                 break;
  1947.  
  1948.             case 2:
  1949.                 DataWindow();
  1950.  
  1951.         }
  1952.     } while( iChoice != ESCAPE );
  1953.     PopTitle();
  1954. }
  1955.  
  1956. /*  WindowSize - Gets coordinates for window location and size.
  1957.  *
  1958.  *  Params: pwt - pointer to windowtype variable
  1959.  */
  1960. void WindowSize( windowtype *pwt )
  1961. {
  1962.     int iChoice;
  1963.  
  1964.     /* Get window size settings.  */
  1965.     PushTitle( pszSize[0] );
  1966.     do
  1967.     {
  1968.         /* Query for top, bottom, left, or right of window.  */
  1969.         iChoice = Menu( pszSize );
  1970.         switch( iChoice )
  1971.         {
  1972.  
  1973.             case 1:
  1974.                 Help( "Enter window top in pixels.", co.InputColor );
  1975.                 pwt->y1 = InputInt( "Top? ", pwt->y1, 0, si.yMax );
  1976.                 break;
  1977.  
  1978.             case 2:
  1979.                 Help( "Enter window Left in pixels.", co.InputColor );
  1980.                 pwt->x1 = InputInt( "Left? ", pwt->x1, 0, si.xMax );
  1981.                 break;
  1982.  
  1983.             case 3:
  1984.                 Help( "Enter window bottom in pixels.", co.InputColor );
  1985.                 pwt->y2 = InputInt( "Bottom? ", pwt->y2, 0, si.yMax );
  1986.                 break;
  1987.  
  1988.             case 4:
  1989.                 Help( "Enter window right in pixels.", co.InputColor );
  1990.                 pwt->x2 = InputInt( "Right? ", pwt->x2, 0, si.xMax );
  1991.         }
  1992.     } while( iChoice != ESCAPE );
  1993.     PopTitle();
  1994. }
  1995.