home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c040 / 1.ddi / SAMPLES / CHRTDEMO.C$ / CHRTDEMO.bin
Encoding:
Text File  |  1990-02-27  |  33.0 KB  |  1,103 lines

  1. /* CHRTDEMO.C - Presentation graphics demonstration program.
  2.  *
  3.  * If GRAPHICS.LIB and PGCHART.LIB were not included in your run-time
  4.  * libraries during setup, you must you must add them to the CHRTDEMO.MAK
  5.  * program list or give them on the QCL command line.
  6.  */
  7.  
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10. #include <conio.h>
  11. #include <string.h>
  12. #include <graph.h>
  13. #include <pgchart.h>
  14. #include "chrtdemo.h"
  15.  
  16. /* Structures for system configuration and chart environment. */
  17. struct videoconfig vc;
  18. chartenv ce;
  19.  
  20. /* Category variables.  */
  21. short cCat;
  22. char _far *aCat[MAXVALUES];
  23.  
  24. /* Series variables.  */
  25. short cSeries;
  26. short _far acSeries[MAXSERIES];
  27. char _far *aSeriesName[MAXSERIES];
  28.  
  29. /* Temporary holding array for all data. Data values for multi-series
  30.  * bar, column, and line charts remain here. Data for other kinds of
  31.  * charts are transferred to the arrays below.
  32.  */
  33. float _far aValue[MAXSERIES][MAXVALUES];
  34.  
  35. /* Data values for single-series charts. First array is used for
  36.  * bar, column, line, and pie. First and second are both used for
  37.  * single-series scatter.
  38.  */
  39. float _far axValue[MAXVALUES];
  40. float _far ayValue[MAXVALUES];
  41.  
  42. /* Data values for multi-series scatter charts.  */
  43. float _far axValueMS[MAXVALUES][MAXVALUES];
  44. float _far ayValueMS[MAXVALUES][MAXVALUES];
  45.  
  46. /* Exploded flags for pie chart.  */
  47. short _far aExplode[MAXVALUES];
  48.  
  49. /* Variable used to track control and screen position.  */
  50. struct SCREENINFO si;
  51.  
  52. /* Colors of menus and prompts. */
  53. struct tagColor co;
  54.  
  55. /* Flags to indicate whether to use imported or default data.  */
  56. BOOL fDefault = TRUE;
  57.  
  58. /* Arrays of strings used by the Menu function. The first string is the
  59.  * menu title. The next non-null strings are the menu selections. A null
  60.  * string indicates the end of the list.
  61.  */
  62. char *pszChartOpt[] =
  63.     { "Options", "Screen Mode", "Windows", "Titles",
  64.       "Axis (X and Y)", "Legend", "Fonts", "Reset", "" };
  65.  
  66. char *pszChartType[] =
  67.     { "Type", "Bar", "Column", "Line", "Scatter", "Pie", "" };
  68.  
  69. char *pszMainMenu[] =
  70.     { "Main Menu", "Demo", "View Chart", "Chart Type", "Options",
  71.       "Show Chart Data", "Quit", "" };
  72.  
  73. /* Sample data.  */
  74. #define O_JUICE 0
  75. #define I_TEA   1
  76. #define H_CHOC  2
  77. #define TEMPERATURE  3
  78.  
  79. char _far *aQuarters[] =
  80.     { "First", "Second", "Third", "Fourth" };
  81.  
  82. char _far *aMonths[] =
  83.     { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  84.       "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
  85.  
  86. float _far aSales[3][12] =
  87. {
  88.     {  3.6F,  3.2F,  3.3F,  3.4F,  3.1F,  2.9F,
  89.        3.0F,  3.6F,  3.2F,  3.3F,  3.5F,  3.9F },
  90.     {  1.0F,  1.3F,  1.4F,  1.7F,  2.2F,  2.9F,
  91.        2.9F,  3.1F,  2.6F,  1.8F,  1.1F,  1.2F },
  92.     {  2.4F,  2.3F,  2.0F,  1.6F,  1.3F,  1.0F,
  93.        0.9F,  0.8F,  1.1F,  1.4F,  1.9F,  2.5F }
  94. };
  95.   
  96. float _far aTemperature[12] =
  97.     {  2.9F,  3.2F,  3.9F,  4.8F,  6.0F,  6.5F,
  98.        7.0F,  7.2F,  6.0F,  4.7F,  4.1F,  3.0F };
  99.  
  100. char _far *aSalesTitles[] =
  101.     { "Orange Juice Sales", "Iced Tea Sales", "Hot Chocolate Sales" };
  102.  
  103. char *TempTitle = "Average Temperature";
  104.  
  105. int main()
  106. {
  107.     Initialize();
  108.     MainMenu();
  109.  
  110.     /* Reset the video mode and screen colors prior to leaving. */
  111.     _setvideomode( _DEFAULTMODE );
  112.     _settextcolor( co.InfoColor );
  113.     _clearscreen( _GCLEARSCREEN );
  114.  
  115.     return 0;
  116. }
  117.  
  118. /*  ChartOptions - Gets chart options.
  119.  *
  120.  *  Params: None
  121.  */
  122. void ChartOptions()
  123. {
  124.     int iChoice;
  125.  
  126.     PushTitle( pszChartOpt[0] );
  127.     while( (iChoice = Menu( pszChartOpt )) != ESCAPE )
  128.     {
  129.  
  130.         /* Get chart options.  */
  131.         switch( iChoice )
  132.         {
  133.  
  134.             /* Branch to the appropriate menu.  */
  135.             case 1:
  136.                 ScreenMode();
  137.                 break;
  138.  
  139.             case 2:
  140.                 Windows();
  141.                 break;
  142.  
  143.             case 3:
  144.                 Titles();
  145.                 break;
  146.  
  147.             case 4:
  148.                 Axes();
  149.                 break;
  150.  
  151.             case 5:
  152.                 Legend();
  153.                 break;
  154.  
  155.             case 6:
  156.                 FontOptions();
  157.                 break;
  158.  
  159.             case 7:
  160.                 ResetOptions();
  161.                 break;
  162.  
  163.         }
  164.     }
  165.     PopTitle();
  166. }
  167.  
  168. /*  ChartType - Gets chart type.
  169.  *
  170.  *  Params: None
  171.  */
  172. void ChartType()
  173. {
  174.     int iChoice;
  175.  
  176.     /* Get chart type.  */
  177.     PushTitle( pszChartType[0] );
  178.     iChoice = Menu( pszChartType );
  179.  
  180.     if( iChoice != ESCAPE )
  181.     {
  182.         /* Set the chart type, and get the chart style.  */
  183.         ce.charttype = iChoice;
  184.         switch( iChoice )
  185.         {
  186.  
  187.             case 1:
  188.             case 2:
  189.                 iChoice = BlankMenu( "Style", "Plain Bars", "Stacked Bars" );
  190.                 break;
  191.  
  192.             case 3:
  193.             case 4:
  194.                 iChoice = BlankMenu( "Style", "Lines-Points", "Points Only" );
  195.                 break;
  196.  
  197.             case 5:
  198.                 iChoice = BlankMenu( "Style", "Percent", "No Percent" );
  199.         }
  200.  
  201.         if( iChoice != ESCAPE)
  202.             ce.chartstyle = iChoice;
  203.  
  204.         /* Set default data without changing environment defaults.  */
  205.         DefaultData( ce.charttype, ce.chartstyle, FALSE );
  206.         PopTitle();
  207.     }
  208.     PopTitle();
  209. }
  210.  
  211. /*  ClearData - Clears category and value data.
  212.  *
  213.  *  Params: fConfirm - flag specifying whether to query for confirmation
  214.  */
  215. void ClearData( BOOL fConfirm )
  216. {
  217.     char chResponse = 'Y';
  218.     int iCat;
  219.  
  220.     WrtForm( 18 );
  221.  
  222.     /* Query for confirmation.  */
  223.     if( fConfirm )
  224.         chResponse = InputCh( "Are you sure? ", "YN\x1b" );
  225.  
  226.     if( chResponse == 'Y' )
  227.     {
  228.  
  229.         /* Clear all relevant data.  */
  230.         for( iCat = 0; iCat < cCat; iCat++ )
  231.             aCat[iCat] = NULL;
  232.         cCat = 0;
  233.         cSeries = 0;
  234.     }
  235. }
  236.  
  237. /*  DefaultData - Initializes default data for each kind of chart.
  238.  *
  239.  *  Params: iType - Chart type to be initialized
  240.  *          iStyle - Chart style
  241.  *          fClear - Signal to clear all defaults
  242.  */
  243. void DefaultData( short iType, short iStyle, BOOL fClear )
  244. {
  245.     int iCat, iValue, iSubValue, iSeries;
  246.  
  247.     /* Call default chart to clear old values.  */
  248.     if( fClear )
  249.         _pg_defaultchart( &ce, iType, iStyle );
  250.  
  251.     /* Initialize category titles.  */
  252.     cCat = 12;
  253.     for( iCat = 0; iCat < cCat; iCat++ )
  254.         aCat[iCat] = aMonths[iCat];
  255.  
  256.     switch( ce.charttype )
  257.     {
  258.  
  259.         /* Initialize data for each chart type.  */
  260.         case _PG_BARCHART:
  261.         
  262.             strcpy( ce.maintitle.title, "Orange Juice and Iced Tea Sales" );
  263.             cSeries = 2;
  264.             for( iSeries = 0; iSeries < cSeries; iSeries++ )
  265.             {
  266.                 aSeriesName[iSeries] = aSalesTitles[iSeries];
  267.                 acSeries[iSeries] = cCat;
  268.                 for( iValue = 0; iValue < cCat; iValue++ )
  269.                     aValue[iSeries][iValue]  = (float)aSales[iSeries][iValue];
  270.             }
  271.             break;
  272.  
  273.         case _PG_COLUMNCHART:
  274.        
  275.             strcpy( ce.maintitle.title, "Orange Juice Sales" );
  276.             cSeries = 1;
  277.             for( iSeries = 0; iSeries < cSeries; iSeries++ )
  278.             {
  279.                 aSeriesName[iSeries] = aSalesTitles[iSeries];
  280.                 acSeries[iSeries] = cCat;
  281.                 for( iValue = 0; iValue < cCat; iValue++ )
  282.                     aValue[iSeries][iValue]  = (float)aSales[iSeries][iValue];
  283.             }
  284.             break;
  285.  
  286.         case _PG_LINECHART:
  287.  
  288.             strcpy( ce.maintitle.title, "Beverage Sales" );
  289.             cSeries = 3;
  290.             for( iSeries = 0; iSeries < cSeries; iSeries++ )
  291.             {
  292.                 aSeriesName[iSeries] = aSalesTitles[iSeries];
  293.                 acSeries[iSeries] = cCat;
  294.                 for( iValue = 0; iValue < cCat; iValue++ )
  295.                     aValue[iSeries][iValue] = (float)aSales[iSeries][iValue];
  296.             }
  297.             break;
  298.  
  299.         case _PG_SCATTERCHART:
  300.  
  301.             strcpy( ce.maintitle.title,
  302.                     "Average Temperature Compared to Beverage Sales" );
  303.             /* ce.chartstyle = _PG_POINTONLY; */
  304.             cSeries = 4;
  305.  
  306.             aSeriesName[0] = aSalesTitles[I_TEA];
  307.             aSeriesName[2] = aSalesTitles[H_CHOC];
  308.             acSeries[0] = acSeries[1] = acSeries[2] = acSeries[3] = 12;
  309.             for( iValue = 0; iValue < 12; iValue++ )
  310.             {
  311.                 aValue[0][iValue]  = (float)aSales[I_TEA][iValue] ;
  312.                 aValue[1][iValue]  = (float)aSales[TEMPERATURE][iValue] ;
  313.                 aValue[2][iValue]  = (float)aSales[H_CHOC][iValue] ;
  314.                 aValue[3][iValue]  = (float)aSales[TEMPERATURE][iValue] ;
  315.             }
  316.             break;
  317.            
  318.         case _PG_PIECHART:
  319.         default:
  320.  
  321.             strcpy( ce.maintitle.title, "Iced Tea Sales" );
  322.             cCat = 4;
  323.             for( iCat = 0; iCat < cCat; iCat++ )
  324.                 aCat[iCat] = aQuarters[iCat];
  325.  
  326.             cSeries = 1;
  327.             aSeriesName[0] = aSalesTitles[I_TEA];
  328.             acSeries[0] = cCat;
  329.  
  330.             for( iValue = 0; iValue < cCat; iValue++ )
  331.             {
  332.                 aValue[0][iValue] = 0.0;
  333.                 for( iSubValue = 0; iSubValue < 3; iSubValue++ )
  334.                     aValue[0][iValue] += (float)aSales[I_TEA][iSubValue * iValue];
  335.             }
  336.             aExplode[3] = 1;
  337.             break;
  338.     }
  339. }
  340.  
  341. /*  Demo - Displays a series of sample charts.
  342.  *
  343.  *  Params: None
  344.  */
  345. void Demo()
  346. {
  347.     int  cValue;
  348.     palettetype palette_struct;
  349.  
  350.     /* Display the sample data in spreadsheet form. */
  351.     ShowSampleData();
  352.  
  353.     DefaultData( _PG_PIECHART, _PG_NOPERCENT, TRUE );
  354.  
  355.     /* Set video mode and draw charts. For each chart, set default
  356.      * data and modify any desired environment fields. If error,
  357.      * terminate demo.
  358.      */
  359.     _setvideomode( si.mode );
  360.  
  361.     cValue = 4;
  362.     strcpy( ce.subtitle.title, "Default Pie Chart" );
  363.     if( ViewChart() )
  364.         return;
  365.     else
  366.         _clearscreen( _GCLEARSCREEN );
  367.  
  368.     strcpy( ce.subtitle.title, "Customized Pie Chart" );
  369.     ce.chartstyle = _PG_PERCENT;
  370.     ce.legend.place = _PG_BOTTOM;
  371.     if (si.fColor)
  372.     {
  373.         ce.maintitle.titlecolor = ce.subtitle.titlecolor = 0;
  374.         ce.chartwindow.background = 1;
  375.         ce.datawindow.background = ce.legend.legendwindow.background = 6;
  376.         ce.legend.textcolor = 1;
  377.     }
  378.     if( ViewChart() )
  379.         return;
  380.     else
  381.         _clearscreen( _GCLEARSCREEN );
  382.  
  383.     cValue = 12;
  384.     DefaultData( _PG_BARCHART, _PG_PLAINBARS, TRUE );
  385.     strcpy( ce.subtitle.title, "Default Bar Chart" );
  386.     if( ViewChart() )
  387.         return;
  388.     else
  389.         _clearscreen( _GCLEARSCREEN );
  390.  
  391.     strcpy( ce.subtitle.title, "Customized Stacked Bar Chart" );
  392.     strcpy( ce.xaxis.axistitle.title, "Sales in Thousands" );
  393.     strcpy( ce.yaxis.axistitle.title, "Month" );
  394.     ce.chartstyle = _PG_STACKEDBARS;
  395.     ce.legend.place = _PG_RIGHT;
  396.     ce.xaxis.ticdecimals = 2;
  397.     if (si.fColor)
  398.     {
  399.         ce.maintitle.titlecolor = ce.subtitle.titlecolor = 12;
  400.         ce.chartwindow.background = 7;
  401.         ce.datawindow.background = 8;
  402.         ce.legend.textcolor = 0;
  403.         ce.legend.legendwindow.background = 8;
  404.         ce.legend.autosize = FALSE;
  405.         ce.legend.legendwindow.y1 = vc.numypixels - 85;
  406.         ce.legend.legendwindow.y2 = vc.numypixels - 45;
  407.     }
  408.     if( ViewChart() )
  409.         return;
  410.     else
  411.         _clearscreen( _GCLEARSCREEN );
  412.  
  413.     DefaultData( _PG_COLUMNCHART, _PG_PLAINBARS, TRUE );
  414.     strcpy( ce.subtitle.title, "Default Column Chart" );
  415.     if( ViewChart() )
  416.         return;
  417.     else
  418.         _clearscreen( _GCLEARSCREEN );
  419.  
  420.     strcpy( ce.subtitle.title, "Customized Column Chart" );
  421.     strcpy( ce.xaxis.axistitle.title, "Month" );
  422.     strcpy( ce.yaxis.axistitle.title, "Sales in Thousands" );
  423.     ce.legend.place = _PG_BOTTOM;
  424.     if (si.fColor)
  425.     {
  426.         ce.maintitle.titlecolor     = 0;
  427.         ce.subtitle.titlecolor     = 0;
  428.         ce.chartwindow.background = 8;
  429.         ce.datawindow.background = 2;
  430.         ce.legend.legendwindow.background = 10;
  431.     }
  432.     if( ViewChart() )
  433.         return;
  434.     else
  435.         _clearscreen( _GCLEARSCREEN );
  436.  
  437.     DefaultData( _PG_LINECHART, _PG_POINTANDLINE, TRUE );
  438.     strcpy( ce.subtitle.title, "Default Line Chart" );
  439.     if( ViewChart() )
  440.         return;
  441.     else
  442.         _clearscreen( _GCLEARSCREEN );
  443.  
  444.     strcpy( ce.subtitle.title, "Customized Line Chart" );
  445.     strcpy( ce.xaxis.axistitle.title, "Month" );
  446.     strcpy( ce.yaxis.axistitle.title, "Sales in Thousands" );
  447.     ce.legend.place = _PG_RIGHT;
  448.     if (si.fColor)
  449.     {
  450.         ce.maintitle.titlecolor = 1;
  451.         ce.subtitle.titlecolor = 1;
  452.         ce.chartwindow.background = 3;
  453.         ce.datawindow.background = 7;
  454.         ce.legend.legendwindow.background = 7;
  455.         ce.legend.autosize = FALSE;
  456.         ce.legend.legendwindow.y1 = vc.numypixels - 85;
  457.         ce.legend.legendwindow.y2 = vc.numypixels - 45;
  458.     }
  459.     if( ViewChart() )
  460.         return;
  461.     else
  462.         _clearscreen( _GCLEARSCREEN );
  463.  
  464.     DefaultData( _PG_SCATTERCHART, _PG_POINTONLY, TRUE );
  465.     strcpy( ce.subtitle.title, "Default Scatter Chart" );
  466.     if( ViewChart() )
  467.         return;
  468.     else
  469.         _clearscreen( _GCLEARSCREEN );
  470.  
  471.     cSeries = 4;
  472.     strcpy( ce.subtitle.title, "Customized Scatter Chart" );
  473.     strcpy( ce.xaxis.axistitle.title, "Sales in Thousands" );
  474.     strcpy( ce.yaxis.axistitle.title, "Average Temperature" );
  475.     ce.legend.place = _PG_RIGHT;
  476.     if (si.fColor)
  477.     {
  478.         ce.maintitle.titlecolor = 0;
  479.         ce.subtitle.titlecolor = 0;
  480.         ce.chartwindow.background = 4;
  481.         ce.datawindow.background = 8;
  482.         ce.legend.legendwindow.background = 8;
  483.         ce.legend.autosize = FALSE;
  484.         ce.legend.legendwindow.y1 = vc.numypixels - 85;
  485.         ce.legend.legendwindow.y2 = vc.numypixels - 45;
  486.     }
  487.     if( ViewChart() )
  488.         return;
  489.     else
  490.         _clearscreen( _GCLEARSCREEN );
  491.  
  492.     DefaultData( _PG_BARCHART, _PG_PERCENT, TRUE );
  493. }
  494.  
  495. /*  FindVideoMode - Finds the "best" video mode for the adaptor in use.
  496.  *
  497.  *  Params: vc - structure of type struct videoconfig
  498.  *
  499.  *  Returns: Best mode
  500.  */
  501. int FindVideoMode( struct videoconfig vc )
  502. {
  503.     switch( vc.adapter )
  504.     {
  505.         case _CGA:
  506.         case _OCGA:
  507.             return _HRESBW;
  508.         case _EGA:
  509.         case _OEGA:
  510.             return( vc.monitor == _MONO ) ? _ERESNOCOLOR : _ERESCOLOR;
  511.         case _VGA:
  512.         case _OVGA:
  513.         case _MCGA:
  514.             return _VRES16COLOR;
  515.         case _HGC:
  516.             return _HERCMONO;
  517.         default:
  518.             return _DEFAULTMODE;
  519.     }
  520. }
  521.  
  522. /*  Initialize - Does various initialization tasks.
  523.  *
  524.  *  Params: None
  525.  */
  526. void Initialize( void )
  527. {
  528.     int iSeries, iValue;
  529.  
  530.     /* Initialize all value arrays to missing.  */
  531.     for( iSeries = 0; iSeries < MAXSERIES; iSeries++ )
  532.     {
  533.  
  534.         axValue[iSeries] = _PG_MISSINGVALUE;
  535.         ayValue[iSeries] = _PG_MISSINGVALUE;
  536.  
  537.         for( iValue = 0; iValue < MAXVALUES; iValue++ )
  538.             aValue[iSeries][iValue] = _PG_MISSINGVALUE;
  539.  
  540.         for( iValue = 0; iValue < MAXVALUES; iValue++ )
  541.         {
  542.             axValueMS[iSeries][iValue] = _PG_MISSINGVALUE;
  543.             ayValueMS[iSeries][iValue] = _PG_MISSINGVALUE;
  544.         }
  545.     }
  546.  
  547.     /* Initialize zero sets. */
  548.     cSeries = 0;
  549.  
  550.     /* Initialize default chart environment, screen mode, and data.  */
  551.     _pg_initchart();
  552.     _getvideoconfig( &vc );
  553.  
  554.     /* Find the best available mode for display.
  555.      * Don't set 256 color, medium resolution (_MRES256COLOR).
  556.      */
  557.     si.mode = FindVideoMode( vc );
  558.  
  559.     if( si.mode == _TEXTMONO )
  560.     {
  561.         _clearscreen( _GCLEARSCREEN );
  562.         _outtext( "No graphics available.  Can't run chart demo." );
  563.         exit( 1 );
  564.     }
  565.  
  566.     SetDisplayColors();
  567.  
  568.     SetGraphMode( si.mode );
  569.     DefaultData( _PG_BARCHART, _PG_PLAINBARS, TRUE );
  570.  
  571.     _setvideomode( _DEFAULTMODE );
  572.  
  573.  
  574. }
  575.  
  576. /*  MainMenu - Manages the main menu.
  577.  *
  578.  *  Params: None
  579.  */
  580. void MainMenu( void )
  581. {
  582.     int iChoice;
  583.     char chResponse = 'Y';
  584.     char chVerify;
  585.  
  586.     PushTitle( pszMainMenu[0] );
  587.     do
  588.     {
  589.         /* If the user selects Quit, iChoice will contain 6.  If the
  590.          *   user presses ESCAPE, iChoice will be ESCAPE, which is
  591.          *   equal to 27.  In any case, we can test both conditions
  592.          *   by checking to see whether iChoice is less than 6.
  593.          */
  594.         while( (iChoice = Menu( pszMainMenu )) < 6 )
  595.         {
  596.             /* Get main menu selection.  */
  597.             switch( iChoice )
  598.             {
  599.  
  600.                 case 1:
  601.                     /* Display demo charts.  */
  602.                     Demo();
  603.                     _setvideomode( _DEFAULTMODE );
  604.                     break;
  605.  
  606.                 case 2:
  607.                     /* Set graphics video mode, display current chart,
  608.                      * and restore text video mode.
  609.                      */
  610.                     _setvideomode( si.mode );
  611.                     ViewChart();
  612.                     _setvideomode( _DEFAULTMODE );
  613.                     break;
  614.  
  615.                 case 3:
  616.                     /* Get chart type and style.  */
  617.                     ChartType();
  618.                     break;
  619.  
  620.                 case 4:
  621.                     /* Get chart options.  */
  622.                     ChartOptions();
  623.                     break;
  624.                 case 5:
  625.                     /* Show chart data. */
  626.                     ShowChartData();
  627.                     break;
  628.  
  629.             }
  630.  
  631.         }
  632.  
  633.         /* If the user is trying to leave the program using the ESCAPE
  634.          *   key, we must verify the choice.  This is done to prevent
  635.          *   an eager typist from pressing ESCAPE one time too often
  636.          *   and exiting at an unanticipated point.
  637.          */
  638.         if( iChoice == ESCAPE )
  639.         {
  640.             Help( "Press \"Q\" to Actually Quit", co.InputColor );
  641.  
  642.             putchar( BEEP );
  643.             _settextposition( si.help - 1, 32 );
  644.             chVerify = getch();
  645.             if( tolower( chVerify ) != 'q' )
  646.                 iChoice = 0;
  647.             else
  648.                 iChoice = 6;
  649.         }
  650.  
  651.     } while( iChoice != 6 );
  652.     PopTitle();
  653. }
  654.  
  655. /*  ResetOptions - After confirmation, resets chart options to default.
  656.  *
  657.  *  Params: None
  658.  */
  659. void ResetOptions()
  660. {
  661.     char chResponse;
  662.  
  663.     /* Prompt for confirmation before setting default environment.  */
  664.     ClrForm();
  665.     Help( "Type  'Y' to reset all options, 'N' to keep them.", co.InputColor );
  666.     chResponse = InputCh( "Are you sure? ", "YN\x1b" );
  667.     if( chResponse == 'Y' )
  668.         _pg_defaultchart( &ce, 1, 1 );
  669.  
  670. }
  671.  
  672. /*  SetGraphMode - Tests the specified graphics mode and sets the xMax
  673.  *  and yMax values in the si (Screen Information) structure.
  674.  *
  675.  *  Params: mode number
  676.  *
  677.  *  Return: FALSE if mode invalid, TRUE if valid
  678.  */
  679. BOOL SetGraphMode(int mode)
  680. {
  681.     if (!_setvideomode( mode ) )
  682.         return FALSE;
  683.     else
  684.     {
  685.         _getvideoconfig ( &vc );
  686.         if( !vc.numxpixels )
  687.             return FALSE;
  688.         si.xMax = vc.numxpixels;
  689.         si.yMax = vc.numypixels;
  690.         si.mode = mode;
  691.  
  692.         /* Set flag to indicate whether multiple colors are available.  */
  693.         si.fColor = iscolor( mode );
  694.  
  695.         return TRUE;
  696.     }
  697. }
  698.  
  699. /*  ShowChartData - Displays the data in the chart environment.
  700.  *
  701.  *  Params: None
  702.  */
  703. void ShowChartData()
  704. {
  705.     int iRow = 2;
  706.     struct _fontinfo fd;
  707.     static char *szContinue =
  708.         "Press any key to continue, ESC to return to the menu.";
  709.  
  710.     _clearscreen( _GCLEARSCREEN );
  711.     SprintAt( iRow++, 1, "short      charttype =  %d", ce.charttype );
  712.     SprintAt( iRow++, 1, "short      chartstyle = %d", ce.chartstyle );
  713.     SprintAt( iRow++, 1, "windowtype chartwindow =" );
  714.     iRow = ShowWindowType( iRow, 1, ce.chartwindow );
  715.     SprintAt( iRow++, 1, "windowtype datawindow =" );
  716.     iRow = ShowWindowType( iRow, 1, ce.datawindow );
  717.     SprintAt( ++iRow, 1, szContinue );
  718.     if( getch() == ESCAPE )
  719.         return;
  720.  
  721.     iRow = 2;
  722.     _clearscreen( _GCLEARSCREEN );
  723.     SprintAt( iRow++, 1, "titletype  maintitle =" );
  724.     iRow = ShowTitleType( iRow, 1, ce.maintitle );
  725.     SprintAt( iRow++, 1, "titletype   subtitle =" );
  726.     iRow = ShowTitleType( iRow, 1, ce.subtitle );
  727.     SprintAt( ++iRow, 1, szContinue );
  728.     if( getch() == ESCAPE )
  729.         return;
  730.  
  731.     iRow = 2;
  732.     _clearscreen( _GCLEARSCREEN );
  733.     SprintAt( iRow++, 1, "axistype       xaxis =" );
  734.     iRow = ShowAxisType( iRow, 1, ce.xaxis );
  735.     SprintAt( ++iRow, 1, szContinue );
  736.     if( getch() == ESCAPE )
  737.         return;
  738.  
  739.     iRow = 2;
  740.     _clearscreen( _GCLEARSCREEN );
  741.     SprintAt( iRow++, 1, "axistype       yaxis =" );
  742.     iRow = ShowAxisType( iRow, 1, ce.yaxis );
  743.     SprintAt( ++iRow, 1, szContinue );
  744.     if( getch() == ESCAPE )
  745.         return;
  746.  
  747.     iRow = 2;
  748.     _clearscreen( _GCLEARSCREEN );
  749.     SprintAt( iRow++, 1, "legendtype     legend =" );
  750.     iRow = ShowLegendType( iRow, 1, ce.legend );
  751.     SprintAt( ++iRow, 1, szContinue );
  752.     if( getch() == ESCAPE )
  753.         return;
  754.  
  755.     iRow = 2;
  756.     _clearscreen( _GCLEARSCREEN );
  757.     if( _getfontinfo( &fd ) != -1 )
  758.     {
  759.         SprintAt( iRow++, 1, "struct _fontinfo =" );
  760.         iRow = ShowFontInfo( iRow, 1, fd );
  761.         SprintAt( ++iRow, 1, "Press any key to continue . . ." );
  762.         getch();
  763.     }
  764. }
  765.  
  766. /*  ShowAxisType - Displays data in a variable of type "axistype".
  767.  *
  768.  *  Params: iRow - Row at which to start
  769.  *          iCol - Column from which to indent
  770.  *          theAxis - Variable of type "axistype" to display
  771.  *
  772.  *  Return: Next available row
  773.  */
  774. int ShowAxisType( int iRow, int iCol, axistype theAxis )
  775. {
  776.     SprintAt( iRow++, iCol + 5, "short        .grid = %d", theAxis.grid );
  777.     SprintAt( iRow++, iCol + 5, "short   .gridstyle = %d", theAxis.gridstyle );
  778.     SprintAt( iRow++, iCol + 5, "titletype axistitle=" );
  779.     iRow = ShowTitleType( iRow, iCol + 5, theAxis.axistitle );
  780.     SprintAt( iRow++, iCol + 5, "short   .axiscolor = %d", theAxis.axiscolor );
  781.     SprintAt( iRow++, iCol + 5, "short     .labeled = %s",
  782.         (theAxis.labeled) ? "TRUE" : "FALSE" );
  783.     SprintAt( iRow++, iCol + 5, "short   .rangetype = %d", theAxis.rangetype );
  784.     SprintAt( iRow++, iCol + 5, "float     .logbase = %f", theAxis.logbase );
  785.     SprintAt( iRow++, iCol + 5, "short   .autoscale = %s",
  786.         (theAxis.autoscale) ? "TRUE" : "FALSE" );
  787.     SprintAt( iRow++, iCol + 5, "float    .scalemin = %f", theAxis.scalemin );
  788.     SprintAt( iRow++, iCol + 5, "float    .scalemax = %f", theAxis.scalemax );
  789.     SprintAt( iRow++, iCol + 5, "float .scalefactor = %f", theAxis.scalefactor );
  790.     iRow = ShowTitleType( iRow, iCol + 5, theAxis.scaletitle );
  791.     SprintAt( iRow++, iCol + 5, "float  .ticinterval = %f", theAxis.ticinterval );
  792.     SprintAt( iRow++, iCol + 5, "short    .ticformat = %d", theAxis.ticformat );
  793.     SprintAt( iRow++, iCol + 5, "short  .ticdecimals = %d", theAxis.ticdecimals );
  794.  
  795.     return iRow;
  796. }
  797.  
  798. /*  ShowFontInfo - Displays data in a variable of type "_fontinfo".
  799.  *
  800.  *  Params: iRow - Row at which to start
  801.  *          iCol - Column from which to indent
  802.  *          theFont - Variable of type "_fontinfo" to display
  803.  *
  804.  *  Return: Next available row
  805.  */
  806. int ShowFontInfo( int iRow, int iCol, struct _fontinfo theFont )
  807. {
  808.     SprintAt( iRow++, iCol + 5, "int          .type = %d", theFont.type );
  809.     SprintAt( iRow++, iCol + 5, "int        .ascent = %d", theFont.ascent );
  810.     SprintAt( iRow++, iCol + 5, "int      .pixwidth = %d", theFont.pixwidth );
  811.     SprintAt( iRow++, iCol + 5, "int     .pixheight = %d", theFont.pixheight );
  812.     SprintAt( iRow++, iCol + 5, "int      .avgwidth = %d", theFont.avgwidth );
  813.     SprintAt( iRow++, iCol + 5, "char     .filename = %s", theFont.filename );
  814.     SprintAt( iRow++, iCol + 5, "char     .facename = %s", theFont.facename );
  815.  
  816.     return iRow;
  817. }
  818.  
  819. /*  ShowLegendType - Displays data in a variable of type "legendtype".
  820.  *
  821.  *  Params: iRow - Row at which to start
  822.  *          iCol - Column from which to indent
  823.  *          theLegend - Variable of type "legendtype" to display
  824.  *
  825.  *  Return: Next available row
  826.  */
  827. int ShowLegendType( int iRow, int iCol, legendtype theLegend )
  828. {
  829.     SprintAt( iRow++, iCol + 5, "short      .legend = %s",
  830.               (theLegend.legend) ? "TRUE" : "FALSE" );
  831.     SprintAt( iRow++, iCol + 5, "short       .place = %d", theLegend.place );
  832.     SprintAt( iRow++, iCol + 5, "short   .textcolor = %d", theLegend.textcolor );
  833.     SprintAt( iRow++, iCol + 5, "short    .autosize = %d", theLegend.autosize );
  834.     SprintAt( iRow++, iCol + 5, "windowtype legendwindow =" );
  835.     iRow = ShowWindowType( iRow, iCol + 5, theLegend.legendwindow );
  836.  
  837.     return iRow;
  838. }
  839.  
  840. /*  ShowSampleData - Displays the sample data for the demo.
  841.  *
  842.  *  Params: None
  843.  */
  844. void ShowSampleData()
  845. {
  846.     int  iCat, y, iSeries, iValue;
  847.     char szTmp[80];
  848.  
  849.     /* Display data in table format. */
  850.     _clearscreen( _GCLEARSCREEN );
  851.     PrintAt( 1, 40 - strlen(szTmp) / 2, "Data in Table Format", -1 );
  852.  
  853.     /* Write titles and draw separator line. */
  854.     y = 3;
  855.     for( iCat = 1; iCat <= 12; iCat++ )
  856.     PrintAt( y, iCat * 6, aMonths[iCat - 1], -1 );
  857.  
  858.     memset( szTmp, '-', 69 );
  859.     szTmp[69] = 0;
  860.     PrintAt( ++y, 6, szTmp, -1 );
  861.  
  862.     /* Write data. */
  863.     for( iSeries = 1; iSeries <= 3; iSeries++ )
  864.     {
  865.         PrintAt( y += 2, 4, aSalesTitles[iSeries - 1], -1 );
  866.         y += 2;
  867.         for( iValue = 1; iValue <= 12; iValue++ )
  868.         {
  869.             sprintf( szTmp, "%#3.2f", aSales[iSeries - 1][iValue - 1] );
  870.             PrintAt( y, iValue * 6, (char _far *)szTmp, -1 );
  871.         }
  872.     }
  873.     PrintAt( y += 2, 4, TempTitle, -1 );
  874.     y += 2;
  875.     for( iValue = 1; iValue <= 12; iValue++ )
  876.     {
  877.         sprintf( szTmp, "%#3.1f", aTemperature[iValue - 1] );
  878.         PrintAt( y, iValue * 6, szTmp, -1 );
  879.     }
  880.  
  881.     PrintAt( y += 2, 1, "Press any key to continue . . .", -1 );
  882.     getche();
  883. }
  884.  
  885. /*  ShowTitleType - Displays data in a variable of type "titletype".
  886.  *
  887.  *  Params: iRow - Row at which to start
  888.  *          iCol - Column from which to indent
  889.  *          theTitle - Variable of type "titletype" to display
  890.  *
  891.  *  Return: Next available row
  892.  */
  893. int ShowTitleType( int iRow, int iCol, titletype theTitle )
  894. {
  895.     SprintAt( iRow++, iCol + 5, "char    .title[%d] = \"%s\"", _PG_TITLELEN,
  896.                  theTitle.title );
  897.     SprintAt( iRow++, iCol + 5, "short  .titlecolor = %d", theTitle.titlecolor );
  898.     SprintAt( iRow++, iCol + 5, "short     .justify = %d", theTitle.justify );
  899.  
  900.     return iRow;
  901. }
  902.  
  903. /*  ShowWindowType - Displays data in a variable of type "windowtype".
  904.  *
  905.  *  Params: iRow - Row at which to start
  906.  *          iCol - Column from which to indent
  907.  *          theWindow - Variable of type "windowtype" to display
  908.  *
  909.  *  Return: Next available row
  910.  */
  911. int ShowWindowType( int iRow, int iCol, windowtype theWindow )
  912. {
  913.     SprintAt( iRow++, iCol + 5, "short          .x1 = %d", theWindow.x1 );
  914.     SprintAt( iRow++, iCol + 5, "short          .y1 = %d", theWindow.y1 );
  915.     SprintAt( iRow++, iCol + 5, "short          .x2 = %d", theWindow.x2 );
  916.     SprintAt( iRow++, iCol + 5, "short          .y2 = %d", theWindow.y2 );
  917.     SprintAt( iRow++, iCol + 5, "short      .border = %d", theWindow.border );
  918.     SprintAt( iRow++, iCol + 5, "short  .background = %d", theWindow.background );
  919.     SprintAt( iRow++, iCol + 5, "short .borderstyle = %d", theWindow.borderstyle );
  920.     SprintAt( iRow++, iCol + 5, "short .bordercolor = %d", theWindow.bordercolor );
  921.  
  922.     return iRow;
  923. }
  924.  
  925. /*  ShowError - Displays error message for one of the chart library
  926.  *  errors.
  927.  *
  928.  *  Params: iErr - Error number
  929.  */
  930. void ShowError( int iErr )
  931. {
  932.     char szTmp[50];
  933.  
  934.     /* Change to text screen.  */
  935.     _setvideomode( _DEFAULTMODE );
  936.  
  937.     /* Select the error text.  */
  938.     switch( iErr )
  939.     {
  940.         case _PG_NOTINITIALIZED:
  941.             strcpy( szTmp, "Chart Library Not Initialized" );
  942.             break;
  943.         case _PG_BADSCREENMODE:
  944.             strcpy( szTmp, "Invalid Screen Mode" );
  945.             break;
  946.         case _PG_BADCHARTTYPE:
  947.             strcpy( szTmp, "Invalid Chart Type" );
  948.             break;
  949.         case _PG_BADCHARTSTYLE:
  950.             strcpy( szTmp, "Invalid Chart Style" );
  951.             break;
  952.         case _PG_BADLEGENDWINDOW:
  953.             strcpy( szTmp, "Invalid Legend Window" );
  954.             break;
  955.         case _PG_BADDATAWINDOW:
  956.             strcpy( szTmp, "No Room for Data window" );
  957.             break;
  958.         case _PG_BADCHARTWINDOW:
  959.             strcpy( szTmp, "Invalid Chart window coordinates" );
  960.             break;
  961.         case _PG_NOMEMORY:
  962.             strcpy( szTmp, "Not Enough Memory for Data Arrays" );
  963.             break;
  964.         case _PG_BADLOGBASE:
  965.             strcpy( szTmp, "X or Y log base <= 0" );
  966.             break;
  967.         case _PG_BADSCALEFACTOR:
  968.             strcpy( szTmp, "X or Y scale factor = 0" );
  969.             break;
  970.         case _PG_TOOSMALLN:
  971.             strcpy( szTmp, "Too few data values" );
  972.             break;
  973.         case _PG_TOOFEWSERIES:
  974.             strcpy( szTmp, "No data series specified" );
  975.             break;
  976.         default:
  977.             strcpy( szTmp, "Unknown error" );
  978.     }
  979.  
  980.     ErrorMsg( szTmp );
  981. }
  982.  
  983. /*  ViewChart - Draws the current chart.
  984.  *
  985.  *  Params: None
  986.  */
  987. int ViewChart()
  988. {
  989.     int cValue, iValue, iSeries, iErr;
  990.  
  991.     /* Make sure some data exists.  */
  992.     if( cSeries <= 0 )
  993.     {
  994.         fDefault = TRUE;
  995.         DefaultData( ce.charttype, ce.chartstyle, FALSE );
  996.     }
  997.  
  998.     /* Find the longest series.  */
  999.     cValue = 0;
  1000.     for( iSeries = 0; iSeries < cSeries; iSeries++ )
  1001.         if( acSeries[iSeries] > cValue )
  1002.             cValue = acSeries[iSeries];
  1003.  
  1004.     _setvideomode( si.mode );
  1005.  
  1006.  
  1007.     /* Process depending on the type of chart.  */
  1008.     switch( ce.charttype )
  1009.     {
  1010.  
  1011.         case _PG_PIECHART:
  1012.         case _PG_BARCHART:
  1013.         case _PG_COLUMNCHART:
  1014.         case _PG_LINECHART:
  1015.  
  1016.             /* Initialize data and draw pie chart or single-series bar,
  1017.              * column, or line chart.
  1018.              */
  1019.             if( (cSeries == 1) ||( ce.charttype == _PG_PIECHART) )
  1020.             {
  1021.  
  1022.                 /* Transfer data into a single-dimension array.  */
  1023.                 for( iValue = 0; iValue < cValue; iValue++ )
  1024.                    axValue[iValue] = aValue[0][iValue];
  1025.  
  1026.                 /* Draw chart.  */
  1027.                 if( ce.charttype == _PG_PIECHART )
  1028.                     iErr = _pg_chartpie( &ce, aCat, axValue,
  1029.                                          aExplode, cValue );
  1030.                 else
  1031.                     iErr = _pg_chart( &ce, aCat, axValue, cValue );
  1032.             }
  1033.             /* If multiple-series, then data is OK. Just draw chart.  */
  1034.             else
  1035.                 iErr = _pg_chartms( &ce, aCat, (float _far *)aValue,
  1036.                                     cSeries, cValue, cValue, aSeriesName );
  1037.             break;
  1038.  
  1039.         case _PG_SCATTERCHART:
  1040.  
  1041.             /* Make sure there are enough data sets.  */
  1042.             if( cSeries == 1 )
  1043.             {
  1044.                 _setvideomode( _DEFAULTMODE );
  1045.                 si.help = 10;
  1046.                 ErrorMsg( "Too few value data columns for scatter chart." );
  1047.                 return 1;
  1048.  
  1049.             }
  1050.             /* If it's a single-series scatter, transfer data to one-
  1051.              * dimensional arrays and make chart call.
  1052.              */
  1053.             else if( cSeries == 2 )
  1054.             {
  1055.                 for( iValue = 0; iValue < cValue; iValue++ )
  1056.                 {
  1057.                     axValue[iValue] = aValue[0][iValue];
  1058.                     ayValue[iValue] = aValue[1][iValue];
  1059.                 }
  1060.                 cSeries = 1;
  1061.                 iErr = _pg_chartscatter( &ce, axValue, ayValue, cValue );
  1062.  
  1063.             }
  1064.             /* If it's a multiple-series scatter, transfer odd columns to
  1065.              * X-axis data array and even columns to Y-axis array and make
  1066.              * chart call.
  1067.              */
  1068.             else
  1069.             {
  1070.  
  1071.                 for( iSeries = 1; iSeries < cSeries; iSeries += 2 )
  1072.                 {
  1073.                     aSeriesName[iSeries / 2] = aSeriesName[iSeries - 1];
  1074.                     for( iValue = 0; iValue < cValue; iValue++ )
  1075.                     {
  1076.                         axValueMS[iSeries / 2][iValue] =
  1077.                             aValue[iSeries - 1][iValue];
  1078.                         ayValueMS[iSeries / 2][iValue] =
  1079.                             aValue[iSeries][iValue];
  1080.                     }
  1081.                 }
  1082.                 cSeries /= 2;
  1083.  
  1084.                 iErr = _pg_chartscatterms( &ce, (float _far *)axValueMS,
  1085.                                            (float _far *)ayValueMS,
  1086.                                            cSeries, cValue, cValue,
  1087.                                            aSeriesName );
  1088.             }
  1089.     }
  1090.  
  1091.     if( !fDefault )
  1092.         ClearData( FALSE );
  1093.  
  1094.     /* If error, show it, else wait for keypress with chart on screen.  */
  1095.     if( iErr )
  1096.     {
  1097.         ShowError( iErr );
  1098.         return iErr;
  1099.     }
  1100.     else
  1101.         return ( getch() == ESCAPE );   /* ESCAPE means stop demo */
  1102. }
  1103.