home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mavcl130.zip / MAVPRINT.CPP < prev    next >
Text File  |  1996-01-27  |  25KB  |  921 lines

  1. /*  File: MAVPRINT.CPP      Updated: Tue Aug 15 15:54:33 1995
  2. Copyright (c) Fabrizio Aversa
  3. ===========================================================*/
  4. #define INCL_DEV
  5. #define INCL_PM
  6. #define INCL_SPLDOSPRINT
  7. #include <os2.h>
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12.  
  13. #include <IString.hpp>
  14.  
  15. #include <iframe.hpp>
  16.  
  17. #include "mavprint.hpp"
  18.  
  19. MavPrint::MavPrint()
  20. {
  21.    pSetup = new PRINTERSETUP;
  22.    memset(pSetup, '\0', sizeof(PRINTERSETUP));
  23.  
  24.    usFontSize = new USHORT[255];
  25.    memset(usFontSize, '\0', 255 * sizeof(USHORT));
  26.  
  27.    lLcIdCount = 0;
  28.  
  29.    rctMargins.xLeft = 0;
  30.    rctMargins.xRight = 0;
  31.    rctMargins.yTop = 0;
  32.    rctMargins.yBottom = 0;
  33.  
  34.    sizMarginedPage.cx = 0;
  35.    sizMarginedPage.cy = 0;
  36.  
  37.    sizPage.cx = 0;
  38.    sizPage.cy = 0;
  39.  
  40.    sizHeader.cx = 0;
  41.    sizHeader.cy = 0;
  42.  
  43.    sizFooter.cx = 0;
  44.    sizFooter.cy = 0;
  45.  
  46. }
  47.  
  48. MavPrint::~MavPrint()
  49. {
  50.    delete pSetup;
  51.    delete usFontSize;
  52. }
  53.  
  54. Boolean MavPrint::setMargins(LONG lxLeft, LONG lxRight, LONG lyTop, LONG lyBottom)
  55. /* set margins, checks that margins are smaller than the page itself / 2 */
  56. {
  57.  
  58.    sizMarginedPage.cx = 0;
  59.    sizMarginedPage.cy = 0;
  60.  
  61.    sizPage.cx = 0;
  62.    sizPage.cy = 0;
  63.  
  64.    if(!GpiQueryPS( hps, &sizPage )) return FALSE;
  65.  
  66.    /* check if margins are too big */
  67.    if (
  68.    sizPage.cx / 2 - lxRight - lxLeft < 0
  69.    ||
  70.    sizPage.cy / 2 - lyTop - lyBottom < 0
  71.    ) return FALSE;
  72.  
  73.    rctMargins.xLeft = lxLeft;
  74.    rctMargins.xRight = lxRight;
  75.    rctMargins.yTop = lyTop;
  76.    rctMargins.yBottom = lyBottom;
  77.  
  78.    sizMarginedPage.cx = sizPage.cx - rctMargins.xLeft - rctMargins.xRight;
  79.    sizMarginedPage.cy = sizPage.cy - rctMargins.yTop - rctMargins.yBottom;
  80.  
  81.    /* header and footer sizes are defined as the margins */
  82.    sizHeader.cx = sizMarginedPage.cx;
  83.    sizHeader.cy = rctMargins.yTop - 1;
  84.  
  85.    sizFooter.cx = sizMarginedPage.cx;
  86.    sizFooter.cy = rctMargins.yBottom - 1;
  87.  
  88.    return TRUE;
  89. }
  90.  
  91. Boolean MavPrint::openPrinterJob(PSZ pszJobTitle)
  92. {
  93.    hdc = DevOpenDC( pSetup->hab, pSetup->lDCType, "*",
  94.    9, pSetup->pDevOpenData, (HDC)0 );
  95.  
  96.    if ( hdc == NULLHANDLE )
  97.    return FALSE;
  98.  
  99.    SIZEL sizel;
  100.  
  101.    sizel.cx = 0;
  102.    sizel.cy = 0;
  103.    hps = GpiCreatePS( pSetup->hab,
  104.    hdc,
  105.    &sizel,
  106.    pSetup->lWorldCoordinates | GPIF_DEFAULT | GPIT_NORMAL | GPIA_ASSOC );
  107.  
  108.    if( GPI_ERROR ==  hps ) {
  109.       DevCloseDC( hdc );
  110.       hdc = (HDC)0;
  111.       hps = (HPS)0;
  112.       return FALSE;
  113.    }
  114.  
  115.    DevEscape(hdc, DEVESC_STARTDOC,
  116.    strlen(pszJobTitle),
  117.    pszJobTitle,
  118.    NULL,
  119.    NULL);
  120.  
  121.    /* default margins 0 */
  122.    if(!setMargins(0, 0, 0, 0)) return FALSE;
  123.  
  124.    if(!GpiSetCharMode(hps, CM_MODE2)) return FALSE;
  125.    if(!GpiSetTextAlignment(hps, TA_NORMAL_HORIZ, TA_NORMAL_VERT)) return FALSE;
  126.  
  127.    return TRUE;
  128. }
  129.  
  130. void MavPrint::abortPrinterJob()
  131. {
  132.    DevEscape( hdc, DEVESC_ABORTDOC, 0, NULL, NULL, NULL );
  133.  
  134.    if( hps )
  135.    {
  136.       GpiSetCharSet( hps, 0 );
  137.       while (lLcIdCount) GpiDeleteSetId( hps, lLcIdCount-- );
  138.       GpiAssociate( hps, (HDC)0 );
  139.       GpiDestroyPS( hps );
  140.       hps = (HPS)0;
  141.    }
  142.  
  143.    if( hdc )
  144.    {
  145.       DevCloseDC( hdc );
  146.       hdc = (HDC)0;
  147.    }
  148.  
  149. }
  150.  
  151. void MavPrint::closePrinterJob()
  152. {
  153.  
  154.    /* end doc */
  155.    DevEscape( hdc, DEVESC_ENDDOC, 0, NULL, NULL, NULL );
  156.  
  157.    /* Close DC and PS */
  158.  
  159.    if( hps )
  160.    {
  161.       GpiSetCharSet( hps, 0 );
  162.       while (lLcIdCount) GpiDeleteSetId( hps, lLcIdCount-- );
  163.       GpiAssociate( hps, (HDC)0 );
  164.       GpiDestroyPS( hps );
  165.       hps = (HPS)0;
  166.    }
  167.  
  168.    if( hdc )
  169.    {
  170.       DevCloseDC( hdc );
  171.       hdc = (HDC)0;
  172.    }
  173.  
  174. }
  175.  
  176. Boolean MavPrint::newPage()
  177. {
  178.    if(hdc) {
  179.       if(
  180.       DevEscape( hdc, DEVESC_NEWFRAME, 0, NULL, NULL, NULL ) == DEV_OK
  181.       ) return TRUE;
  182.    }
  183.  
  184.    return FALSE;
  185.  
  186. }
  187.  
  188.  
  189. PRECTL MavPrint::rectlInMargins(PRECTL recSource, PRECTL rec)
  190. /* recSource is in margin coords, it is returned in page coords */
  191. {
  192.    rec->xLeft = recSource->xLeft + rctMargins.xLeft;
  193.    rec->xRight = recSource->xRight + rctMargins.xLeft;
  194.    rec->yTop = recSource->yTop + rctMargins.yBottom;
  195.    rec->yBottom = recSource->yBottom + rctMargins.yBottom;
  196.  
  197.    return rec;
  198. }
  199.  
  200. PPOINTL MavPrint::coordsInMargins(PPOINTL pntSource, PPOINTL pnt)
  201. /* pnt1 is in margin coords, it is returned in page coords */
  202. {
  203.    pnt->x = pntSource->x + rctMargins.xLeft;
  204.    pnt->y = pntSource->y + rctMargins.yBottom;
  205.  
  206.    return pnt;
  207. }
  208.  
  209. PPOINTL MavPrint::coordsInHeader(PPOINTL pntSource, PPOINTL pnt)
  210. /* pnt1 is in header coords, it is returned in page coords */
  211. {
  212.    pnt->x = pntSource->x + rctMargins.xLeft;
  213.    pnt->y = pntSource->y + sizPage.cy - rctMargins.yTop;
  214.  
  215.    return pnt;
  216. }
  217.  
  218. PPOINTL MavPrint::coordsInFooter(PPOINTL pntSource, PPOINTL pnt)
  219. /* pnt1 is in footer coords, it is returned in page coords */
  220. {
  221.    pnt->x = pntSource->x + rctMargins.xLeft;
  222.    pnt->y = pntSource->y;
  223.  
  224.    return pnt;
  225. }
  226.  
  227. Boolean MavPrint::printStringAt(PPOINTL pnt, PSZ string, LONG len)
  228. /* print a string at a point given in page coords
  229. if len is given (world coords) it is used to clip text */
  230. {
  231.    IString str = string;
  232.    return printStringAt(pnt, str, len);
  233. }
  234.  
  235. Boolean MavPrint::printStringAt(PPOINTL pnt, IString & string, LONG len)
  236. /* print a string at a point given in page coords
  237. if len is given (world coords) it is used to clip text */
  238. {
  239.    /* coords check (rough) */
  240.    if (
  241.    pnt->y < 0 || pnt->y > sizPage.cy ||
  242.    pnt->x < 0 || pnt->x > sizPage.cx
  243.    ) {
  244.       return FALSE;
  245.    }
  246.  
  247.    if (len == 0) {
  248.  
  249.       if(GpiCharStringAt( hps, pnt, string.length(), (PSZ)string ) != GPI_OK) {
  250.          return FALSE;
  251.       }
  252.  
  253.    } else {
  254.  
  255.       /* define clipping region (bigger than needed at left-top-bottom) */
  256.       RECTL rec;
  257.       rec.xLeft = pnt->x  - len; /* string may be aligned center or right */
  258.       rec.yBottom = pnt->y  - fm.lMaxBaselineExt;
  259.       rec.xRight = pnt->x + len;
  260.       rec.yTop = pnt->y + fm.lMaxBaselineExt;
  261.  
  262.       if(rec.xLeft < 0) rec.xLeft = 0;
  263.       if(rec.yBottom < 0) rec.yBottom = 0;
  264.       if(rec.yTop > sizPage.cy) rec.yTop = sizPage.cy;
  265.       if(rec.xRight > sizPage.cx) rec.xRight = sizPage.cx;
  266.  
  267.       if(GpiCharStringPosAt( hps, pnt, &rec, CHS_CLIP,
  268.       string.length(), (PSZ)string, NULL ) != GPI_OK) {
  269.          return FALSE;
  270.       }
  271.  
  272.    } /* endif */
  273.  
  274.    return TRUE;
  275.  
  276. }
  277.  
  278. Boolean MavPrint::printTextInBox(PRECTL prct,
  279. PSZ string, LONG & lWordsNotWritten, USHORT usShrink,
  280. LONG lControl, LONG lRound)
  281. {
  282.    IString str = string;
  283.    return printTextInBox(prct, str, lWordsNotWritten, usShrink,
  284.    lControl, lRound);
  285. }
  286.  
  287. Boolean MavPrint::printTextInBox(PRECTL prct,
  288. IString & string, LONG & lWordsNotWritten, USHORT usShrink,
  289. LONG lControl, LONG lRound)
  290. /*
  291. print a text in a rectangle.
  292. \n are considered.
  293. if text does not fit lWordsNotWritten returns the number of words left out.
  294. On exit prct contains the area used (may be less than maximum allowed
  295. depending on text length, in this case rectangle is lowered)
  296. lControl is the parameter of GpiBox
  297. lRound is the corner rounding axis of an ellipse as in GpiBox
  298. All coords in world coords
  299. usShrink = 0: do not shrink rectangle round text
  300. usShrink = 1: shrink rectangle round text
  301. usShrink = 2: shrink rectangle round text only vertically
  302. */
  303. {
  304.  
  305.    /* coords check */
  306.    if (
  307.    prct->yBottom >= prct->yTop || prct->xLeft >= prct->xRight ||
  308.    prct->yBottom < 0 || prct->yTop > sizPage.cy ||
  309.    prct->xRight < 0 || prct->xLeft > sizPage.cx
  310.    ) {
  311.       return FALSE;
  312.    }
  313.  
  314.    POINTL pnt;
  315.    LONG lMargin = (prct->xRight - prct->xLeft) / 30;
  316.  
  317.    if(string.strip().length()) {
  318.  
  319.       LONG lAvailableLineLen = prct->xRight - prct->xLeft -2*lMargin;
  320.  
  321.       /* pnt is beginning of line (x never changes but depends on alignment
  322.       if box is not shrinkable) */
  323.       LONG lHorizAlignment, lVertAlignment;
  324.       if(!GpiQueryTextAlignment(hps, &lHorizAlignment, &lVertAlignment)) return FALSE;
  325.  
  326.       /* default left margin */
  327.       pnt.x = lMargin + prct->xLeft;
  328.  
  329.       if(usShrink != 1 && lHorizAlignment != TA_NORMAL_HORIZ) {
  330.  
  331.          switch(lHorizAlignment) {
  332.  
  333.             case TA_RIGHT:
  334.             pnt.x = prct->xRight - lMargin;
  335.             break;
  336.  
  337.             case TA_CENTER:
  338.             pnt.x = prct->xLeft + (prct->xRight - prct->xLeft) / 2;
  339.             break;
  340.  
  341.          }
  342.  
  343.       }
  344.  
  345.       /* top margin = margin + first line space */
  346.       pnt.y = prct->yTop - fm.lMaxBaselineExt;
  347.  
  348.       IString strLine = "";
  349.  
  350.       USHORT usNewLineRequest;
  351.       USHORT i = 1;
  352.       LONG lMaxLineWidth = 0;
  353.       LONG lLineWidth;
  354.  
  355.       for(;;) {
  356.  
  357.          strLine +=  string.word(i);
  358.  
  359.          /* copy separators and see if new line
  360.          is requested (\n) at the end of this word */
  361.          USHORT index = string.indexOfWord(i) + string.word(i).length();
  362.  
  363.          usNewLineRequest = 0;
  364.          while (index < string.indexOfWord(i+1)) {
  365.  
  366.             if ( string[index] == 13 || string[index] == '\n') {
  367.                index++;
  368.                usNewLineRequest++;
  369.                if(string[index] == 10) index++;
  370.             }
  371.  
  372.             /* append separators (spaces) up to 1st cr+lf */
  373.             if(!usNewLineRequest) strLine +=  string[index];
  374.  
  375.             index ++;
  376.  
  377.          } /* endwhile */
  378.  
  379.          /* force new line (print) if end of string */
  380.          if(i == string.numWords()) usNewLineRequest = TRUE;
  381.  
  382.          POINTL ptlString[TXTBOX_COUNT];
  383.  
  384.          GpiQueryTextBox(hps,
  385.          strLine.length(), (PSZ)strLine,
  386.          TXTBOX_COUNT,  /* return maximum information */
  387.          ptlString);         /* array of coordinates points in world coordinates */
  388.  
  389.          if( ptlString[3].x -  ptlString[1].x > lAvailableLineLen
  390.          || usNewLineRequest) {
  391.             /* string exeedes available space or new line request */
  392.  
  393.             if(strLine.numWords() > 1 &&
  394.             ptlString[3].x -  ptlString[1].x > lAvailableLineLen) {
  395.                /* strip last word, if more than one present in strLine */
  396.  
  397.                i--;
  398.  
  399.                strLine =strLine.words(1, strLine.numWords() - 1);
  400.  
  401.                /* cancel any newline request that would be shifted up the
  402.                word we are clipping */
  403.                usNewLineRequest = 0;
  404.             }
  405.  
  406.             /* calc line width */
  407.             GpiQueryTextBox(hps,
  408.             strLine.length(), (PSZ)strLine,
  409.             TXTBOX_COUNT,  /* return maximum information */
  410.             ptlString);         /* array of coordinates points in world coordinates */
  411.  
  412.             /* update  lMaxLineWidth */
  413.             if( (lLineWidth = ptlString[3].x -  ptlString[1].x) > lMaxLineWidth)
  414.             lMaxLineWidth = lLineWidth;
  415.  
  416.             if(! printStringAt(&pnt, strLine, lAvailableLineLen ) ) return FALSE;
  417.  
  418.             if(i == string.numWords()) {
  419.                break;
  420.             }
  421.  
  422.             strLine = "";
  423.  
  424.             LONG lVertMove = fm.lMaxBaselineExt *
  425.             (1 + (usNewLineRequest ? usNewLineRequest -1 : 0));
  426.  
  427.             if(pnt.y - lVertMove < prct->yBottom + lMargin) break;
  428.  
  429.             pnt.y -= lVertMove;
  430.  
  431.          }
  432.  
  433.          i++;
  434.  
  435.       }
  436.  
  437.       lWordsNotWritten = string.numWords() - i;
  438.  
  439.       if(usShrink == 1) {
  440.          /* horizontal shrink request */
  441.          prct->xRight = prct->xLeft + lMaxLineWidth + lMargin*2;
  442.       }
  443.  
  444.       if(usShrink != 0) {
  445.          /* update prct->yBottom with actual values after text print */
  446.          prct->yBottom = pnt.y - lMargin;
  447.       }
  448.  
  449.    } else {
  450.  
  451.       lWordsNotWritten = 0;
  452.  
  453.       /* calc a rectangle of the right measures */
  454.       if(usShrink != 0) {
  455.          prct->yBottom = prct->yTop - fm.lMaxBaselineExt;
  456.          if (prct->yBottom < 0) prct->yBottom = 0;
  457.       }
  458.  
  459.       if(usShrink == 1) {
  460.          /* horizontal shrink request */
  461.          prct->xRight = prct->xLeft+ lMargin*2;
  462.       }
  463.  
  464.    } /* end of if str len */
  465.  
  466.    /* draw box if required */
  467.    if (lControl) {
  468.  
  469.       POINTL pntEnd;
  470.  
  471.       pnt.x = prct->xLeft;
  472.       pnt.y = prct->yBottom;
  473.  
  474.       pntEnd.x = prct->xRight;
  475.       pntEnd.y = prct->yTop;
  476.  
  477.       if(lControl == DRO_FILL || lControl == DRO_OUTLINEFILL ) {
  478.          if(!GpiSetMix(hps, FM_XOR)) return FALSE;
  479.          if(!GpiSetPattern(hps, PATSYM_DENSE8)) return FALSE;
  480.       }
  481.  
  482.       if(!GpiSetCurrentPosition(hps, &pnt)) return FALSE;
  483.  
  484.       if(GpiBox(hps, lControl, &pntEnd, lRound, lRound) != GPI_OK) return FALSE;
  485.  
  486.       if(lControl == DRO_FILL || lControl == DRO_OUTLINEFILL )
  487.       if(!GpiSetMix(hps, FM_DEFAULT)) return FALSE;
  488.  
  489.    }
  490.  
  491.    return TRUE;
  492. }
  493.  
  494. LONG MavPrint::createFontMatching(PSZ pszFacename, LONG lPointSize,
  495. ULONG fl, PBOOL pfScalable, PSIZEF psizfxBox)
  496. /*  This function is used select the requested font. An image font
  497. is first searched for and if one is not found that matches the
  498. font face and size, a scalable font is then searched for */
  499. {
  500.    LONG      cFont;     /* Fonts Count   */
  501.    LONG      lFontsTotal = 0L;    /* Fonts Total Count   */
  502.    LONG      lXDeviceRes;    /* x Device Resolution  */
  503.    LONG      lYDeviceRes;    /* y Device Resolution  */
  504.    PFONTMETRICS pfmSelect;     /* Font Metrics Pointer  */
  505.    FATTRS      fat;     /* Font Attributes   */
  506.    register INT i;      /* Loop Counter   */
  507.  
  508.    LONG lNominalPointSize = lPointSize * 10;
  509.  
  510.    /* Get the height of the screen in pels  */
  511.  
  512.    DevQueryCaps(hdc, CAPS_HORIZONTAL_FONT_RES, 1L, &lXDeviceRes);
  513.    DevQueryCaps(hdc, CAPS_VERTICAL_FONT_RES,   1L, &lYDeviceRes);
  514.  
  515.    /* Get the number of fonts for the face name */
  516.    /* provided     */
  517.  
  518.    if ( (cFont = GpiQueryFonts(hps, QF_PUBLIC, pszFacename, &lFontsTotal,
  519.    sizeof(FONTMETRICS), (PFONTMETRICS)NULL)) != 0L )
  520.    {
  521.       /* Allocate space for the font metrics for the */
  522.       /* different font sizes and devices of the font */
  523.  
  524.       DosAllocMem((PPVOID)(PVOID)&pfmSelect, (ULONG)(sizeof(FONTMETRICS) * cFont),
  525.       PAG_READ | PAG_WRITE | PAG_COMMIT);
  526.  
  527.       /* Make a pointer for the memory allocated for */
  528.       /* the font metrics and get the font metrics for */
  529.       /* the number of fonts for the face name  */
  530.       /* provided     */
  531.  
  532.       GpiQueryFonts(hps, QF_PUBLIC, pszFacename, &cFont,
  533.       sizeof(FONTMETRICS), pfmSelect);
  534.  
  535.       /* Loop through the font metrics returned to */
  536.       /* locate the desired font by matching the x and */
  537.       /* y device resolution of the font and the point */
  538.       /* size      */
  539.  
  540.       for ( i = 0; i < (INT)cFont; i++ )
  541.       if ( (pfmSelect[i].sXDeviceRes == (SHORT)lXDeviceRes) &&
  542.       (pfmSelect[i].sYDeviceRes == (SHORT)lYDeviceRes) &&
  543.       ((LONG)pfmSelect[i].sNominalPointSize == lNominalPointSize) )
  544.       {
  545.          /* Font found, get the match value to allow the */
  546.          /* exact font to be selected by the calling */
  547.          /* application     */
  548.  
  549.          memset(&fat, 0, sizeof(FATTRS));
  550.          fat.usRecordLength  = sizeof(FATTRS);
  551.          strcpy(fat.szFacename, pszFacename);
  552.          fat.lMatch        = pfmSelect[i].lMatch;
  553.          fat.fsSelection     = (USHORT)fl;
  554.  
  555.          DosFreeMem((PVOID)pfmSelect);
  556.  
  557.          if(pfScalable) *pfScalable = FALSE;
  558.          GpiCreateLogFont(hps, (PSTR8)NULL, lLcIdCount + 1, &fat);
  559.          /* increment local identifier now that GpiCreateLogFont went ok */
  560.          lLcIdCount++;
  561.  
  562.          /* not scalable */
  563.          usFontSize[lLcIdCount] = 0;
  564.  
  565.          if(!selectLogFont(lLcIdCount, psizfxBox)) return 0;
  566.  
  567.          return lLcIdCount;
  568.  
  569.       }
  570.  
  571.       /* NOT FOUND, TRY SCALABLE FONT */
  572.       /* Loop through the font metrics returned to */
  573.       /* locate the desired font by matching the x and */
  574.       /* y device resolution == 1000 (means scalable) */
  575.  
  576.       for ( i = 0; i < (INT)cFont; i++ )
  577.       if ( (pfmSelect[i].sXDeviceRes == 1000) && (pfmSelect[i].sYDeviceRes == 1000) )
  578.       {
  579.          /* Font found, get the match value to allow the */
  580.          /* exact font to be selected by the calling */
  581.          /* application     */
  582.  
  583.          memset(&fat, 0, sizeof(FATTRS));
  584.          fat.usRecordLength  = sizeof(FATTRS);
  585.          strcpy(fat.szFacename, pszFacename);
  586.          fat.lMatch        = pfmSelect[i].lMatch;
  587.          fat.usCodePage      = 850;
  588.          fat.fsFontUse       = FATTR_FONTUSE_OUTLINE | FATTR_FONTUSE_TRANSFORMABLE;
  589.          fat.fsSelection     = (USHORT)fl;
  590.  
  591.          DosFreeMem((PVOID)pfmSelect);
  592.  
  593.          if(pfScalable) *pfScalable = TRUE;
  594.          GpiCreateLogFont(hps, (PSTR8)NULL, lLcIdCount + 1, &fat);
  595.          /* increment local identifier now that GpiCreateLogFont went ok */
  596.          lLcIdCount++;
  597.  
  598.          /* scalable */
  599.          usFontSize[lLcIdCount] = lNominalPointSize;
  600.  
  601.          if(!selectLogFont(lLcIdCount, psizfxBox)) return 0;
  602.  
  603.          return lLcIdCount;
  604.  
  605.       }
  606.  
  607.       /* Release the memory allocated for the font */
  608.       /* metrics array     */
  609.  
  610.       DosFreeMem((PVOID)pfmSelect);
  611.    }
  612.  
  613.    return(0);
  614. }
  615.  
  616. Boolean MavPrint::selectLogFont(LONG lLcId, PSIZEF psizfxBox)
  617. /* Font is set to a previously created one and fm (fontmetrics) updated */
  618. {
  619.  
  620.    LONG lNominalPointSize = usFontSize[lLcId];
  621.    LONG lFontSize;
  622.  
  623.    if( ! GpiSetCharSet(hps, lLcId) ) return FALSE;
  624.  
  625.    /* only scalable fonts have usFontSize[i] > 0 as
  626.    set by createlogfont */
  627.    if(lNominalPointSize) {
  628.  
  629.       switch(pSetup->lWorldCoordinates) {
  630.  
  631.          case PU_LOMETRIC:
  632.          lFontSize = lNominalPointSize * 2 *254/1440;
  633.          break;
  634.  
  635.          case PU_HIMETRIC:
  636.          lFontSize = lNominalPointSize * 2 *2540/1440;
  637.          break;
  638.  
  639.          case PU_LOENGLISH:
  640.          lFontSize = lNominalPointSize * 2 *100/1440;
  641.          break;
  642.  
  643.          case PU_HIENGLISH:
  644.          lFontSize = lNominalPointSize * 2 *1000/1440;
  645.          break;
  646.  
  647.          case PU_TWIPS:
  648.          lFontSize = lNominalPointSize * 2;
  649.          break;
  650.  
  651.          default:
  652.          lFontSize = lNominalPointSize * 2;
  653.          break;
  654.  
  655.       }
  656.  
  657.       SIZEF siz;
  658.       siz.cx = siz.cy = MAKEFIXED(lFontSize, 0);
  659.  
  660.       if(psizfxBox) {
  661.          psizfxBox->cx = psizfxBox->cy = siz.cx;
  662.       }
  663.  
  664.       if(! GpiSetCharBox( hps, &siz ) ) return FALSE;
  665.    }
  666.  
  667.    if(! GpiQueryFontMetrics( hps, sizeof( fm ), &fm ) ) return FALSE;
  668.  
  669.    return TRUE;
  670.  
  671. }
  672.  
  673. Boolean MavPrint::printBitmapInBox(RECTL * rectl, PSZ pszFileName,
  674. Boolean booMaintainAspectRatio)
  675. {
  676.    FILESTATUS3 filestatus3;
  677.    HBITMAP hbm, hbm1, hbmOld;
  678.    HFILE hfile;
  679.    PBITMAPFILEHEADER2 pbmpfileheader2;
  680.    PBITMAPFILEHEADER2 pbmpfileheader2Work;
  681.    PBITMAPINFOHEADER2 pbmp2;
  682.    PBYTE pBits;
  683.    PBYTE pBitsAligned;
  684.    ULONG rc, ulAction, cBytes, cScans;
  685.    ULONG cbImageData;
  686.    LONG lRC;
  687.    LONG cxBitmap, cyBitmap;
  688.  
  689.    /* open bitmap file */
  690.    rc = DosOpen( pszFileName,
  691.    &hfile,
  692.    &ulAction,
  693.    0L,
  694.    FILE_NORMAL,
  695.    FILE_OPEN,
  696.    OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE,
  697.    NULL );
  698.    if( rc != 0 )
  699.    {
  700.       return FALSE;
  701.    }
  702.  
  703.    /* query file size; returned in filestatus3.cbFile */
  704.    rc = DosQueryFileInfo( hfile, FIL_STANDARD,
  705.    (PVOID)&filestatus3, sizeof( filestatus3 ));
  706.    if(rc) {
  707.       DosClose( hfile );
  708.       return FALSE;
  709.    }
  710.  
  711.    /* alloc memory for bitmap file read */
  712.    if(!(pbmpfileheader2 =
  713.    (PBITMAPFILEHEADER2) malloc( filestatus3.cbFile ))) {
  714.       DosClose( hfile );
  715.       return FALSE;
  716.    }
  717.  
  718.    /* read bitmap file into memory */
  719.    rc = DosRead( hfile, (PVOID)pbmpfileheader2, filestatus3.cbFile, &cBytes );
  720.    if( rc != 0  ||  cBytes == 0 )
  721.    {
  722.       free( pbmpfileheader2 );
  723.       DosClose( hfile );
  724.       return FALSE;
  725.    }
  726.  
  727.    DosClose( hfile );
  728.  
  729.    switch( pbmpfileheader2->usType )
  730.    {
  731.       case BFT_BITMAPARRAY:
  732.       /* default to the first bitmap in the array */
  733.       pbmpfileheader2Work = &((PBITMAPARRAYFILEHEADER2)pbmpfileheader2)->bfh2;
  734.       pbmp2 = &pbmpfileheader2Work->bmp2;
  735.       cbImageData = filestatus3.cbFile - pbmpfileheader2Work->offBits;
  736.       pBits = (PBYTE)pbmpfileheader2 + pbmpfileheader2Work->offBits;
  737.       break;
  738.  
  739.       case BFT_BMAP:
  740.       /* set pbmp2 to point to the BITMAPINFO2 structure within the file */
  741.       pbmp2 = &pbmpfileheader2->bmp2;
  742.       cbImageData = filestatus3.cbFile - pbmpfileheader2->offBits;
  743.       pBits = (PBYTE)pbmpfileheader2 + pbmpfileheader2->offBits;
  744.       break;
  745.  
  746.       default:
  747.       /* invalid file format */
  748.       free( pbmpfileheader2 );
  749.       return FALSE;
  750.    }
  751.  
  752.    /* pBits should be sensible */
  753.    if( !pbmp2 || !pBits ) {
  754.       free( pbmpfileheader2 );
  755.       return FALSE;
  756.    }
  757.  
  758.    /* create a compatible memory PS */
  759.  
  760.    HDC    hdcMemory;       /* Device-context handle                */
  761.    HPS    hpsMemory;       /* presentation-space handle            */
  762.    SIZEL sizel;
  763.    /* create memory device context and presentation space, associating
  764.    DC with the PS */
  765.    hdcMemory = DevOpenDC(pSetup->hab, OD_MEMORY, "*", 0, NULL, hdc);
  766.    if (!hdcMemory)
  767.    {
  768.       free( pbmpfileheader2 );
  769.       return FALSE;
  770.    }
  771.  
  772.    sizel.cx = 0;
  773.    sizel.cy = 0;
  774.    hpsMemory = GpiCreatePS(pSetup->hab, hdcMemory, &sizel,
  775.    GPIA_ASSOC | PU_PELS | GPIT_NORMAL);
  776.    if (!hpsMemory)
  777.    {
  778.       free( pbmpfileheader2 );
  779.       DevCloseDC( hdcMemory );
  780.       return FALSE;
  781.    }
  782.  
  783.  
  784.    /* create a bitmap */
  785.  
  786.    hbm1 = GpiCreateBitmap( hpsMemory,
  787.    pbmp2,
  788.    0,                  /* options */
  789.    (PBYTE)NULL,        /* init table */
  790.    (PBITMAPINFO2)NULL );  /* bitmap info */
  791.  
  792.    /* check that bitmap has been created properly */
  793.    if (hbm1 == GPI_ERROR)
  794.    {
  795.       free( pbmpfileheader2 );
  796.       /* Clean up bitmap, memory PS and memory DC */
  797.       GpiAssociate( hpsMemory, (HDC)NULLHANDLE );
  798.       GpiDestroyPS( hpsMemory );
  799.       DevCloseDC( hdcMemory );
  800.  
  801.       return FALSE;
  802.    }
  803.  
  804.    /* set bitmap into the memory ps */
  805.    hbm = GpiSetBitmap( hpsMemory, hbm1 );
  806.    if(hbm == HBM_ERROR ) {
  807.       free( pbmpfileheader2 );
  808.       /* Clean up bitmap, memory PS and memory DC */
  809.       GpiDeleteBitmap(hbm1);
  810.       GpiAssociate( hpsMemory, (HDC)NULLHANDLE );
  811.       GpiDestroyPS( hpsMemory );
  812.       DevCloseDC( hdcMemory );
  813.  
  814.       return FALSE;
  815.    }
  816.  
  817.    cScans = pbmp2->cy;
  818.    cyBitmap = pbmp2->cy;
  819.    cxBitmap = pbmp2->cx;
  820.  
  821.    /*
  822.    * Some print drivers expect the bit image data to be dword
  823.    * aligned.  Allocate a new memory object and copy bit data
  824.    * to it.
  825.    */
  826.    pBitsAligned = (PBYTE) malloc( cbImageData );
  827.    if(!pBitsAligned) {
  828.       free( pbmpfileheader2 );
  829.       /* Clean up bitmap, memory PS and memory DC */
  830.       GpiDeleteBitmap(hbm1);
  831.       GpiAssociate( hpsMemory, (HDC)NULLHANDLE );
  832.       GpiDestroyPS( hpsMemory );
  833.       DevCloseDC( hdcMemory );
  834.  
  835.       return FALSE;
  836.    }
  837.  
  838.    memcpy( pBitsAligned, pBits, cbImageData );
  839.  
  840.    /* take bitmap bits from file buffer and place into memory ps for bitmap */
  841.    lRC = GpiSetBitmapBits( hpsMemory,
  842.    0,
  843.    (LONG)cScans,
  844.    pBitsAligned,
  845.    (PBITMAPINFO2)pbmp2  );
  846.  
  847.    if( lRC == GPI_ERROR ) {
  848.       free( pBitsAligned );
  849.       free( pbmpfileheader2 );
  850.       /* Clean up bitmap, memory PS and memory DC */
  851.       GpiDeleteBitmap(hbm1);
  852.       GpiAssociate( hpsMemory, (HDC)NULLHANDLE );
  853.       GpiDestroyPS( hpsMemory );
  854.       DevCloseDC( hdcMemory );
  855.  
  856.       return FALSE;
  857.    }
  858.  
  859.    /* clean up */
  860.    free( pBitsAligned );
  861.    free( pbmpfileheader2 );
  862.  
  863.    POINTL aptl[4];
  864.  
  865.    /* setup the source bitblt rectangle */
  866.    aptl[2].x = 0;
  867.    aptl[2].y = 0;
  868.    aptl[3].x = cxBitmap;
  869.    aptl[3].y = cyBitmap;
  870.  
  871.    /* Set up target bitblt rectangles */
  872.    aptl[0].x = rectl->xLeft;
  873.    aptl[0].y = rectl->yBottom;
  874.    aptl[1].x = rectl->xRight;
  875.    aptl[1].y = rectl->yTop;
  876.  
  877.    if(booMaintainAspectRatio) {
  878.  
  879.       /* shrink x or y target rectangle */
  880.       if(cxBitmap < cyBitmap) {
  881.          aptl[1].x = rectl->xLeft + (rectl->xRight - rectl->xLeft)
  882.          * ((double)cxBitmap/(double)cyBitmap);
  883.       } else {
  884.          aptl[1].y = rectl->yBottom + (rectl->yTop - rectl->yBottom)
  885.          * ((double)cyBitmap/(double)cxBitmap);
  886.       }
  887.  
  888.    }
  889.  
  890.    hbmOld = GpiSetBitmap( hpsMemory, 0L );
  891.    if(hbmOld == HBM_ERROR){
  892.       /* Clean up bitmap, memory PS and memory DC */
  893.       GpiDeleteBitmap(hbm1);
  894.       GpiAssociate( hpsMemory, (HDC)NULLHANDLE );
  895.       GpiDestroyPS( hpsMemory );
  896.       DevCloseDC( hdcMemory );
  897.  
  898.       return FALSE;
  899.    }
  900.  
  901.  
  902.    lRC = GpiWCBitBlt( hps,
  903.    hbm1,
  904.    4L,
  905.    (PPOINTL)aptl,
  906.    ROP_SRCCOPY,
  907.    BBO_IGNORE );
  908.  
  909.    /* Clean up bitmap, memory PS and memory DC */
  910.    GpiDeleteBitmap(hbm1);
  911.    GpiAssociate( hpsMemory, (HDC)NULLHANDLE );
  912.    GpiDestroyPS( hpsMemory );
  913.    DevCloseDC( hdcMemory );
  914.  
  915.    if(lRC != GPI_OK) return FALSE;
  916.  
  917.    return TRUE;
  918.  
  919. }
  920.  
  921.