home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / C++-7 / DISK4 / SAMPLES / GRAPHICS / CHRTDEMO.C$ / CHRTDEMO
Encoding:
Text File  |  1992-02-26  |  32.7 KB  |  1,095 lines

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