home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 19 Printer / 19-Printer.zip / PRNTCAL2.ZIP / PRINTCAL.C next >
C/C++ Source or Header  |  1991-07-08  |  17KB  |  519 lines

  1. /*---------------------------------------------------------------------
  2.    PRINTCAL.C -- OS/2 Presentation Manager program to print a calendar
  3.                  (c) 1990, Ziff Communications Co.
  4.          PC Magazine * Charles Petzold, 10/89
  5.  
  6.   Revised by Rex P. Warshell 07/91
  7.  
  8.          Revisions include the following:
  9.  
  10.          1. Converted to MS C6.0 Datatypes.
  11.          2. Display Day Names.
  12.          3. Include Printdc code for Default Device context
  13.             in zip file
  14.   ---------------------------------------------------------------------*/
  15.  
  16. #define INCL_WIN
  17. #define INCL_GPI
  18. #define INCL_DEV
  19. #define INCL_DOSPROCESS
  20. #include <os2.h>
  21. #include <process.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include "printcal.h"
  26.  
  27. #define LCID_CALFONT          1L
  28. #define STACKSIZE             (4096 * sizeof (int))
  29. #define WM_USER_PRINT_OK      (WM_USER + 0)
  30. #define WM_USER_PRINT_ERROR   (WM_USER + 1)
  31.  
  32. typedef struct
  33.      {
  34.      SHORT sYear, sMonthBeg, sMonthEnd ;
  35.      }
  36.      CALPARAMS ;
  37.  
  38. typedef struct
  39.      {
  40.      int       aiThreadStack[STACKSIZE / sizeof (int)] ;
  41.      CALPARAMS cp ;
  42.      HWND      hwndNotify ;
  43.      }
  44.      THREADPARAMS ;
  45.  
  46. MPARAM EXPENTRY ClientWndProc (HWND, USHORT, MPARAM, MPARAM) ;
  47. MPARAM EXPENTRY AboutDlgProc  (HWND, USHORT, MPARAM, MPARAM) ;
  48. MPARAM EXPENTRY PrintDlgProc  (HWND, USHORT, MPARAM, MPARAM) ;
  49. VOID            DisplayPage   (HPS, SIZEL *, SHORT, SHORT) ;
  50. VOID            Message       (HWND, SHORT, CHAR *) ;
  51. VOID   FAR      PrintThread   (THREADPARAMS *) ;
  52. HDC             OpenDefaultPrinterDC (HAB) ;           // in PRINTDC.C
  53.  
  54. HAB    hab ;
  55. USHORT usActiveThreads = 0 ;
  56.  
  57. int main (void)
  58.      {
  59.      static CHAR  szClientClass[] = "PrintCal" ;
  60.      static ULONG flFrameFlags = FCF_TITLEBAR      | FCF_SYSMENU |
  61.                                  FCF_SIZEBORDER    | FCF_MINMAX  |
  62.                                  FCF_MENU          |
  63.                                  FCF_SHELLPOSITION | FCF_TASKLIST ;
  64.      HMQ          hmq ;
  65.      HWND         hwndFrame, hwndClient ;
  66.      QMSG         qmsg ;
  67.  
  68.      hab = WinInitialize (0) ;
  69.      hmq = WinCreateMsgQueue (hab, 0) ;
  70.      WinRegisterClass (hab, szClientClass, ClientWndProc, CS_SIZEREDRAW, 0) ;
  71.  
  72.      hwndFrame = WinCreateStdWindow (HWND_DESKTOP, WS_VISIBLE,
  73.                                      &flFrameFlags, szClientClass, NULL,
  74.                      0L, (HMODULE)NULL, ID_RESOURCE, &hwndClient) ;
  75.      while (TRUE)
  76.           {
  77.           while (WinGetMsg (hab, &qmsg, NULL, 0, 0))
  78.                WinDispatchMsg (hab, &qmsg) ;
  79.  
  80.           if (usActiveThreads == 0)
  81.                break ;
  82.  
  83.           Message (hwndClient, MB_ICONEXCLAMATION,
  84.                    "Printing thread still active.\n"
  85.                    "Program cannot be closed now.") ;
  86.  
  87.           WinCancelShutdown (hmq, FALSE) ;
  88.           }
  89.  
  90.      WinDestroyWindow (hwndFrame) ;
  91.      WinDestroyMsgQueue (hmq) ;
  92.      WinTerminate (hab) ;
  93.      return 0 ;
  94.      }
  95.  
  96. MPARAM EXPENTRY ClientWndProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  97.      {
  98.      static CALPARAMS cp ;
  99.      static HPS       hps ;
  100.      static SIZEL     sizlClient ;
  101.      DATETIME         dt ;
  102.      HDC              hdc ;
  103.      SHORT            sResult ;
  104.      SIZEL            sizlPage ;
  105.      THREADPARAMS     *ptp ;
  106.  
  107.      switch (msg)
  108.           {
  109.           case WM_CREATE:
  110.                hdc = WinOpenWindowDC (hwnd) ;
  111.                sizlPage.cx = 0 ;
  112.                sizlPage.cy = 0 ;
  113.                hps = GpiCreatePS (hab, hdc, &sizlPage,
  114.                                   PU_ARBITRARY | GPIF_DEFAULT |
  115.                                   GPIT_MICRO   | GPIA_ASSOC) ;
  116.  
  117.                DosGetDateTime (&dt) ;
  118.                cp.sYear     = dt.year ;
  119.                cp.sMonthBeg = dt.month - 1 ;
  120.                cp.sMonthEnd = dt.month - 1 ;
  121.                return 0 ;
  122.  
  123.           case WM_SIZE:
  124.                sizlClient.cx = SHORT1FROMMP (mp2) ;
  125.                sizlClient.cy = SHORT2FROMMP (mp2) ;
  126.  
  127.                GpiConvert (hps, CVTC_DEVICE, CVTC_PAGE, 1L,
  128.                            (PPOINTL) &sizlClient) ;
  129.                return 0 ;
  130.  
  131.           case WM_PAINT:
  132.                WinBeginPaint (hwnd, hps, NULL) ;
  133.  
  134.                GpiErase (hps) ;
  135.                DisplayPage (hps, &sizlClient, cp.sYear, cp.sMonthBeg) ;
  136.  
  137.                WinEndPaint (hps) ;
  138.                return 0 ;
  139.  
  140.           case WM_COMMAND:
  141.                switch (COMMANDMSG(&msg)->cmd)
  142.                     {
  143.                     case IDM_ABOUT:
  144.                          WinDlgBox (HWND_DESKTOP, hwnd, AboutDlgProc,
  145.                     (HMODULE)NULL, IDD_ABOUT, NULL) ;
  146.                          return 0 ;
  147.  
  148.                     case IDM_PRINT:
  149.                          sResult = WinDlgBox (HWND_DESKTOP, hwnd, PrintDlgProc,
  150.                           (HMODULE)NULL, IDD_PRINT, &cp) ;
  151.  
  152.                          if (sResult == DID_CANCEL)
  153.                               return 0 ;
  154.  
  155.                          WinInvalidateRect (hwnd, NULL, FALSE) ;
  156.  
  157.                          if (sResult == IDD_PREVIEW)
  158.                               return 0 ;
  159.  
  160.                          if ((ptp = malloc (sizeof (THREADPARAMS))) == NULL)
  161.                               {
  162.                               Message (hwnd, MB_ICONEXCLAMATION,
  163.                                   "Cannot allocate memory for print thread!") ;
  164.                               return 0 ;
  165.                               }
  166.  
  167.                          ptp->cp         = cp ;
  168.                          ptp->hwndNotify = hwnd ;
  169.  
  170.                          if (_beginthread (PrintThread, ptp->aiThreadStack,
  171.                                            STACKSIZE, ptp) == -1)
  172.                               {
  173.                               free (ptp) ;
  174.                               Message (hwnd, MB_ICONEXCLAMATION,
  175.                                        "Cannot create print thread!") ;
  176.                               return 0 ;
  177.                               }
  178.  
  179.                          usActiveThreads++ ;
  180.                          Message (hwnd, MB_ICONASTERISK,
  181.                                   "Print job successfully started.") ;
  182.                          return 0 ;
  183.                     }
  184.                break ;
  185.  
  186.           case WM_USER_PRINT_OK:
  187.                ptp = PVOIDFROMMP (mp1) ;
  188.                free (ptp) ;
  189.                usActiveThreads-- ;
  190.                Message (hwnd, MB_ICONASTERISK,
  191.                         "Print job sent to spooler.") ;
  192.                return 0 ;
  193.  
  194.           case WM_USER_PRINT_ERROR:
  195.                ptp = PVOIDFROMMP (mp1) ;
  196.                free (ptp) ;
  197.                usActiveThreads-- ;
  198.                Message (hwnd, MB_ICONEXCLAMATION,
  199.                         "Error encountered during printing.") ;
  200.                return 0 ;
  201.  
  202.           case WM_DESTROY:
  203.                GpiDestroyPS (hps) ;
  204.                return 0 ;
  205.           }
  206.      return WinDefWindowProc (hwnd, msg, mp1, mp2) ;
  207.      }
  208.  
  209. MRESULT EXPENTRY AboutDlgProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  210.      {
  211.      switch (msg)
  212.           {
  213.           case WM_COMMAND:
  214.                switch (COMMANDMSG(&msg)->cmd)
  215.                     {
  216.                     case DID_OK:
  217.                     case DID_CANCEL:
  218.                          WinDismissDlg (hwnd, TRUE) ;
  219.                          return 0 ;
  220.                     }
  221.                break ;
  222.           }
  223.      return WinDefDlgProc (hwnd, msg, mp1, mp2) ;
  224.      }
  225.  
  226. MRESULT EXPENTRY PrintDlgProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  227.      {
  228.      static CALPARAMS cpLocal, *pcpCurrent ;
  229.  
  230.      switch (msg)
  231.           {
  232.           case WM_INITDLG:
  233.                pcpCurrent = PVOIDFROMMP (mp2) ;
  234.                cpLocal = *pcpCurrent ;
  235.  
  236.                WinSendDlgItemMsg (hwnd, IDD_MONTHBEG + cpLocal.sMonthBeg,
  237.                                   BM_SETCHECK, MPFROM2SHORT (TRUE, 0), NULL) ;
  238.  
  239.                WinSendDlgItemMsg (hwnd, IDD_MONTHEND + cpLocal.sMonthEnd,
  240.                                   BM_SETCHECK, MPFROM2SHORT (TRUE, 0), NULL) ;
  241.  
  242.                WinSendDlgItemMsg (hwnd, IDD_YEAR, EM_SETTEXTLIMIT,
  243.                                   MPFROM2SHORT (4, 0), NULL) ;
  244.  
  245.                WinSetDlgItemShort (hwnd, IDD_YEAR, cpLocal.sYear, FALSE) ;
  246.                return 0 ;
  247.  
  248.           case WM_CONTROL:
  249.                if (SHORT1FROMMP (mp1) >= IDD_MONTHBEG &&
  250.                    SHORT1FROMMP (mp1) <  IDD_MONTHBEG + 12)
  251.  
  252.                     cpLocal.sMonthBeg = SHORT1FROMMP (mp1) - IDD_MONTHBEG ;
  253.  
  254.                else if (SHORT1FROMMP (mp1) >= IDD_MONTHEND &&
  255.                         SHORT1FROMMP (mp1) <  IDD_MONTHEND + 12)
  256.  
  257.                     cpLocal.sMonthEnd = SHORT1FROMMP (mp1) - IDD_MONTHEND ;
  258.  
  259.                return 0 ;
  260.  
  261.           case WM_COMMAND:
  262.                switch (COMMANDMSG(&msg)->cmd)
  263.                     {
  264.                     case DID_OK:
  265.                     case IDD_PREVIEW:
  266.                          WinQueryDlgItemShort (hwnd, IDD_YEAR,
  267.                                                &cpLocal.sYear, FALSE) ;
  268.  
  269.                          if (cpLocal.sYear < 1900 || cpLocal.sYear > 2099)
  270.                               {
  271.                               Message (hwnd, MB_ICONEXCLAMATION,
  272.                                        "Year must be between 1900 and 2099!") ;
  273.                               WinSetFocus (HWND_DESKTOP,
  274.                                            WinWindowFromID (hwnd, IDD_YEAR)) ;
  275.                               return 0 ;
  276.                               }
  277.  
  278.                          if (cpLocal.sMonthBeg > cpLocal.sMonthEnd)
  279.                               {
  280.                               Message (hwnd, MB_ICONEXCLAMATION,
  281.                                        "Begin month cannot be later "
  282.                                        "than end month!") ;
  283.                               WinSetFocus (HWND_DESKTOP,
  284.                                    WinWindowFromID (hwnd,
  285.                                         IDD_MONTHBEG + cpLocal.sMonthBeg)) ;
  286.                               return 0 ;
  287.                               }
  288.  
  289.                          *pcpCurrent = cpLocal ;
  290.                                                        // fall through
  291.                     case DID_CANCEL:
  292.                          WinDismissDlg (hwnd, COMMANDMSG(&msg)->cmd) ;
  293.                          return 0 ;
  294.                     }
  295.                break ;
  296.           }
  297.      return WinDefDlgProc (hwnd, msg, mp1, mp2) ;
  298.      }
  299.  
  300. VOID DisplayPage (HPS hps, SIZEL *psizlPage, SHORT sYear, SHORT sMonth)
  301.      {
  302.      static CHAR  *apszMonths[]  = { "January", "February", "March",
  303.                                      "April",   "May",      "June",
  304.                                      "July",    "August",   "September",
  305.                      "October", "November", "December" } ;
  306.  
  307.  
  308.      static CHAR  *pszDays[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
  309.                 "Thursday", "Friday", "Saturday"};
  310.  
  311.  
  312.  
  313.      static SHORT asMonthLen[]   = { 31, 28, 31, 30, 31, 30,
  314.                      31, 31, 30, 31, 30, 31 } ;
  315.  
  316.      static SHORT asMonthStart[] = {  0,  3,  3,  6,  1,  4,
  317.                                       6,  2,  5,  0,  3,  5 } ;
  318.      CHAR         szBuffer[16] ;
  319.      BOOL         fLeap ;
  320.      FATTRS       fat ;
  321.      LONG         lLength ;
  322.      POINTL       ptl, aptlTextBox[TXTBOX_COUNT] ;
  323.      SHORT      sDayStart, sDay, sExtraDay, sTDay ;
  324.      SIZEF        sizfx ;
  325.      SIZEL        sizlCell ;
  326.  
  327.      GpiSavePS (hps) ;
  328.  
  329.                // Determine size of day cell
  330.  
  331.      sizlCell.cx = (psizlPage->cx - 1) / 7 ;
  332.      sizlCell.cy = (psizlPage->cy - 1) / 7 ;
  333.  
  334.                // Create the vector font and use it in the PS
  335.  
  336.      fat.usRecordLength  = sizeof fat ;
  337.      fat.fsSelection     = 0 ;
  338.      fat.lMatch          = 0 ;
  339.      fat.idRegistry      = 0 ;
  340.      fat.usCodePage      = GpiQueryCp (hps) ;
  341.      fat.lMaxBaselineExt = 0 ;
  342.      fat.lAveCharWidth   = 0 ;
  343.      fat.fsType          = 0 ;
  344.      fat.fsFontUse       = FATTR_FONTUSE_OUTLINE |
  345.                            FATTR_FONTUSE_TRANSFORMABLE ;
  346.  
  347.      strcpy (fat.szFacename, "Helv") ;
  348.  
  349.      GpiCreateLogFont (hps, NULL, LCID_CALFONT, &fat) ;
  350.  
  351.      GpiSetCharSet (hps, LCID_CALFONT) ;
  352.  
  353.                // Scale the font for the month and year name
  354.  
  355.      lLength = sprintf (szBuffer, " %s %d ", apszMonths[sMonth], sYear) ;
  356.  
  357.      GpiQueryTextBox (hps, lLength, szBuffer, TXTBOX_COUNT, aptlTextBox) ;
  358.  
  359.      GpiQueryCharBox (hps, &sizfx) ;
  360.  
  361.      sizfx.cx = sizlCell.cx * 7 / aptlTextBox[TXTBOX_CONCAT].x * sizfx.cx;
  362.  
  363.      sizfx.cy = sizlCell.cy * sizfx.cy / (aptlTextBox[TXTBOX_TOPLEFT].y -
  364.                                           aptlTextBox[TXTBOX_BOTTOMLEFT].y) ;
  365.  
  366.      sizfx.cx = sizfx.cy = min (sizfx.cx, sizfx.cy) ;
  367.  
  368.      GpiSetCharBox (hps, &sizfx) ;
  369.  
  370.      GpiQueryTextBox (hps, lLength, szBuffer, TXTBOX_COUNT, aptlTextBox) ;
  371.  
  372.                // Display month and year at top of page
  373.  
  374.      ptl.x = (psizlPage->cx - aptlTextBox[TXTBOX_CONCAT].x) / 2 ;
  375.  
  376.      ptl.y =  6 * sizlCell.cy - aptlTextBox[TXTBOX_BOTTOMLEFT].y ;
  377.  
  378.      GpiCharStringAt (hps, &ptl, lLength, szBuffer) ;
  379.  
  380.  
  381.      //Set Font for Day Names
  382.  
  383.  
  384.      sizfx.cx = sizfx.cy = MAKEFIXED (min((sizlCell.cx / 9),sizlCell.cy),0);
  385.  
  386.      GpiSetCharBox (hps, &sizfx) ;
  387.  
  388.  
  389.      //Display Day Names
  390.  
  391.  
  392.      for (sTDay = 0; sTDay < 7; sTDay++)
  393.      {
  394.  
  395.       lLength = sprintf(szBuffer, "%s", pszDays[sTDay]) ;
  396.  
  397.       GpiQueryTextBox (hps, lLength, szBuffer, TXTBOX_COUNT, aptlTextBox) ;
  398.  
  399.       ptl.x = ((sizlCell.cx * sTDay) + ((sizlCell.cx - aptlTextBox[TXTBOX_CONCAT].x) / 2));
  400.  
  401.       ptl.y = ((5 * sizlCell.cy) + ((sizlCell.cy - (aptlTextBox[TXTBOX_TOPLEFT].y -
  402.                             aptlTextBox[TXTBOX_BOTTOMLEFT].y)) / 2) );
  403.  
  404.       GpiCharStringAt (hps, &ptl, lLength, szBuffer);
  405.  
  406.       }
  407.  
  408.       // Set font size for day numbers
  409.  
  410.      sizfx.cx = sizfx.cy = MAKEFIXED (min (sizlCell.cx, sizlCell.cy) / 4, 0) ;
  411.  
  412.      GpiSetCharBox (hps, &sizfx) ;
  413.  
  414.       // Calculate some variables for showing days in month
  415.  
  416.      fLeap = (sYear % 4 == 0) && ((sYear % 100 != 0) || (sYear % 400 == 0)) ;
  417.      sExtraDay = fLeap && sMonth == 1 ? 1 : 0 ;
  418.  
  419.      sDayStart  = 1 + sYear - 1900 + (sYear - 1901) / 4 ;
  420.      sDayStart += asMonthStart[sMonth] + (fLeap && sMonth > 1 ? 1 : 0) ;
  421.      sDayStart %= 7 ;
  422.  
  423.                // Loop through days
  424.  
  425.      for (sDay = 0 ; sDay < asMonthLen[sMonth] + sExtraDay ; sDay++)
  426.           {
  427.           ptl.x =      (sDayStart + sDay) % 7  * sizlCell.cx ;
  428.       ptl.y = (4 - (sDayStart + sDay) / 7) * sizlCell.cy ;
  429.           GpiMove (hps, &ptl) ;
  430.  
  431.           ptl.x += sizlCell.cx ;
  432.           ptl.y += sizlCell.cy ;
  433.           GpiBox (hps, DRO_OUTLINE, &ptl, 0L, 0L) ;
  434.  
  435.       lLength = sprintf (szBuffer, " %d", sDay + 1) ;
  436.  
  437.           GpiQueryTextBox (hps, lLength, szBuffer, TXTBOX_COUNT, aptlTextBox) ;
  438.  
  439.       GpiQueryCurrentPosition (hps, &ptl) ;
  440.  
  441.       ptl.y += sizlCell.cy - aptlTextBox[TXTBOX_TOPLEFT].y ;
  442.  
  443.           GpiCharStringAt (hps, &ptl, lLength, szBuffer) ;
  444.           }
  445.                // Clean up
  446.  
  447.      GpiSetCharSet (hps, LCID_DEFAULT) ;
  448.      GpiDeleteSetId (hps, LCID_CALFONT) ;
  449.      GpiRestorePS (hps, -1L) ;
  450.      }
  451.  
  452. VOID Message (HWND hwnd, SHORT sIcon, CHAR *pszMessage)
  453.      {
  454.      WinMessageBox (HWND_DESKTOP, hwnd, pszMessage, "PrintCal",
  455.                     0, sIcon | MB_OK | MB_MOVEABLE) ;
  456.      }
  457.  
  458. VOID FAR PrintThread (THREADPARAMS *ptp)
  459.      {
  460.      HAB   hab ;
  461.      HDC   hdcPrinter ;
  462.      HPS   hpsPrinter ;
  463.      SHORT msgReturn ;
  464.      SHORT sMonth ;
  465.      SIZEL sizlPage ;
  466.  
  467.      hab = WinInitialize (0) ;
  468.  
  469.      if ((hdcPrinter = OpenDefaultPrinterDC (hab)) != DEV_ERROR)
  470.           {
  471.                     // Create the presentation space for the printer
  472.  
  473.           sizlPage.cx = 0 ;
  474.           sizlPage.cy = 0 ;
  475.           hpsPrinter = GpiCreatePS (hab, hdcPrinter, &sizlPage,
  476.                                     PU_ARBITRARY | GPIF_DEFAULT |
  477.                                     GPIT_MICRO   | GPIA_ASSOC) ;
  478.  
  479.           GpiQueryPS (hpsPrinter, &sizlPage) ;
  480.  
  481.                     // Start the document
  482.  
  483.           if (DevEscape (hdcPrinter, DEVESC_STARTDOC,
  484.                          8L, "Calendar", NULL, NULL) != DEVESC_ERROR)
  485.                {
  486.                         // Loop through months
  487.  
  488.                for (sMonth  = ptp->cp.sMonthBeg ;
  489.                     sMonth <= ptp->cp.sMonthEnd ; sMonth++)
  490.                     {
  491.                     DisplayPage (hpsPrinter, &sizlPage, ptp->cp.sYear, sMonth);
  492.  
  493.                     DevEscape (hdcPrinter, DEVESC_NEWFRAME,
  494.                                0L, NULL, NULL, NULL) ;
  495.                     }
  496.                          // End the document
  497.  
  498.                DevEscape (hdcPrinter, DEVESC_ENDDOC, 0L, NULL, NULL, NULL) ;
  499.                msgReturn = WM_USER_PRINT_OK ;
  500.                }
  501.           else
  502.                msgReturn = WM_USER_PRINT_ERROR ;
  503.  
  504.                     // Clean up
  505.  
  506.           GpiDestroyPS (hpsPrinter) ;
  507.           DevCloseDC (hdcPrinter) ;
  508.           }
  509.      else
  510.           msgReturn = WM_USER_PRINT_ERROR ;
  511.  
  512.                // Post message to client window and end thread
  513.  
  514.      DosEnterCritSec () ;
  515.      WinPostMsg (ptp->hwndNotify, msgReturn, MPFROMP (ptp), NULL) ;
  516.      WinTerminate (hab) ;
  517.      _endthread () ;
  518.      }
  519.