home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / os2sdk / os2sdk12 / stock / stock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-09  |  24.5 KB  |  1,004 lines

  1. /***    stock - draw a stock chart
  2.  *
  3.  *    Author:
  4.  *        Benjamin W. Slivka
  5.  *
  6.  *    History:
  7.  *        27-Mar-1989 bens    Initial version.
  8.  *        06-Apr-1989 bens    Always repaint on WM_SIZE.
  9.  *        26-Apr-1990 bens    Get it limping along
  10.  *        03-May-1990 bens    Add file open
  11.  *        11-May-1990 bens    Printing works!
  12.  *        06-Jun-1990 bens    Finish job property handling
  13.  *        07-Jun-1990 bens    Fix bugs in JP stuff, spiff up user interface
  14.  */
  15.  
  16. #define INCL_DEV
  17.  
  18. #define INCL_GPIPRIMITIVES
  19.  
  20. #define INCL_WINDIALOGS
  21. #define INCL_WINERRORS
  22. #define INCL_WINFRAMEMGR
  23. #define INCL_WINLISTBOXES
  24. #define INCL_WINMENUS
  25. #define INCL_WINPOINTERS
  26. #define INCL_WINWINDOWMGR
  27.  
  28. #include <os2.h>
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32.  
  33. #include "ea.h"
  34. #include "ids.h"
  35. #include "file.h"
  36. #include "limits.h"
  37. #include "mem.h"
  38. #include "print.h"
  39.  
  40.  
  41. #define cchDate    10
  42. #define cchMax       80
  43.  
  44. #define iH        0        // index of High
  45. #define iL        1        // index of Low
  46. #define iC        2        // index of Close
  47. #define NV        3        // Number of vectors
  48. #define cptMax     1200        // maximum data points
  49.  
  50.  
  51. #define ENABLE_MENU_ITEM(x, y)                    \
  52.     WinSendDlgItemMsg((x), FID_MENU, MM_SETITEMATTR,    \
  53.         MPFROM2SHORT((y),TRUE),                \
  54.         MPFROM2SHORT(MIA_DISABLED,NULL))
  55.  
  56. #define DISABLE_MENU_ITEM(x, y)                 \
  57.     WinSendDlgItemMsg((x), FID_MENU, MM_SETITEMATTR,    \
  58.         MPFROM2SHORT((y),TRUE),                \
  59.         MPFROM2SHORT(MIA_DISABLED,MIA_DISABLED))
  60.  
  61. #define CHECK_MENU_ITEM(x, y)                    \
  62.     WinSendDlgItemMsg((x), FID_MENU, MM_SETITEMATTR,    \
  63.         MPFROM2SHORT((y),TRUE),                \
  64.         MPFROM2SHORT(MIA_CHECKED,MIA_CHECKED))
  65.  
  66. #define UNCHECK_MENU_ITEM(x, y)                 \
  67.     WinSendDlgItemMsg((x), FID_MENU, MM_SETITEMATTR,    \
  68.         MPFROM2SHORT((y),TRUE),                \
  69.         MPFROM2SHORT(MIA_CHECKED,NULL))
  70.  
  71.  
  72. MRESULT EXPENTRY ClientWndProc(HWND hwnd,USHORT msg,MPARAM mp1,MPARAM mp2);
  73. MRESULT EXPENTRY AboutDlgProc(HWND hwnd,USHORT msg,MPARAM mp1,MPARAM mp2);
  74. MRESULT EXPENTRY PrinterSetupDlgProc(HWND hwnd,USHORT msg,MPARAM mp1,MPARAM mp2);
  75.  
  76.  
  77. HPRINTER    HPRTFromListBox(HWND hwnd);
  78. BOOL        InteractSaveFile(HWND hwnd);
  79. int cdecl   main(int cArg,char **ppszArg);
  80. VOID        Message(char *psz, HWND hwnd);
  81. VOID        PlotPrice(HPS hps,RECTL rcl);
  82. BOOL        QueryHCI(HDC hdc,HCINFO *phci);
  83. BOOL        PrintChart(HWND hwnd);
  84. BOOL        ReadData(HWND hwnd);
  85. VOID        SaveJobProperties(VOID);
  86. VOID        SetOriginMenu(VOID);
  87. VOID        SetFileMenu(VOID);
  88. VOID        ShowWinError(char *psz);
  89.  
  90.  
  91. /***    GLOBAL - global data
  92.  *
  93.  */
  94. typedef struct {    /* glb */
  95.     char     achAppTitle[CCHMAXPATH]; // Application title
  96.     USHORT     cpt;        // Number of points
  97.     BOOL     fNewJobProp;    // TRUE => job properties changed
  98.     BOOL     fZeroOrigin;    // TRUE => Y origin is 0; else is minimum price
  99.     HAB      hab;
  100.     HWND     hwndFrame;
  101.     HWND     hwndClient;
  102.     USHORT     pMax;        // Maximum price
  103.     USHORT     pMin;        // Minimum price
  104.     char *     pszFile;    // Data file
  105.     HPRINTER     hprt;        // Current printer handle
  106.     HPRINTERLIST hprtlist;    // Handle of printer list
  107. } GLOBAL;
  108.  
  109. char        achMisc[CCHMAXPATH];
  110. USHORT        apt[NV][cptMax];
  111. GLOBAL        glb;
  112. HPOINTER    hptrNormal;
  113. HPOINTER    hptrWait;
  114. char        szClientClass[]="Stock";
  115. char        pszJobProp[]="StockJobProp";
  116.  
  117.  
  118. /***    main - main program
  119.  *
  120.  */
  121. int cdecl main(int cArg, char **ppszArg)
  122. {
  123.     ULONG        flFrameFlags= FCF_TITLEBAR        | FCF_SYSMENU  |
  124.                   FCF_SIZEBORDER    | FCF_MINMAX   |
  125.                   FCF_SHELLPOSITION | FCF_TASKLIST |
  126.                   FCF_MENU;
  127.     HMQ         hmq;
  128.     QMSG        qmsg;
  129.  
  130.     glb.hprt = NULL;
  131.     glb.cpt = 0;
  132.     glb.fZeroOrigin = TRUE;        // Use a zero origin
  133.     glb.fNewJobProp = FALSE;        // No new job properties
  134.  
  135.     // If at least one argument, take that as data file name
  136.     if (cArg >= 2)
  137.     glb.pszFile = MemStrDup(ppszArg[1]);
  138.     else
  139.     glb.pszFile = NULL;
  140.  
  141.     glb.hab = WinInitialize(0);
  142.     hmq = WinCreateMsgQueue(glb.hab,0);
  143.  
  144.     hptrWait = WinQuerySysPointer(HWND_DESKTOP,SPTR_WAIT,FALSE);
  145.     hptrNormal = WinQuerySysPointer(HWND_DESKTOP,SPTR_ARROW,FALSE);
  146.  
  147.     WinRegisterClass(glb.hab,szClientClass,ClientWndProc,0L,0);
  148.  
  149.     glb.hwndFrame = WinCreateStdWindow(HWND_DESKTOP,
  150.             WS_VISIBLE | FS_ICON | FS_TASKLIST, // Window styles
  151.             &flFrameFlags,
  152.             szClientClass,
  153.             NULL,
  154.             0L,
  155.             (HMODULE) NULL,
  156.             IDR_APP,
  157.             &glb.hwndClient);
  158.  
  159.     if (glb.hwndFrame == 0) {
  160.     Message("Cannot create main window",NULL);
  161.     WinDestroyMsgQueue(hmq);
  162.     WinTerminate(glb.hab);
  163.     return 1;
  164.     }
  165.  
  166.     // Get printer list
  167.     glb.hprtlist = PrintCreatePrinterList(glb.hab);
  168.  
  169.     // Get application title
  170.     WinQueryWindowText(glb.hwndFrame, sizeof(glb.achAppTitle),glb.achAppTitle);
  171.  
  172.     if (glb.pszFile != NULL)
  173.     ReadData(glb.hwndClient);
  174.  
  175.     // Get printer, if not already set by ReadData
  176.  
  177.     if (glb.hprt == NULL) {        // Need to find it
  178.     if (glb.hprtlist != NULL) {    // Printers exists
  179.         glb.hprt = PrintQueryDefaultPrinter(glb.hprtlist); // Get default
  180.     }
  181.     }
  182.  
  183.     // Set up valid menu options
  184.  
  185.     SetFileMenu();
  186.     SetOriginMenu();
  187.  
  188.     // Message loop
  189.  
  190.     while (WinGetMsg(glb.hab,&qmsg,NULL,0,0)) {
  191.     WinDispatchMsg(glb.hab,&qmsg);
  192.     }
  193.  
  194.     // Destroy printer list
  195.  
  196.     if (glb.hprtlist != NULL)
  197.     PrintDestroyPrinterList(glb.hprtlist);
  198.  
  199.     WinDestroyWindow(glb.hwndFrame);
  200.     WinDestroyMsgQueue(hmq);
  201.     WinTerminate(glb.hab);
  202.     return 0;
  203. }
  204.  
  205.  
  206. /***    ClientWndProc - window proc for client window
  207.  *
  208.  */
  209. MRESULT EXPENTRY ClientWndProc(HWND hwnd,USHORT msg,MPARAM mp1,MPARAM mp2)
  210. {
  211.     HPS     hps;
  212.     char *  psz;
  213.     RECTL   rcl;
  214.  
  215.     switch (msg) {
  216.  
  217.     case WM_COMMAND:
  218.     switch (SHORT1FROMMP(mp1)) {
  219.  
  220.     case IDM_ABOUT:
  221.         WinDlgBox(HWND_DESKTOP,hwnd,AboutDlgProc,NULL,IDD_ABOUT,NULL);
  222.         return FALSE;
  223.  
  224.     case IDM_FILE_CLOSE:
  225.         // Make sure current file is saved
  226.         if (!InteractSaveFile(hwnd)) // User cancelled
  227.         return FALSE;
  228.  
  229.         // Empty data
  230.  
  231.         glb.cpt = 0;
  232.         if (glb.pszFile != NULL) {
  233.         MemFree(glb.pszFile);
  234.         glb.pszFile = NULL;
  235.         }
  236.         WinInvalidateRect(hwnd,NULL,FALSE); // Force repaint
  237.  
  238.  
  239.         SetFileMenu();        // Set valid menu options
  240.         return FALSE;
  241.  
  242.     case IDM_FILE_OPEN:
  243.         // Make sure current file is saved
  244.         if (!InteractSaveFile(hwnd)) // User cancelled
  245.             return FALSE;
  246.  
  247.         psz = FileOpen(hwnd, "Open", "*.dat");
  248.         if (psz != NULL) {
  249.         if (glb.pszFile != NULL) // Old file data present
  250.             MemFree(glb.pszFile); // Free old file name
  251.         glb.pszFile = psz;    // Set new file name
  252.         if (ReadData(hwnd))    // If data was read successfully
  253.             WinInvalidateRect(hwnd,NULL,FALSE); // Force repaint
  254.         }
  255.         return FALSE;
  256.  
  257.     case IDM_FILE_PRINT:
  258.  
  259.         PrintChart(hwnd);
  260.         break;
  261.  
  262.     case IDM_FILE_PRINTER_SETUP:
  263.         WinDlgBox(HWND_DESKTOP,hwnd,PrinterSetupDlgProc,NULL,
  264.                          IDD_PRINTER_SETUP,NULL);
  265.         return FALSE;
  266.  
  267.     case IDM_FILE_SAVE:
  268.         SaveJobProperties();
  269.         SetFileMenu();
  270.         return FALSE;
  271.  
  272.     case IDM_FILE_EXIT:
  273.         WinSendMsg(hwnd,WM_QUIT,NULL,NULL);
  274.         break;
  275.  
  276.     case IDM_OPTIONS_ORIGIN:
  277.         glb.fZeroOrigin = !glb.fZeroOrigin; // Flip state
  278.         SetOriginMenu();
  279.         return FALSE;
  280.     }
  281.     break;
  282.  
  283.     case WM_CREATE:
  284.     break;
  285.  
  286.     case WM_QUIT:
  287.     if (!InteractSaveFile(hwnd))        // User cancelled
  288.         return FALSE;            //    Do not quit
  289.     break;                    // Do standard quit processing
  290.  
  291.     case WM_SIZE:
  292.     WinInvalidateRect(hwnd,NULL,FALSE);
  293.     return 0;
  294.  
  295.     case WM_PAINT:
  296.     hps = WinBeginPaint(hwnd,NULL,NULL);
  297.     GpiErase(hps);
  298.     WinQueryWindowRect(hwnd,&rcl);
  299.     PlotPrice(hps,rcl);
  300.     WinEndPaint(hps);
  301.     return 0;
  302.     }
  303.     return WinDefWindowProc(hwnd,msg,mp1,mp2);
  304. }
  305.  
  306.  
  307. /***    InteractSaveFile - If new job properties, let user save them
  308.  *
  309.  *    Entry
  310.  *        hwnd - parent window for message box
  311.  *        glb.fNewJobProp
  312.  *
  313.  *    Exit-Success
  314.  *        returns TRUE, file is saved
  315.  *
  316.  *    Exit-Failure
  317.  *        returns FALSE, user cancelled save
  318.  */
  319. BOOL InteractSaveFile(HWND hwnd)
  320. {
  321.     static char ach[CCHMAXPATH];
  322.     USHORT    rc;
  323.  
  324.     if (!glb.fNewJobProp)        // No job properties to save
  325.     return TRUE;
  326.  
  327.     sprintf(ach,"Save printer setup in '%s'?",glb.pszFile);
  328.     rc = WinMessageBox(
  329.         HWND_DESKTOP,        // Parent
  330.         hwnd,            // Owner
  331.         ach,            // Message
  332.         szClientClass,        // Caption (use default)
  333.         NULL,            // Window id
  334.         MB_QUERY | MB_YESNOCANCEL | MB_APPLMODAL // window style
  335.     );
  336.     switch (rc) {
  337.     case MBID_YES:            // Save job properties
  338.         SaveJobProperties();
  339.         SetFileMenu();
  340.         return TRUE;
  341.  
  342.     case MBID_NO:            // Do not save job properties
  343.         glb.fNewJobProp = FALSE;
  344.         SetFileMenu();
  345.         return TRUE;
  346.  
  347.     case MBID_CANCEL:        // Cancel save
  348.         return FALSE;
  349.     }
  350.     return FALSE;
  351. }
  352.  
  353.  
  354. /***    PrintChart - Draw chart on printer
  355.  *
  356.  *    Entry
  357.  *        hwnd - hwnd for status
  358.  *
  359.  *        glb.hab  - Anchor block
  360.  *        glb.hprt - Printer destination
  361.  *        glb.pszFile - File name (for job description)
  362.  *
  363.  *        Same variables as PlotPrice;
  364.  *
  365.  *    Exit-Success
  366.  *        returns TRUE
  367.  *
  368.  *    Exit-Failure
  369.  *        returns FALSE
  370.  */
  371. BOOL PrintChart(HWND hwnd)
  372. {
  373.     LONG        cb;
  374.     USHORT        jobid;
  375.     HDC         hdc=NULL;
  376.     HPS         hps=NULL;
  377.     static HCINFO   hci;
  378.     LONG        rc;
  379.     RECTL        rcl;
  380.     SIZEL        sizl;
  381.  
  382.     WinSetPointer(HWND_DESKTOP,hptrWait); // Tell user we are being slow
  383.  
  384.     // Create DC
  385.  
  386.     hdc = PrintOpenDC(glb.hab,glb.hprt,"PM_Q_STD");
  387.     if (hdc == NULL) {
  388.     ShowWinError("PrintOpenDC failed");
  389.     rc = DEV_ERROR;
  390.     goto Exit;
  391.     }
  392.  
  393.     if (!QueryHCI(hdc,&hci)) {
  394.     Message("QueryHCI failed",NULL);
  395.     rc = DEV_ERROR;
  396.     goto Exit;
  397.     }
  398.  
  399.     // Create and associate PS
  400.     sizl.cx = 0L;
  401.     sizl.cy = 0L;
  402.     hps = GpiCreatePS(glb.hab,hdc,&sizl,GPIA_ASSOC | PU_PELS | GPIT_NORMAL);
  403.     if (hps == NULL) {
  404.     ShowWinError("GpiCreatePS failed");
  405.     rc = DEV_ERROR;
  406.     goto Exit;
  407.     }
  408.  
  409.     // Set dimensions of drawing area
  410.     rcl.xLeft    = 0;
  411.     rcl.yBottom = 0;
  412.     rcl.xRight    = hci.xPels;
  413.     rcl.yTop    = hci.yPels;
  414.  
  415.     // Time to draw
  416.     rc = DevEscape(
  417.         hdc,            // Display context
  418.         DEVESC_STARTDOC,        // Start document
  419.         (LONG)strlen(glb.pszFile),    // Length of print job name
  420.         glb.pszFile,        // Print job name
  421.         0L,             // Ignored
  422.         0L                // Ignored
  423.      );
  424.     if (rc != DEV_OK) {
  425.     ShowWinError("STARTDOC failed");
  426.     goto Exit;
  427.     }
  428.  
  429.     PlotPrice(hps,rcl);
  430.  
  431.     cb = sizeof(jobid);         // Size of output buffer
  432.     rc = DevEscape(
  433.         hdc,            // Display context
  434.         DEVESC_ENDDOC,        // End document
  435.         0L,             // Length of print job name
  436.         0L,             // Print job name
  437.         &cb,            // Size of jobid
  438.         (PBYTE)&jobid        // Jobid
  439.      );
  440.     if (rc != DEV_OK)
  441.     ShowWinError("ENDDOC failed");
  442.  
  443.     // Free resources
  444. Exit:
  445.     if (hps != NULL) {
  446.     GpiAssociate(hps,NULL);
  447.     GpiDestroyPS(hps);
  448.     }
  449.     if (hdc != NULL)
  450.     DevCloseDC(hdc);
  451.     WinSetPointer(HWND_DESKTOP,hptrNormal); // Tell user we are done
  452.     return (rc == DEV_OK);
  453. }
  454.  
  455.  
  456. /***    ShowWinError - Show message box with error from Win* API call
  457.  *
  458.  *    Entry
  459.  *        psz - message text
  460.  *
  461.  *    Exit
  462.  *        none
  463.  *
  464.  */
  465. VOID ShowWinError(char *psz)
  466. {
  467.     PERRINFO        perri;
  468.  
  469.     perri = WinGetErrorInfo(glb.hab);
  470.     if (perri == (PERRINFO) NULL)
  471.     return;
  472.  
  473.     sprintf(achMisc,"%s; Error = 0x%0x",psz,perri->idError);
  474.     Message(achMisc,NULL);
  475.     WinFreeErrorInfo(perri);
  476. }
  477.  
  478.  
  479. /***    SetOriginMenu - Set text in origin menu
  480.  *
  481.  *    Entry
  482.  *        glb.fZeroOrgin - current state of origin plotting
  483.  *
  484.  *    Exit
  485.  *        Menu item checked/unchecked
  486.  */
  487. VOID SetOriginMenu(VOID)
  488. {
  489.     if (glb.fZeroOrigin)
  490.     UNCHECK_MENU_ITEM(glb.hwndFrame,IDM_OPTIONS_ORIGIN);
  491.     else
  492.     CHECK_MENU_ITEM(glb.hwndFrame,IDM_OPTIONS_ORIGIN);
  493.  
  494.     WinInvalidateRect(glb.hwndClient,NULL,FALSE); // Force repaint
  495. }
  496.  
  497.  
  498. /***    SetFileMenu - Set file menu item states
  499.  *
  500.  */
  501. VOID SetFileMenu(VOID)
  502. {
  503.     static char ach[CCHMAXPATH];
  504.  
  505.     strcpy(ach,glb.achAppTitle);    // Title start with app name
  506.  
  507.     if (glb.pszFile == NULL) {        // No file currently open
  508.     DISABLE_MENU_ITEM(glb.hwndFrame,IDM_FILE_CLOSE);
  509.     DISABLE_MENU_ITEM(glb.hwndFrame,IDM_FILE_SAVE);
  510.     DISABLE_MENU_ITEM(glb.hwndFrame,IDM_FILE_PRINT);
  511.     DISABLE_MENU_ITEM(glb.hwndFrame,IDM_FILE_PRINTER_SETUP);
  512.     }
  513.     else {
  514.     ENABLE_MENU_ITEM(glb.hwndFrame,IDM_FILE_CLOSE);
  515.  
  516.     if (glb.fNewJobProp)        // Job properties need to be saved
  517.         ENABLE_MENU_ITEM(glb.hwndFrame,IDM_FILE_SAVE);
  518.     else
  519.         DISABLE_MENU_ITEM(glb.hwndFrame,IDM_FILE_SAVE);
  520.  
  521.     if (glb.hprt != NULL) {     // A printer exists
  522.         ENABLE_MENU_ITEM(glb.hwndFrame,IDM_FILE_PRINT);
  523.         ENABLE_MENU_ITEM(glb.hwndFrame,IDM_FILE_PRINTER_SETUP);
  524.     }
  525.     else {
  526.         DISABLE_MENU_ITEM(glb.hwndFrame,IDM_FILE_PRINT);
  527.         DISABLE_MENU_ITEM(glb.hwndFrame,IDM_FILE_PRINTER_SETUP);
  528.     }
  529.  
  530.     strcat(ach," - ");        // Append file name
  531.     strcat(ach,glb.pszFile);
  532.     }
  533.     WinSetWindowText(glb.hwndFrame,ach); // Set title
  534. }
  535.  
  536.  
  537. /***    ReadData - read stock data from file
  538.  *
  539.  *    Entry
  540.  *        hwnd     - Hwnd for status messages
  541.  *        glb.pszFile  - File to read
  542.  *        glb.hprtlist - Printer list
  543.  *
  544.  *    Exit-Success
  545.  *        Returns TRUE
  546.  *        apt[][]  = Filled in with price data
  547.  *        glb.cpt  = Count of points read
  548.  *        glb.pMax = Maximum price
  549.  *        glb.pMin = Minimum price
  550.  *        glb.hprt = May have change, to file job properties
  551.  *
  552.  *    Exit-Failure
  553.  *        Returns FALSE
  554.  */
  555. BOOL ReadData(HWND hwnd)
  556. {
  557.     static char   ach[CCHMAXPATH];
  558.     static USHORT cb;
  559.     int       cf;
  560.     USHORT      factorSplit;
  561.     USHORT      fracClose;
  562.     USHORT      fracHigh;
  563.     USHORT      fracLow;
  564.     HPRINTER      hprt;
  565.     int       i;
  566.     USHORT      intClose;
  567.     USHORT      intHigh;
  568.     USHORT      intLow;
  569.     int       j;
  570.     char *      pb;
  571.     char *      pch;
  572.     char *      pch1;
  573.     FILE *      pfile;
  574.     ULONG      ulVol;
  575.  
  576.     WinSetPointer(HWND_DESKTOP,hptrWait); // Tell user we are being slow
  577.  
  578.     glb.cpt = 0;
  579.     glb.fNewJobProp = FALSE;        // Job properties not changed
  580.     SetFileMenu();
  581.  
  582.     pfile = fopen(glb.pszFile,"r");
  583.     if (pfile == NULL) {
  584.     WinSetPointer(HWND_DESKTOP,hptrNormal); // Tell user we are done
  585.     sprintf(achMisc,"Could not open \"%s\"",glb.pszFile);
  586.     Message(achMisc,hwnd);
  587.     return FALSE;
  588.     }
  589.  
  590.     fgets(ach,cchMax,pfile);   // skip two header lines
  591.     fgets(ach,cchMax,pfile);
  592.     fgets(ach,cchMax,pfile);   // Get first data line
  593.     while (!feof(pfile)) {
  594.     if (glb.cpt > cptMax) {
  595.         WinSetPointer(HWND_DESKTOP,hptrNormal); // Tell user we are done
  596.         sprintf(achMisc,"Too many data points. Max is %d.",cptMax);
  597.         Message(achMisc,hwnd);
  598. // BUGBUG 03-May-1990 bens Should continue with truncated data?
  599. //
  600. // Should make file read a separate function, and do min/max computation
  601. // as long as some data was read.
  602. //
  603.     return FALSE;
  604.     }
  605.  
  606.     // Skip date
  607.     pch = strchr(ach,'"')+1;    // pch    -> 04/24/60",....
  608.     pch1 = strchr(pch,'"');     // pch1 ->       ",....
  609.     *pch1 = '\0';            // Split string at end of date
  610.     pch1 += 2;            // Skip ",
  611.  
  612.     cf = sscanf(pch1," %d.%d, %d.%d, %d.%d, %ld",
  613.           &intHigh,&fracHigh,&intLow,&fracLow,&intClose,&fracClose,&ulVol);
  614.  
  615.     if (cf != 7) {
  616.         WinSetPointer(HWND_DESKTOP,hptrNormal); // Tell user we are done
  617.         // Adjust count for two header lines, plus base 0
  618.         sprintf(achMisc,"Line %d is bad: [%s]",glb.cpt+3,ach);
  619.         Message(achMisc,hwnd);
  620. // BUGBUG 03-May-1990 bens What to do now?
  621. //
  622. // On par with previous BUGBUG, we should probably display data up to the
  623. // point where it was bad.
  624. //
  625. // Also, it would be nice to give a hint about the problem.
  626. //
  627. // At a minimum, tell if too many or too few data points.
  628.         return FALSE;
  629.     }
  630.  
  631.     // convert to units of 8 points
  632.     intHigh  = (intHigh  << 3) + (fracHigh    / 125);
  633.     intLow     = (intLow   << 3) + (fracLow    / 125);
  634.     intClose = (intClose << 3) + (fracClose / 125);
  635.  
  636.     if (stricmp(pch,"SPLIT") == 0) {
  637.         factorSplit = intHigh/8;
  638.         for (i=0; i<(int) glb.cpt; i++)        // Process all saved records
  639.         for (j=0; j<NV; j++)    // Process dollar values
  640.             apt[j][i] /= factorSplit;
  641.         // dP(iV, j%) *= factorSplit;
  642.     }
  643.     else {
  644.         apt[iH][glb.cpt] = intHigh;
  645.         apt[iL][glb.cpt] = intLow;
  646.         apt[iC][glb.cpt] = intClose;
  647.         glb.cpt++;
  648.     }
  649.     fgets(ach,cchMax,pfile);    // Get next data line
  650.     }
  651.     fclose(pfile);
  652.  
  653.     // Find max and min prices
  654.  
  655.     // Speed win: prime min/max with real value.
  656.     //    This allows the if..else if below to work reliably.
  657.  
  658.     glb.pMax = apt[0][0];
  659.     glb.pMin = apt[0][0];
  660.  
  661.     for (i=0; i<(int)glb.cpt; i++) {
  662.     for (j=0; j<NV; j++) {
  663.         if (apt[j][i] > glb.pMax)
  664.         glb.pMax = apt[j][i];
  665.         else if (apt[j][i] < glb.pMin)
  666.         glb.pMin = apt[j][i];
  667.     }
  668.     }
  669.  
  670.     // Select printer, based on job properties
  671.  
  672.     pb = EAQueryValue(glb.pszFile,pszJobProp,&cb);
  673.     if (pb == NULL) {            // No job prop, use default printer
  674.     WinSetPointer(HWND_DESKTOP,hptrNormal); // Tell user we are done
  675.     return TRUE;            //  Done
  676.     }
  677.     if (cb == 0) {            // Data is not binary
  678.     MemFree(pb);            // Free buffer
  679.     WinSetPointer(HWND_DESKTOP,hptrNormal); // Tell user we are done
  680.     return TRUE;            //  Done
  681.     }
  682.  
  683.     // Try to match a printer
  684.  
  685.     hprt = PrintMatchPrinter(glb.hprtlist,cb,pb);
  686.     if (hprt != NULL)            // Got a match!
  687.     glb.hprt = hprt;        // Set new printer
  688.  
  689.     MemFree(pb);            // Free buffer
  690.  
  691.     SetFileMenu();            // Update menus and title bar
  692.  
  693.     WinSetPointer(HWND_DESKTOP,hptrNormal); // Tell user we are done
  694.     return TRUE;            //  Done
  695. }
  696.  
  697.  
  698. /***    PlotPrice - plot stock price
  699.  *
  700.  *    Entry
  701.  *        hps - Presentation space to plot to
  702.  *        rcl - Bounding rectangle in hps
  703.  *
  704.  *        apt[][]  = Filled in with price data
  705.  *        glb.cpt  = Count of points read
  706.  *        glb.pMax = Maximum price
  707.  *        glb.pMin = Minimum price
  708.  *        glb.hprt = May have change, to file job properties
  709.  *        glb.fZeroOrigin - TRUE => make Y-origin be 0.
  710.  *
  711.  *    Exit
  712.  *        Stock chart plotted
  713.  */
  714. VOID PlotPrice(HPS hps,RECTL rcl)
  715. {
  716.     SHORT   cxBar;
  717.     int     i;
  718.     POINTL  ptl;
  719.     SHORT   x;
  720.     float   xFactor;
  721.     SHORT   xMargin = 4;
  722.     SHORT   yC;
  723.     float   yFactor;
  724.     SHORT   yH;
  725.     SHORT   yL;
  726.     SHORT   yMargin = 4;
  727.     SHORT   yOrigin;
  728.  
  729.     if (glb.cpt == 0)            // No points to draw
  730.     return;
  731.  
  732.     if (glb.fZeroOrigin)
  733.     yOrigin = 0;
  734.     else
  735.     yOrigin = glb.pMin;
  736.  
  737.     yFactor = (float)(rcl.yTop - rcl.yBottom - (LONG)(2*yMargin)) /
  738.           (float)(glb.pMax-yOrigin);
  739.     xFactor = (float)(rcl.xRight - rcl.xLeft - (LONG)(2*xMargin)) /
  740.           (float)(glb.cpt);
  741.  
  742.     cxBar = (USHORT)(xFactor/2.0);
  743.     if (cxBar < 1)
  744.     cxBar = 1;
  745.  
  746.     WinSetPointer(HWND_DESKTOP,hptrWait); // Tell user we are being slow
  747.  
  748.     for (i=0; i<(int)glb.cpt; i++) {
  749.         x = (USHORT)(i*(float)xFactor) + xMargin;
  750.         yH = (USHORT)((float)(apt[iH][i]-yOrigin)*yFactor) + yMargin;
  751.         yL = (USHORT)((float)(apt[iL][i]-yOrigin)*yFactor) + yMargin;
  752.         yC = (USHORT)((float)(apt[iC][i]-yOrigin)*yFactor) + yMargin;
  753.  
  754.         // Draw vertical (low to high) bar
  755.  
  756.         GpiSetColor(hps,CLR_CYAN);
  757.  
  758.         ptl.x = x;
  759.         ptl.y = yL;
  760.         GpiMove(hps,&ptl);
  761.  
  762.         ptl.y = yH;
  763.         GpiLine(hps,&ptl);
  764.  
  765.         // Draw horizontal (close) bar
  766.  
  767.         GpiSetColor(hps,CLR_RED);
  768.  
  769.         ptl.x = x;
  770.         ptl.y = yC;
  771.         GpiMove(hps,&ptl);
  772.  
  773.         ptl.x += cxBar;
  774.         GpiLine(hps,&ptl);
  775.     }
  776.     WinSetPointer(HWND_DESKTOP,hptrNormal); // Tell user we are done
  777. }
  778.  
  779.  
  780. /***    AboutDlgProc - "About..." Dialog Procedure
  781. *
  782. */
  783. MRESULT EXPENTRY AboutDlgProc(HWND hwnd,USHORT msg,MPARAM mp1,MPARAM mp2)
  784. {
  785.     switch (msg) {
  786.     case WM_COMMAND:
  787.         switch (SHORT1FROMMP(mp1)) {
  788.         case DID_OK:
  789.             WinDismissDlg(hwnd,TRUE);
  790.             return FALSE;
  791.         }
  792.         break;
  793.     }
  794.     return WinDefDlgProc(hwnd,msg,mp1,mp2);
  795. }
  796.  
  797.  
  798. /***    PrinterSetupDlgProc - "File Printer Setup..." Dialog Procedure
  799. *
  800. */
  801. MRESULT EXPENTRY PrinterSetupDlgProc(HWND hwnd,USHORT msg,MPARAM mp1,MPARAM mp2)
  802. {
  803.     static BOOL     fNewJobProp;
  804.     HPRINTER        hprt;
  805.     HWND        hwndLB;
  806.     USHORT        i;
  807.     char *        pszName;
  808.     char *        pszNameDefault;
  809.  
  810.     switch (msg) {
  811.  
  812.     case WM_INITDLG:
  813.     fNewJobProp = FALSE;
  814.     hwndLB = WinWindowFromID(hwnd, IDL_PRINTER);
  815.     hprt = 0;            // Enumerate full list of printers
  816.     while ((hprt=PrintQueryNextPrinter(glb.hprtlist,hprt)) != NULL) {
  817.         pszName = (char *)PrintQueryPrinterInfo(hprt,PQPI_NAME);
  818.         // Insert item and store handle
  819.         i = SHORT1FROMMR(WinSendMsg(hwndLB, LM_INSERTITEM,
  820.                MPFROMSHORT(LIT_SORTASCENDING),MPFROMP(pszName)));
  821.         WinSendMsg(hwndLB,LM_SETITEMHANDLE,
  822.                       MPFROMSHORT(i),MPFROMP(hprt));
  823.         if (hprt == glb.hprt)    // This is the default printer
  824.         pszNameDefault = pszName; // Save name to set selection
  825.     }
  826.  
  827.     // Find default printer and set selection
  828.  
  829.     i = SHORT1FROMMR(WinSendMsg(hwndLB,LM_SEARCHSTRING,
  830.              MPFROM2SHORT(0,LIT_FIRST),MPFROMP(pszNameDefault)));
  831.     WinSendMsg(hwndLB,LM_SELECTITEM,MPFROMSHORT(i),MPFROMSHORT(TRUE));
  832.     break;
  833.  
  834.     case WM_COMMAND:
  835.     switch (SHORT1FROMMP(mp1)) {
  836.  
  837.     case DID_OK:
  838.         hprt = HPRTFromListBox(hwnd); // Get selection
  839.         if (hprt != glb.hprt) {    // Printer destination changed
  840.         glb.hprt = hprt;    // Remember new printer
  841.         fNewJobProp = TRUE;    // Force new job properties
  842.         }
  843.         glb.fNewJobProp = fNewJobProp; // User made change
  844.         SetFileMenu();
  845.         WinDismissDlg(hwnd,TRUE);
  846.         return FALSE;
  847.  
  848.     case IDB_SETUP:
  849.         hprt = HPRTFromListBox(hwnd); // Get selection
  850.         if (PrintChangeJobProperties(hprt)) // Properties changed
  851.         fNewJobProp = TRUE;    //  Remember JP changed
  852.         return FALSE;
  853.  
  854.     case IDB_RESET:
  855.         hprt = HPRTFromListBox(hwnd); // Get selection
  856.         PrintResetJobProperties(hprt); // Reset job properties
  857.         fNewJobProp = TRUE;     //  Remember JP changed
  858.         return FALSE;
  859.  
  860.     case DID_CANCEL:
  861.         WinDismissDlg(hwnd,FALSE);
  862.         return FALSE;
  863.     }
  864.     break;
  865.     }
  866.     return WinDefDlgProc(hwnd,msg,mp1,mp2);
  867. }
  868.  
  869.  
  870. /***    HPRTFromListBox - Get selected printer
  871.  *
  872.  *    Entry
  873.  *        hwnd - hwnd of Printer Setup dialog
  874.  *
  875.  *    Exit
  876.  *        hprt of selected printer
  877.  */
  878. HPRINTER HPRTFromListBox(HWND hwnd)
  879. {
  880.     HWND    hwndLB;
  881.     USHORT  i;
  882.  
  883.     // Get selection
  884.     hwndLB = WinWindowFromID(hwnd, IDL_PRINTER);
  885.     i = SHORT1FROMMR(WinSendDlgItemMsg(hwnd,IDL_PRINTER,LM_QUERYSELECTION,0L,0L));
  886.  
  887.     // Get printer handle
  888.  
  889.     return (HPRINTER) (ULONG)WinSendMsg(hwndLB,LM_QUERYITEMHANDLE,MPFROMSHORT(i),0L);
  890. }
  891.  
  892.  
  893. /***    SaveJobProperties - Save current job properties in EA on file
  894.  *
  895.  *    Entry
  896.  *        glb.hprt    - printer handle
  897.  *        glb.pszFile - file name
  898.  *
  899.  *    Exit
  900.  *        Job properties saved with file.
  901.  */
  902. VOID SaveJobProperties(VOID)
  903. {
  904.     static USHORT   cb;
  905.     char *        pb;
  906.  
  907.     if (!glb.fNewJobProp)        // Nothing to save
  908.     return;
  909.  
  910.     glb.fNewJobProp = FALSE;        // JP will be saved
  911.  
  912.     // Get job properties size
  913.  
  914.     WinSetPointer(HWND_DESKTOP,hptrWait); // Tell user we are being slow
  915.  
  916.     cb = 0;
  917.     PrintQueryJobProperties(glb.hprt,&cb,pb); // Get size
  918.     if (cb == 0)            // No job properties to save
  919.     return;             //  Done
  920.     pb = MemAlloc(cb);            // Alloc buffer
  921.     if (pb == NULL)            // Could not get memory
  922.     return;             //  Done
  923.  
  924.     // Get job properties
  925.  
  926.     if (!PrintQueryJobProperties(glb.hprt,&cb,pb)) { // failed
  927.     MemFree(pb);            // Free buffer
  928.     return;             //  Done
  929.     }
  930.  
  931.     // Save new Job Properties with data file
  932.  
  933.     EASetValue(glb.pszFile,pszJobProp,cb,pb);
  934.     MemFree(pb);            // Free buffer
  935.  
  936.     WinSetPointer(HWND_DESKTOP,hptrNormal); // Tell user we are done
  937. }
  938.  
  939.  
  940. /***    Message - Put up message box
  941.  *
  942.  *    Entry
  943.  *        psz  - message
  944.  *        hwnd - parent window
  945.  *
  946.  *    Exit
  947.  *        None
  948.  */
  949. VOID Message(char *psz, HWND hwnd)
  950. {
  951.     HWND    hwndOwner;
  952.  
  953.     if (hwnd == NULL) {
  954.     hwndOwner = glb.hwndClient;
  955.     if (hwndOwner == NULL)
  956.         hwndOwner = HWND_DESKTOP;
  957.     }
  958.     else
  959.     hwndOwner = hwnd;
  960.  
  961.     WinMessageBox(
  962.     HWND_DESKTOP,        // parent
  963.     hwndOwner,        // owner
  964.     psz,            // message
  965.     NULL,            // caption (use default)
  966.     NULL,            // window id
  967.     MB_OK | MB_APPLMODAL    // window style
  968.     );
  969. }
  970.  
  971.  
  972. /***    QueryHCI - Query hardcopy capabilities for current form
  973.  *
  974.  *    Entry
  975.  *        hdc - handle to DC
  976.  *        phci - pointer to HCINFO structure
  977.  *
  978.  *    Exit-Success
  979.  *        Returns TRUE
  980.  *
  981.  *    Exit-Failure
  982.  *        Returns FALSE
  983.  */
  984. BOOL QueryHCI(HDC hdc,HCINFO *phci)
  985. {
  986.     LONG    cForms;
  987.     LONG    i;
  988.     LONG    rc;
  989.  
  990.     cForms = DevQueryHardcopyCaps(hdc,0L,0L,phci); // Get form count
  991.     if (cForms == 0)
  992.     return FALSE;            // No forms!
  993.  
  994.     for (i=0; i<cForms; i++) {
  995.     rc = DevQueryHardcopyCaps(hdc,i,1L,phci); // Get info for this form
  996.     if (rc == 1) {            // Got info
  997.         if (phci->flAttributes & HCAPS_CURRENT) { // Have current form
  998.         return TRUE;        // Return data
  999.         }
  1000.     }
  1001.     }
  1002.     return FALSE;
  1003. }
  1004.