home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: WPS_PM / WPS_PM.zip / xfld085s.zip / helpers / gpih.c < prev    next >
C/C++ Source or Header  |  1999-02-23  |  13KB  |  397 lines

  1.  
  2. /*
  3.  *@@sourcefile gpih.c:
  4.  *      contains GPI helper functions that are
  5.  *      independent of a single application, i.e. these can be
  6.  *      used w/out the rest of the XFolder source in any PM
  7.  *      program.
  8.  *
  9.  *      Function prefixes (new with V0.81):
  10.  *      --  gpih*   GPI helper functions
  11.  *
  12.  *@@include #include <os2.h>
  13.  *@@include #include "gpih.h"
  14.  */
  15.  
  16. /*
  17.  *      Copyright (C) 1997-99 Ulrich Möller.
  18.  *      This file is part of the XFolder source package.
  19.  *      XFolder is free software; you can redistribute it and/or modify
  20.  *      it under the terms of the GNU General Public License as published
  21.  *      by the Free Software Foundation, in version 2 as it comes in the
  22.  *      "COPYING" file of the XFolder main distribution.
  23.  *      This program is distributed in the hope that it will be useful,
  24.  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  25.  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  26.  *      GNU General Public License for more details.
  27.  */
  28.  
  29. #define INCL_DOSDEVIOCTL
  30. #define INCL_DOS
  31. #define INCL_DOSERRORS
  32. #define INCL_WIN
  33. #define INCL_GPI
  34. #include <os2.h>
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #include <stdio.h>
  38. #include <sys/types.h>
  39. #include <sys/stat.h>
  40.  
  41. #include "winh.h"
  42. #include "gpih.h"
  43.  
  44. // array for querying device capabilities (gpihQueryDisplayCaps)
  45. LONG            DisplayCaps[CAPS_DEVICE_POLYSET_POINTS] = {0};
  46. BOOL            fCapsQueried = FALSE;
  47.  
  48. /*
  49.  *@@ gpihQueryDisplayCaps:
  50.  *      this returns certain device capabilities of
  51.  *      the Display device. ulIndex must be one of
  52.  *      the indices as described in DevQueryCaps.
  53.  *      This function will load all the device capabilities
  54.  *      only once and reuse them afterwards.
  55.  */
  56.  
  57. ULONG gpihQueryDisplayCaps(ULONG ulIndex)
  58. {
  59.     if (!fCapsQueried)
  60.     {
  61.         HPS hps = WinGetScreenPS(HWND_DESKTOP);
  62.         HDC hdc = GpiQueryDevice(hps);
  63.         DevQueryCaps(hdc, 0, CAPS_DEVICE_POLYSET_POINTS, &DisplayCaps[0]);
  64.     }
  65.  
  66.     return (DisplayCaps[ulIndex]);
  67. }
  68.  
  69. /*
  70.  *@@ gpihQueryLineSpacing:
  71.  *      this returns the optimal line spacing for text
  72.  *      output with the current HPS; this is computed
  73.  *      by evaluating those incredible FONTMETRICS
  74.  */
  75.  
  76. LONG gpihQueryLineSpacing(HPS hps,
  77.                           PSZ pszText)      // in:  text to output
  78. {
  79.     FONTMETRICS fm;
  80.     POINTL aptlText[TXTBOX_COUNT];
  81.     GpiQueryTextBox(hps, strlen(pszText), pszText,
  82.              TXTBOX_COUNT, (PPOINTL)&aptlText);
  83.  
  84.     if (GpiQueryFontMetrics(hps, sizeof(FONTMETRICS), &fm))
  85.         return ( (  fm.lMaxBaselineExt     // max vertical font space
  86.                    +fm.lExternalLeading)    // space advised by font designer
  87.                  // * 12 / 10
  88.                );
  89.     else
  90.         return (15);
  91. }
  92.  
  93. /*
  94.  *@@ gpihDraw3DFrame:
  95.  *      this draws a rectl in 3D style with a given line width;
  96.  *      if (fRaised), the 3D line is given a "raised" look,
  97.  *      "sunken" otherwise
  98.  */
  99.  
  100. VOID gpihDraw3DFrame(HPS hps,
  101.                      PRECTL prcl,       // in:  rectangle
  102.                      USHORT usWidth,    // in:  line width (>= 1)
  103.                      BOOL fRaised)      // in:  TRUE for "raised", FALSE "sunken"
  104. {
  105.     RECTL rcl2 = *prcl;
  106.     LONG lColorLeft, lColorRight;
  107.     USHORT us;
  108.     POINTL ptl1;
  109.  
  110.     if (fRaised) {
  111.         lColorLeft = WinQuerySysColor(HWND_DESKTOP, SYSCLR_BUTTONLIGHT, 0);
  112.         lColorRight = WinQuerySysColor(HWND_DESKTOP, SYSCLR_BUTTONDARK, 0);
  113.     } else {
  114.         lColorLeft = WinQuerySysColor(HWND_DESKTOP, SYSCLR_BUTTONDARK, 0);
  115.         lColorRight = WinQuerySysColor(HWND_DESKTOP, SYSCLR_BUTTONLIGHT, 0);
  116.     }
  117.  
  118.     for (us = 0; us < usWidth; us++)
  119.     {
  120.         GpiSetColor(hps, lColorLeft);
  121.         ptl1.x = rcl2.xLeft;
  122.         ptl1.y = rcl2.yBottom;
  123.         GpiMove(hps, &ptl1);
  124.         ptl1.y = rcl2.yTop-1;
  125.         GpiLine(hps, &ptl1);
  126.         ptl1.x = rcl2.xRight-1;
  127.         GpiLine(hps, &ptl1);
  128.         GpiSetColor(hps, lColorRight);
  129.         ptl1.y = rcl2.yBottom;
  130.         GpiLine(hps, &ptl1);
  131.         ptl1.x = rcl2.xLeft;
  132.         GpiLine(hps, &ptl1);
  133.  
  134.         rcl2.xLeft++;
  135.         rcl2.yBottom++;
  136.         rcl2.xRight--;
  137.         rcl2.yTop--;
  138.     }
  139. }
  140.  
  141.  
  142. /*
  143.  *@@ gpihCreateMemPS:
  144.  *      creates a memory device context and presentation space so
  145.  *      they are compatible with the screen device context and
  146.  *      presentation space. These are stored in *hdcMem and *hpsMem.
  147.  *      You must free these with GpiDestroyPS(hpsMem) and
  148.  *      DevCloseDC(hdcMem) when you don't need these any more.
  149.  *      Returns FALSE upon errors.
  150.  */
  151.  
  152. BOOL gpihCreateMemPS(HAB hab,        // in: anchor block
  153.                     HDC *hdcMem,     // out: memory DC
  154.                     HPS *hpsMem)     // out: memory PS
  155. {
  156.     BOOL brc = FALSE;
  157.     PSZ pszData[4] = { "Display", NULL, NULL, NULL };
  158.     SIZEL sizlPage = {0, 0};
  159.  
  160.     if (*hdcMem = DevOpenDC(hab,
  161.                             OD_MEMORY,
  162.                             "*", 4,
  163.                             (PDEVOPENDATA)pszData,
  164.                             NULLHANDLE))
  165.         if (*hpsMem = GpiCreatePS(hab, *hdcMem,
  166.                                     &sizlPage,
  167.                                     PU_PELS | GPIA_ASSOC | GPIT_MICRO))
  168.             brc = TRUE;
  169.         else
  170.             // error: close memory DC again
  171.             DevCloseDC(*hdcMem);
  172.  
  173.     return (brc);
  174. }
  175.  
  176. /*
  177.  *@@ gpihCreateBitmap:
  178.  *      creates a new bitmap for a given memory PS.
  179.  *      This new bitmap has the size specified in *prcl.
  180.  *      Note that the bitmap is _not_ selected in the mem PS.
  181.  *      Returns the bitmap handle or NULLHANDLE upon errors.
  182.  */
  183.  
  184. HBITMAP gpihCreateBitmap(HPS hpsMem,        // memory DC
  185.                          PRECTL prcl)       // size of bitmap
  186. {
  187.     HBITMAP hbm = NULLHANDLE;
  188.     LONG alData[2];
  189.     BITMAPINFOHEADER2 bmp;
  190.     PBITMAPINFO2 pbmi = NULL;
  191.  
  192.     // determine the device's plane/bit-count format.
  193.     if (GpiQueryDeviceBitmapFormats(hpsMem, 2, alData))
  194.     {
  195.         // set up the BITMAPINFOHEADER2 and BITMAPINFO2 structures
  196.         bmp.cbFix = (ULONG)sizeof(BITMAPINFOHEADER2);
  197.         bmp.cx = (prcl->xRight - prcl->xLeft);
  198.         bmp.cy = (prcl->yTop - prcl->yBottom);
  199.         bmp.cPlanes = alData[0];
  200.         bmp.cBitCount = alData[1];
  201.         bmp.ulCompression = BCA_UNCOMP;
  202.         bmp.cbImage = (((bmp.cx *
  203.             (1 << bmp.cPlanes) * (1 << bmp.cBitCount)) + 31) / 32) * bmp.cy;
  204.         bmp.cxResolution = 70;
  205.         bmp.cyResolution = 70;
  206.         bmp.cclrUsed = 2;
  207.         bmp.cclrImportant = 0;
  208.         bmp.usUnits = BRU_METRIC;
  209.         bmp.usReserved = 0;
  210.         bmp.usRecording = BRA_BOTTOMUP;
  211.         bmp.usRendering = BRH_NOTHALFTONED;
  212.         bmp.cSize1 = 0;
  213.         bmp.cSize2 = 0;
  214.         bmp.ulColorEncoding = BCE_RGB;
  215.         bmp.ulIdentifier = 0;
  216.  
  217.         // allocate memory for info header
  218.         if (DosAllocMem((PPVOID)&pbmi, sizeof(BITMAPINFO2) +
  219.             (sizeof(RGB2) * (1 << bmp.cPlanes) * (1 << bmp.cBitCount)),
  220.             PAG_COMMIT | PAG_READ | PAG_WRITE) == NO_ERROR)
  221.         {
  222.             pbmi->cbFix = bmp.cbFix;
  223.             pbmi->cx = bmp.cx;
  224.             pbmi->cy = bmp.cy;
  225.             pbmi->cPlanes = bmp.cPlanes;
  226.             pbmi->cBitCount = bmp.cBitCount;
  227.             pbmi->ulCompression = BCA_UNCOMP;
  228.             pbmi->cbImage = ((bmp.cx+31)/32) * bmp.cy;
  229.             pbmi->cxResolution = 70;
  230.             pbmi->cyResolution = 70;
  231.             pbmi->cclrUsed = 2;
  232.             pbmi->cclrImportant = 0;
  233.             pbmi->usUnits = BRU_METRIC;
  234.             pbmi->usReserved = 0;
  235.             pbmi->usRecording = BRA_BOTTOMUP;
  236.             pbmi->usRendering = BRH_NOTHALFTONED;
  237.             pbmi->cSize1 = 0;
  238.             pbmi->cSize2 = 0;
  239.             pbmi->ulColorEncoding = BCE_RGB;
  240.             pbmi->ulIdentifier = 0;
  241.  
  242.             // Create a bit map that is compatible with the display.
  243.             hbm = GpiCreateBitmap(hpsMem, &bmp, FALSE, NULL, pbmi);
  244.  
  245.             // free the memory we allocated previously; GPI has
  246.             // allocated all the resources it needs itself, so
  247.             // we can release this
  248.             DosFreeMem(pbmi);
  249.         }
  250.     }
  251.  
  252.     return (hbm);
  253. }
  254.  
  255. /*
  256.  *@@ gpihCreateBmpFromPS:
  257.  *      this creates a new bitmap, which is compatible with the
  258.  *      device associated with hpsScreen, and then copies the
  259.  *      rectangle prcl into it; returns the handle of the bitmap,
  260.  *      which can then be used for WinDrawBitmap and such
  261.  */
  262.  
  263. HBITMAP gpihCreateBmpFromPS(HAB hab,        // in: anchor block
  264.                             HPS hpsScreen,  // in: screen PS to copy from
  265.                             PRECTL prcl)    // in: rectangle to copy
  266. {
  267.  
  268.     /* To copy an image from a display screen to a bit map:
  269.       1. Associate the memory device context with a presentation space.
  270.       2. Create a bit map.
  271.       3. Select the bit map into the memory device context by calling GpiSetBitmap.
  272.       4. Determine the location (in device coordinates) of the image.
  273.       5. Call GpiBitBlt and copy the image to the bit map. */
  274.  
  275.     HDC hdcMem;
  276.     // PSZ pszData[4] = { "Display", NULL, NULL, NULL };
  277.     HPS hpsMem;
  278.     HBITMAP hbm = NULLHANDLE;
  279.     POINTL aptl[3];
  280.  
  281.     if (gpihCreateMemPS(hab, &hdcMem, &hpsMem))
  282.     {
  283.         if (hbm = gpihCreateBitmap(hpsMem, prcl))
  284.         {
  285.             // Associate the bit map and the memory presentation space.
  286.             if (GpiSetBitmap(hpsMem, hbm)
  287.                     != HBM_ERROR)
  288.             {
  289.                 // Copy the screen to the bit map.
  290.                 aptl[0].x = 0;              // lower-left corner of destination rectangle
  291.                 aptl[0].y = 0;
  292.                 aptl[1].x = prcl->xRight;   // upper-right corner for both
  293.                 aptl[1].y = prcl->yTop;
  294.                 aptl[2].x = prcl->xLeft;    // lower-left corner of source rectangle
  295.                 aptl[2].y = prcl->yBottom;
  296.  
  297.                 if (GpiBitBlt(hpsMem, hpsScreen,
  298.                         sizeof(aptl) / sizeof(POINTL), // Number of points in aptl
  299.                         aptl,
  300.                         ROP_SRCCOPY,
  301.                         BBO_IGNORE) == GPI_ERROR)
  302.                 {
  303.                     // error during bitblt:
  304.                     GpiDeleteBitmap(hbm);
  305.                     hbm = NULLHANDLE; // for return code
  306.                 }
  307.             } else {
  308.                 // error selecting bitmap for hpsMem:
  309.                 GpiDeleteBitmap(hbm);
  310.                 hbm = NULLHANDLE; // for return code
  311.             }
  312.         }
  313.  
  314.         GpiDestroyPS(hpsMem);
  315.         DevCloseDC(hdcMem);
  316.     } // end if (hdcMem = DevOpenDC())
  317.  
  318.     return (hbm);
  319. }
  320.  
  321. /*
  322.  *@@ gpihLoadBitmapFile:
  323.  *      this loads the specified bitmap file into
  324.  *      the given HPS. Note that the bitmap is _not_
  325.  *      selected into the HPS yet.
  326.  *
  327.  *      This function can only handle OS/2 1.3 bitmaps.
  328.  *      Returns the new bitmap handle or NULL upon errors.
  329.  *      In the latter case, *pulError is set to one of
  330.  *      the following:
  331.  *      --  -1:      file not found
  332.  *      --  -2:      memory allocation failed
  333.  *      --  -3:      the bitmap data could not be loaded
  334.  *      --  -4:      file format not recognized
  335.  *      --  -5:      GpiCreateBitmap error
  336.  */
  337.  
  338. HBITMAP gpihLoadBitmapFile(HPS hps,             // in: HPS for bmp
  339.                            PSZ pszBmpFile,      // in: bitmap filename
  340.                            PULONG pulError)     // out: set to error
  341. {
  342.     HBITMAP hbm;
  343.     PBITMAPFILEHEADER2  pbfh;
  344.  
  345.     struct stat st;
  346.     PUCHAR      pBmpData;
  347.     FILE        *BmpFile;
  348.     PUCHAR      fn = "loadData";
  349.  
  350.     if (stat(pszBmpFile, &st) == 0)
  351.     {
  352.  
  353.         if ((pBmpData = malloc(st.st_size)))
  354.         {
  355.             // open bmp file
  356.             if ((BmpFile = fopen(pszBmpFile, "rb")))
  357.             {
  358.                 // read bmp data
  359.                 fread(pBmpData, 1, st.st_size, BmpFile);
  360.                 fclose(BmpFile);
  361.  
  362.                 // check bitmap magic codes
  363.                 if (pBmpData[0] == 'B' && pBmpData[1] == 'M')
  364.                 {
  365.                     pbfh = (PBITMAPFILEHEADER2)pBmpData;
  366.                     hbm = GpiCreateBitmap(hps,
  367.                                 &pbfh->bmp2,
  368.                                 CBM_INIT,
  369.                                 (pBmpData + pbfh->offBits),
  370.                                 (PBITMAPINFO2)&pbfh->bmp2);
  371.  
  372.                     if (hbm == NULLHANDLE)
  373.                     {
  374.                         if (pulError)
  375.                         *pulError = -5;
  376.                     }
  377.                 }
  378.                 else if (pulError)
  379.                         *pulError = -4;
  380.  
  381.             }
  382.             else if (pulError)
  383.                     *pulError = -3;
  384.  
  385.             free(pBmpData);
  386.         }
  387.         else if (pulError)
  388.                 *pulError = -2;
  389.     }
  390.     else if (pulError)
  391.             *pulError = -1;
  392.  
  393.     return (hbm);
  394. }
  395.  
  396.  
  397.