home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tkisrc04.zip / tk / os2 / tkOS2Draw.c < prev    next >
C/C++ Source or Header  |  1998-08-07  |  115KB  |  3,401 lines

  1. /* 
  2.  * tkOS2Draw.c --
  3.  *
  4.  *    This file contains the Xlib emulation functions pertaining to
  5.  *    actually drawing objects on a window.
  6.  *
  7.  * Copyright (c) 1996-1997 Illya Vaes
  8.  * Copyright (c) 1995 Sun Microsystems, Inc.
  9.  * Copyright (c) 1994 Software Research Associates, Inc.
  10.  *
  11.  * See the file "license.terms" for information on usage and redistribution
  12.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  13.  */
  14.  
  15.  
  16. #include "tkOS2Int.h"
  17.  
  18. #define PI 3.14159265358979
  19. #define XAngleToRadians(a) ((double)(a) / 64 * PI / 180)
  20.  
  21. /*
  22.  * Translation tables between X gc values and OS/2 GPI line attributes.
  23.  */
  24.  
  25. static int lineStyles[] = {
  26.     LINETYPE_SOLID,    /* LineSolid */
  27.     LINETYPE_SHORTDASH,    /* LineOnOffDash */
  28.     LINETYPE_SHORTDASH    /* LineDoubleDash EXTRA PROCESSING NECESSARY */
  29. };
  30. static int capStyles[] = {
  31.     LINEEND_FLAT,    /* CapNotLast EXTRA PROCESSING NECESSARY */
  32.     LINEEND_FLAT,    /* CapButt */
  33.     LINEEND_ROUND,    /* CapRound */
  34.     LINEEND_SQUARE    /* CapProjecting */
  35. };
  36. static int joinStyles[] = {
  37.     LINEJOIN_MITRE,    /* JoinMiter */
  38.     LINEJOIN_ROUND,    /* JoinRound */
  39.     LINEJOIN_BEVEL    /* JoinBevel */
  40. };
  41.  
  42. /*
  43.  * Translation table between X gc functions and OS/2 GPI mix attributes.
  44.  */
  45.  
  46. static int mixModes[] = {
  47.     FM_ZERO,            /* GXclear */
  48.     FM_AND,            /* GXand */
  49.     FM_MASKSRCNOT,        /* GXandReverse */
  50.     FM_OVERPAINT,        /* GXcopy */
  51.     FM_SUBTRACT,        /* GXandInverted */
  52.     FM_LEAVEALONE,        /* GXnoop */
  53.     FM_XOR,            /* GXxor */
  54.     FM_OR,            /* GXor */
  55.     FM_NOTMERGESRC,        /* GXnor */
  56.     FM_NOTXORSRC,        /* GXequiv */
  57.     FM_INVERT,            /* GXinvert */
  58.     FM_MERGESRCNOT,        /* GXorReverse */
  59.     FM_NOTCOPYSRC,        /* GXcopyInverted */
  60.     FM_MERGENOTSRC,        /* GXorInverted */
  61.     FM_NOTMASKSRC,        /* GXnand */
  62.     FM_ONE            /* GXset */
  63. };
  64.  
  65.  
  66. /*
  67.  * Translation table between X gc functions and OS/2 GPI BitBlt raster op modes.
  68.  * Some of the operations defined in X don't have names, so we have to construct
  69.  * new opcodes for those functions.  This is arcane and probably not all that
  70.  * useful, but at least it's accurate.
  71.  */
  72.  
  73. #define NOTSRCAND    (LONG)0x0022 /* dest = (NOT source) AND dest */
  74. #define NOTSRCINVERT    (LONG)0x0099 /* dest = (NOT source) XOR dest */
  75. #define SRCORREVERSE    (LONG)0x00dd /* dest = source OR (NOT dest) */
  76. #define SRCNAND        (LONG)0x0077 /* dest = (NOT source) OR (NOT dest) */
  77.  
  78. static int bltModes[] = {
  79.     ROP_ZERO,            /* GXclear */
  80.     ROP_SRCAND,            /* GXand */
  81.     ROP_SRCERASE,        /* GXandReverse */
  82.     ROP_SRCCOPY,        /* GXcopy */
  83.     NOTSRCAND,            /* GXandInverted */
  84.     ROP_PATCOPY,        /* GXnoop */
  85.     ROP_SRCINVERT,        /* GXxor */
  86.     ROP_SRCPAINT,        /* GXor */
  87.     ROP_NOTSRCERASE,        /* GXnor */
  88.     NOTSRCINVERT,        /* GXequiv */
  89.     ROP_DSTINVERT,        /* GXinvert */
  90.     SRCORREVERSE,        /* GXorReverse */
  91.     ROP_NOTSRCCOPY,        /* GXcopyInverted */
  92.     ROP_MERGEPAINT,        /* GXorInverted */
  93.     SRCNAND,            /* GXnand */
  94.     ROP_ONE            /* GXset */
  95. };
  96.  
  97. /*
  98.  * The following raster op uses the source bitmap as a mask for the
  99.  * pattern.  This is used to draw in a foreground color but leave the
  100.  * background color transparent.
  101.  */
  102.  
  103. #define MASKPAT        0x00e2 /* dest = (src & pat) | (!src & dst) */
  104.  
  105. /*
  106.  * The following two raster ops are used to copy the foreground and background
  107.  * bits of a source pattern as defined by a stipple used as the pattern.
  108.  */
  109.  
  110. #define COPYFG        0x00ca /* dest = (pat & src) | (!pat & dst) */
  111. #define COPYBG        0x00ac /* dest = (!pat & src) | (pat & dst) */
  112.  
  113. /*
  114.  * Macros used later in the file.
  115.  */
  116.  
  117. #ifndef MIN
  118. #define MIN(a,b)    ((a>b) ? b : a)
  119. #endif
  120. #ifndef MAX
  121. #define MAX(a,b)    ((a<b) ? b : a)
  122. #endif
  123.  
  124. /*
  125.  * Forward declarations for procedures defined in this file:
  126.  */
  127.  
  128. static POINTL *        ConvertPoints (Drawable d, XPoint *points, int npoints,
  129.                 int mode, RECTL *bbox);
  130. static void        DrawOrFillArc (Display *display,
  131.                 Drawable d, GC gc, int x, int y,
  132.                 unsigned int width, unsigned int height,
  133.                 int angle1, int angle2, int fill);
  134. static void        RenderObject (HPS hps, GC gc, Drawable d,
  135.                             XPoint* points, int npoints, int mode,
  136.                             PLINEBUNDLE lineBundle, int func);
  137. static void        TkOS2SetStipple(HPS destPS, HPS bmpPS, HBITMAP stipple,
  138.                 LONG x, LONG y, LONG *oldPatternSet,
  139.                 PPOINTL oldRefPoint);
  140. static void        TkOS2UnsetStipple(HPS destPS, HPS bmpPS, HBITMAP stipple,
  141.                 LONG oldPatternSet, PPOINTL oldRefPoint);
  142.  
  143. /*
  144.  *----------------------------------------------------------------------
  145.  *
  146.  * TkOS2GetDrawablePS --
  147.  *
  148.  *    Retrieve the Presentation Space from a drawable.
  149.  *
  150.  * Results:
  151.  *    Returns the window PS for windows.  Returns the associated memory PS
  152.  *    for pixmaps.
  153.  *
  154.  * Side effects:
  155.  *    Sets up the palette for the presentation space, and saves the old
  156.  *    presentation space state in the passed in TkOS2PSState structure.
  157.  *
  158.  *----------------------------------------------------------------------
  159.  */
  160.  
  161. HPS
  162. TkOS2GetDrawablePS(display, d, state)
  163.     Display *display;
  164.     Drawable d;
  165.     TkOS2PSState* state;
  166. {
  167.     HPS hps;
  168.     TkOS2Drawable *todPtr = (TkOS2Drawable *)d;
  169.     Colormap cmap;
  170.  
  171.     if (todPtr->type != TOD_BITMAP) {
  172.         TkWindow *winPtr = todPtr->window.winPtr;
  173.  
  174.     hps = WinGetPS(todPtr->window.handle);
  175. #ifdef DEBUG
  176.         printf("TkOS2GetDrawablePS window %x (handle %x, hps %x)\n", todPtr,
  177.                todPtr->window.handle, hps);
  178. #endif
  179.         if (winPtr == NULL) {
  180.         cmap = DefaultColormap(display, DefaultScreen(display));
  181.         } else {
  182.         cmap = winPtr->atts.colormap;
  183.         }
  184.         state->palette = TkOS2SelectPalette(hps, todPtr->window.handle, cmap);
  185.     } else {
  186.  
  187.         hps = todPtr->bitmap.hps;
  188. #ifdef DEBUG
  189.         printf("TkOS2GetDrawablePS bitmap %x (handle %x, hps %x)\n", d,
  190.                todPtr->bitmap.handle, hps);
  191. #endif
  192.         cmap = todPtr->bitmap.colormap;
  193.         state->palette = TkOS2SelectPalette(hps, todPtr->bitmap.parent, cmap);
  194.     }
  195.     return hps;
  196. }
  197.  
  198. /*
  199.  *----------------------------------------------------------------------
  200.  *
  201.  * TkOS2ReleaseDrawablePS --
  202.  *
  203.  *    Frees the resources associated with a drawable's DC.
  204.  *
  205.  * Results:
  206.  *    None.
  207.  *
  208.  * Side effects:
  209.  *    Restores the old bitmap handle to the memory DC for pixmaps.
  210.  *
  211.  *----------------------------------------------------------------------
  212.  */
  213.  
  214. void
  215. TkOS2ReleaseDrawablePS(d, hps, state)
  216.     Drawable d;
  217.     HPS hps;
  218.     TkOS2PSState *state;
  219. {
  220.     ULONG changed;
  221.     HPAL oldPal;
  222.     TkOS2Drawable *todPtr = (TkOS2Drawable *)d;
  223.  
  224.     oldPal = GpiSelectPalette(hps, state->palette);
  225. #ifdef DEBUG
  226.     if (oldPal == PAL_ERROR) {
  227.         printf("GpiSelectPalette TkOS2ReleaseDrawablePS PAL_ERROR: %x\n",
  228.                WinGetLastError(hab));
  229.     } else {
  230.         printf("GpiSelectPalette TkOS2ReleaseDrawablePS: %x\n", oldPal);
  231.     }
  232. #endif
  233.     if (todPtr->type != TOD_BITMAP) {
  234. #ifdef DEBUG
  235.         printf("TkOS2ReleaseDrawablePS window %x\n", d);
  236. #endif
  237.         WinRealizePalette(TkOS2GetHWND(d), hps, &changed);
  238.         WinReleasePS(hps);
  239.     } else {
  240. #ifdef DEBUG
  241.         printf("TkOS2ReleaseDrawablePS bitmap %x released %x\n", d,
  242.                state->bitmap);
  243. #endif
  244.         WinRealizePalette(todPtr->bitmap.parent, hps, &changed);
  245.     }
  246. }
  247.  
  248. /*
  249.  *----------------------------------------------------------------------
  250.  *
  251.  * ConvertPoints --
  252.  *
  253.  *    Convert an array of X points to an array of OS/2 GPI points.
  254.  *
  255.  * Results:
  256.  *    Returns the converted array of POINTLs.
  257.  *
  258.  * Side effects:
  259.  *    Allocates a block of memory that should not be freed.
  260.  *
  261.  *----------------------------------------------------------------------
  262.  */
  263.  
  264. static POINTL *
  265. ConvertPoints(d, points, npoints, mode, bbox)
  266.     Drawable d;
  267.     XPoint *points;
  268.     int npoints;
  269.     int mode;            /* CoordModeOrigin or CoordModePrevious. */
  270.     RECTL *bbox;            /* Bounding box of points. */
  271. {
  272.     static POINTL *os2Points = NULL; /* Array of points that is reused. */
  273.     static int nOS2Points = -1;        /* Current size of point array. */
  274.     LONG windowHeight;
  275.     int i;
  276.  
  277. #ifdef DEBUG
  278.     printf("ConvertPoints %s\n", mode == CoordModeOrigin ? "CoordModeOrigin":
  279.            "CoordModePrevious");
  280. #endif
  281.  
  282.     windowHeight = TkOS2WindowHeight((TkOS2Drawable *)d);
  283.  
  284.     /*
  285.      * To avoid paying the cost of a malloc on every drawing routine,
  286.      * we reuse the last array if it is large enough.
  287.      */
  288.  
  289.     if (npoints > nOS2Points) {
  290.     if (os2Points != NULL) {
  291. #ifdef DEBUG
  292.             printf("    ckfree os2Points %x\n", os2Points);
  293. #endif
  294.         ckfree((char *) os2Points);
  295.     }
  296.     os2Points = (POINTL *) ckalloc(sizeof(POINTL) * npoints);
  297. #ifdef DEBUG
  298.         printf("    ckalloc os2Points %x\n", os2Points);
  299. #endif
  300.     if (os2Points == NULL) {
  301.         nOS2Points = -1;
  302.         return NULL;
  303.     }
  304.     nOS2Points = npoints;
  305.     }
  306.  
  307.     /* Convert to PM Coordinates */
  308.     bbox->xLeft = bbox->xRight = points[0].x;
  309.     bbox->yTop = bbox->yBottom = windowHeight - points[0].y;
  310.     
  311.     if (mode == CoordModeOrigin) {
  312.     for (i = 0; i < npoints; i++) {
  313.         os2Points[i].x = points[i].x;
  314.         /* convert to PM */
  315.         os2Points[i].y = windowHeight - points[i].y;
  316.         bbox->xLeft = MIN(bbox->xLeft, os2Points[i].x);
  317.         /* Since GpiBitBlt excludes top & right, add one */
  318.         bbox->xRight = MAX(bbox->xRight, os2Points[i].x + 1);
  319.         /* y: min and max switched for PM */
  320.         bbox->yTop = MAX(bbox->yTop, os2Points[i].y + 1);
  321.         bbox->yBottom = MIN(bbox->yBottom, os2Points[i].y);
  322. #ifdef DEBUG
  323.             printf("   point %d: x %d, y %d; bbox xL %d, xR %d, yT %d, yB %d\n",
  324.                    i, points[i].x, points[i].y, bbox->xLeft, bbox->xRight,
  325.                    bbox->yTop, bbox->yBottom);
  326. #endif
  327.     }
  328.     } else {
  329.     os2Points[0].x = points[0].x;
  330.     os2Points[0].y = windowHeight - points[0].y;
  331.     for (i = 1; i < npoints; i++) {
  332.         os2Points[i].x = os2Points[i-1].x + points[i].x;
  333.         /* convert to PM */
  334.         os2Points[i].y = os2Points[i-1].y -
  335.                          (windowHeight - points[i].y);
  336.         bbox->xLeft = MIN(bbox->xLeft, os2Points[i].x);
  337.         /* Since GpiBitBlt excludes top & right, add one */
  338.         bbox->xRight = MAX(bbox->xRight, os2Points[i].x + 1);
  339.         /* y: min and max switched for PM */
  340.         bbox->yTop = MAX(bbox->yTop, os2Points[i].y + 1);
  341.         bbox->yBottom = MIN(bbox->yBottom, os2Points[i].y);
  342. #ifdef DEBUG
  343.             printf("    point %d: x %d, y %d; bbox xL %d, xR %d, yT %d, yB %d\n",
  344.                    points[i].x, points[i].y, bbox->xLeft, bbox->xRight,
  345.                    bbox->yTop, bbox->yBottom);
  346.             printf("    os2point: x %d, y %d\n", os2Points[i].x, os2Points[i].y);
  347. #endif
  348.     }
  349.     }
  350.     return os2Points;
  351. }
  352.  
  353. /*
  354.  *----------------------------------------------------------------------
  355.  *
  356.  * XCopyArea --
  357.  *
  358.  *    Copies data from one drawable to another using block transfer
  359.  *    routines.
  360.  *
  361.  * Results:
  362.  *    None.
  363.  *
  364.  * Side effects:
  365.  *    Data is moved from a window or bitmap to a second window or
  366.  *    bitmap.
  367.  *
  368.  *----------------------------------------------------------------------
  369.  */
  370.  
  371. void
  372. XCopyArea(display, src, dest, gc, src_x, src_y, width, height, dest_x, dest_y)
  373.     Display* display;
  374.     Drawable src;
  375.     Drawable dest;
  376.     GC gc;
  377.     int src_x, src_y;
  378.     unsigned int width, height;
  379.     int dest_x, dest_y;
  380. {
  381.     HPS srcPS, destPS;
  382.     TkOS2PSState srcState, destState;
  383.     POINTL aPoints[3]; /* Lower-left, upper-right, lower-left source */
  384.     BOOL rc;
  385.     LONG windowHeight;
  386.  
  387. #ifdef DEBUG
  388.     printf("XCopyArea (%d,%d) -> (%d,%d), %dx%d, gc->func %x, fg %x, bg %x\n",
  389.            src_x, src_y, dest_x, dest_y, width, height, gc->function,
  390.            gc->foreground, gc->background);
  391. #endif
  392.     /* Translate the Y coordinates to PM coordinates */
  393.     /* Determine height of window */
  394.     windowHeight = TkOS2WindowHeight((TkOS2Drawable *)dest);
  395.     aPoints[0].x = dest_x;
  396.     aPoints[0].y = windowHeight - dest_y - height;
  397.     aPoints[1].x = dest_x + width;
  398.     aPoints[1].y = windowHeight - dest_y;
  399.     aPoints[2].x = src_x;
  400.     if (src != dest) {
  401.         windowHeight = TkOS2WindowHeight((TkOS2Drawable *)src);
  402.     }
  403.     aPoints[2].y = windowHeight - src_y - height;
  404.     srcPS = TkOS2GetDrawablePS(display, src, &srcState);
  405. #ifdef DEBUG
  406.     printf("    PM: (%d,%d)-(%d,%d) <- (%d,%d)\n", aPoints[0].x, aPoints[0].y,
  407.            aPoints[1].x, aPoints[1].y, aPoints[2].x, aPoints[2].y);
  408. #endif
  409.  
  410.     if (src != dest) {
  411.     destPS = TkOS2GetDrawablePS(display, dest, &destState);
  412.     } else {
  413.     destPS = srcPS;
  414.     }
  415. #ifdef DEBUG
  416.     rc = GpiRectVisible(destPS, (PRECTL)&aPoints[0]);
  417.     if (rc==RVIS_PARTIAL || rc==RVIS_VISIBLE) {
  418.         printf("GpiRectVisible (%d,%d) (%d,%d) (partially) visible\n",
  419.                aPoints[0].x, aPoints[0].y, aPoints[1].x, aPoints[1].y);
  420.     } else {
  421.         if (rc==RVIS_INVISIBLE) {
  422.             printf("GpiRectVisible (%d,%d) (%d,%d) invisible\n",
  423.                    aPoints[0].x, aPoints[0].y, aPoints[1].x, aPoints[1].y);
  424.         } else {
  425.             printf("GpiRectVisible (%d,%d) (%d,%d) ERROR, error %x\n",
  426.                    aPoints[0].x, aPoints[0].y, aPoints[1].x, aPoints[1].y,
  427.                    WinGetLastError(hab));
  428.         }
  429.     }
  430. #endif
  431.     rc = GpiBitBlt(destPS, srcPS, 3, aPoints, bltModes[gc->function],
  432.                    BBO_IGNORE);
  433. #ifdef DEBUG
  434.     printf("    srcPS %x, type %s, destPS %x, type %s\n", srcPS,
  435.            ((TkOS2Drawable *)src)->type == TOD_BITMAP ? "bitmap" : "window",
  436.            destPS,
  437.            ((TkOS2Drawable *)dest)->type == TOD_BITMAP ? "bitmap" : "window");
  438.     printf("    GpiBitBlt %x -> %x, 3, (%d,%d)(%d,%d)(%d,%d), %x returns %d\n",
  439.            srcPS, destPS, aPoints[0].x, aPoints[0].y,
  440.            aPoints[1].x, aPoints[1].y, aPoints[2].x, aPoints[2].y,
  441.            bltModes[gc->function], rc);
  442. #endif
  443.  
  444.     if (src != dest) {
  445.     TkOS2ReleaseDrawablePS(dest, destPS, &destState);
  446.     }
  447.     TkOS2ReleaseDrawablePS(src, srcPS, &srcState);
  448. }
  449.  
  450. /*
  451.  *----------------------------------------------------------------------
  452.  *
  453.  * XCopyPlane --
  454.  *
  455.  *    Copies a bitmap from a source drawable to a destination
  456.  *    drawable.  The plane argument specifies which bit plane of
  457.  *    the source contains the bitmap.  Note that this implementation
  458.  *    ignores the gc->function.
  459.  *
  460.  * Results:
  461.  *    None.
  462.  *
  463.  * Side effects:
  464.  *    Changes the destination drawable.
  465.  *
  466.  *----------------------------------------------------------------------
  467.  */
  468.  
  469. void
  470. XCopyPlane(display, src, dest, gc, src_x, src_y, width, height, dest_x,
  471.     dest_y, plane)
  472.     Display* display;
  473.     Drawable src;
  474.     Drawable dest;
  475.     GC gc;
  476.     int src_x, src_y;
  477.     unsigned int width, height;
  478.     int dest_x, dest_y;
  479.     unsigned long plane;
  480. {
  481.     HPS srcPS, destPS;
  482.     TkOS2PSState srcState, destState;
  483.     LONG oldPattern;
  484.     LONG oldMix, oldBackMix;
  485.     LONG oldColor, oldBackColor;
  486.     LONG srcWindowHeight, destWindowHeight;
  487.     POINTL aPoints[3]; /* Lower-left, upper-right, lower-left source */
  488.     LONG rc;
  489.  
  490. #ifdef DEBUG
  491.     printf("XCopyPlane (%d,%d) -> (%d,%d), w %d, h %d; fg %x, bg %x, gc->func %x\n",
  492.            src_x, src_y, dest_x, dest_y, width, height, gc->foreground,
  493.            gc->background, gc->function);
  494. #endif
  495.  
  496.     /* Translate the Y coordinates to PM coordinates */
  497.     destWindowHeight = TkOS2WindowHeight((TkOS2Drawable *)dest);
  498.     if (src != dest) {
  499.         srcWindowHeight = TkOS2WindowHeight((TkOS2Drawable *)src);
  500.     } else {
  501.         srcWindowHeight = destWindowHeight;
  502.     }
  503. #ifdef DEBUG
  504.     printf("srcWindowHeight %d, destWindowHeight %d\n", srcWindowHeight,
  505.            destWindowHeight);
  506. #endif
  507.     aPoints[0].x = dest_x;
  508.     aPoints[0].y = destWindowHeight - dest_y - height;
  509.     aPoints[1].x = dest_x + width;
  510.     aPoints[1].y = destWindowHeight - dest_y;
  511.     aPoints[2].x = src_x;
  512.     aPoints[2].y = src_y;
  513.     display->request++;
  514.  
  515.     if (plane != 1) {
  516.     panic("Unexpected plane specified for XCopyPlane");
  517.     }
  518.  
  519.     srcPS = TkOS2GetDrawablePS(display, src, &srcState);
  520.  
  521.     if (src != dest) {
  522.     destPS = TkOS2GetDrawablePS(display, dest, &destState);
  523.     } else {
  524.     destPS = srcPS;
  525.     }
  526. #ifdef DEBUG
  527.     printf("    srcPS %x, type %s, destPS %x, type %s, clip_mask %x\n", srcPS,
  528.            ((TkOS2Drawable *)src)->type == TOD_BITMAP ? "bitmap" : "window",
  529.            destPS,
  530.            ((TkOS2Drawable *)dest)->type == TOD_BITMAP ? "bitmap" : "window",
  531.            gc->clip_mask);
  532.     printf("    (%d,%d) (%d,%d) (%d,%d)\n", aPoints[0].x, aPoints[0].y,
  533.            aPoints[1].x, aPoints[1].y, aPoints[2].x, aPoints[2].y);
  534. #endif
  535.  
  536.     if (gc->clip_mask == src) {
  537. #ifdef DEBUG
  538.         printf("XCopyPlane case1\n");
  539. #endif
  540.  
  541.     /*
  542.      * Case 1: transparent bitmaps are handled by setting the
  543.      * destination to the foreground color whenever the source
  544.      * pixel is set.
  545.      */
  546.  
  547.     oldColor = GpiQueryColor(destPS);
  548.         oldBackColor = GpiQueryBackColor(destPS);
  549.     oldPattern = GpiQueryPattern(destPS);
  550.     GpiSetColor(destPS, gc->foreground);
  551.         rc= GpiSetBackColor(destPS, gc->background);
  552.     GpiSetPattern(destPS, PATSYM_SOLID);
  553.         rc = GpiBitBlt(destPS, srcPS, 3, aPoints, MASKPAT, BBO_IGNORE);
  554. #ifdef DEBUG
  555.         printf("    GpiBitBlt (clip_mask src) %x, %x returns %d\n", destPS,
  556.                srcPS, rc);
  557. #endif
  558.     GpiSetPattern(destPS, oldPattern);
  559.         GpiSetBackColor(destPS, oldBackColor);
  560.     GpiSetColor(destPS, oldColor);
  561.  
  562.     } else if (gc->clip_mask == None) {
  563. #ifdef DEBUG
  564.         printf("XCopyPlane case2\n");
  565. #endif
  566.  
  567.     /*
  568.      * Case 2: opaque bitmaps.
  569.      * Conversion from a monochrome bitmap to a color bitmap/device:
  570.      *     source 1 -> image foreground color
  571.      *     source 0 -> image background color
  572.      *
  573.      */
  574.  
  575.         oldColor = GpiQueryColor(destPS);
  576.         oldBackColor = GpiQueryBackColor(destPS);
  577.         oldMix = GpiQueryMix(destPS);
  578.         oldBackMix = GpiQueryBackMix(destPS);
  579. #ifdef DEBUG
  580.         printf("    oldColor %d, oldBackColor %d, oldMix %d, oldBackMix %d\n",
  581.                oldColor, oldBackColor, oldMix, oldBackMix);
  582.         printf("    oldColor srcPS %d, oldBackColor srcPS %d\n",
  583.                GpiQueryColor(srcPS), GpiQueryBackColor(srcPS));
  584. #endif
  585.  
  586.         /*
  587.         rc= GpiSetColor(destPS, gc->foreground);
  588.         */
  589.         rc= GpiSetColor(destPS, gc->background);
  590. #ifdef DEBUG
  591.         if (rc==TRUE) printf("    GpiSetColor %x OK\n", gc->foreground);
  592.         else printf("    GpiSetColor %x ERROR: %x\n", gc->foreground,
  593.                     WinGetLastError(hab));
  594. #endif
  595.         /*
  596.         rc= GpiSetBackColor(destPS, gc->background);
  597.         */
  598.         rc= GpiSetBackColor(destPS, gc->foreground);
  599. #ifdef DEBUG
  600.         if (rc==TRUE) printf("    GpiSetBackColor %x OK\n", gc->background);
  601.         else printf("    GpiSetBackColor %x ERROR: %x\n", gc->background,
  602.                     WinGetLastError(hab));
  603. #endif
  604.  
  605.         rc = GpiBitBlt(destPS, srcPS, 3, aPoints, ROP_SRCCOPY, BBO_IGNORE);
  606. #ifdef DEBUG
  607.         printf("    GpiBitBlt (clip_mask None) %x -> %x returns %x\n", srcPS,
  608.                destPS, rc);
  609. fflush(stdout);
  610. #endif
  611.         rc= GpiSetColor(destPS, oldColor);
  612.         rc= GpiSetBackColor(destPS, oldBackColor);
  613.         rc= GpiSetMix(destPS, oldMix);
  614.         rc= GpiSetBackMix(destPS, oldBackMix);
  615.     } else {
  616.  
  617.     /*
  618.      * Case 3: two arbitrary bitmaps.  Copy the source rectangle
  619.      * into a color pixmap.  Use the result as a brush when
  620.      * copying the clip mask into the destination.     
  621.      */
  622.  
  623.     HPS memPS, maskPS;
  624.     BITMAPINFOHEADER2 bmpInfo;
  625.     HBITMAP bitmap, oldBitmap;
  626.     TkOS2PSState maskState;
  627.  
  628. #ifdef DEBUG
  629.         printf("XCopyPlane case3\n");
  630. #endif
  631.  
  632.     oldColor = GpiQueryColor(destPS);
  633.     oldPattern = GpiQueryPattern(destPS);
  634.  
  635.     maskPS = TkOS2GetDrawablePS(display, gc->clip_mask, &maskState);
  636.     memPS = WinGetScreenPS(HWND_DESKTOP);
  637.     bmpInfo.cbFix = sizeof(BITMAPINFOHEADER2);
  638.     bmpInfo.cx = width;
  639.     bmpInfo.cy = height;
  640.     bmpInfo.cPlanes = 1;
  641.     bmpInfo.cBitCount = 1;
  642.     bitmap = GpiCreateBitmap(memPS, &bmpInfo, 0L, NULL, NULL);
  643. #ifdef DEBUG
  644.         printf("    GpiCreateBitmap (%d,%d) returned %x\n", width, height,
  645.                bitmap);
  646. #endif
  647.     oldBitmap = GpiSetBitmap(memPS, bitmap);
  648. #ifdef DEBUG
  649.         printf("    GpiSetBitmap %x returned %x\n", bitmap, oldBitmap);
  650. #endif
  651.  
  652.     /*
  653.      * Set foreground bits.  We create a new bitmap containing
  654.      * (source AND mask), then use it to set the foreground color
  655.      * into the destination.
  656.      */
  657.  
  658.         /* Translate the Y coordinates to PM coordinates */
  659.         aPoints[0].x = 0; /* dest_x = 0 */
  660.         aPoints[0].y = destWindowHeight - height; /* dest_y = 0 */
  661.         aPoints[1].x = width;
  662.         aPoints[1].y = destWindowHeight;
  663.         aPoints[2].x = src_x;
  664.         aPoints[2].y = srcWindowHeight - src_y - height;
  665.         rc = GpiBitBlt(memPS, srcPS, 3, aPoints, ROP_SRCCOPY, BBO_IGNORE);
  666. #ifdef DEBUG
  667.         printf("    GpiBitBlt nr1 %x, %x returns %d\n", destPS, srcPS, rc);
  668. #endif
  669.         /* Translate the Y coordinates to PM coordinates */
  670.         aPoints[0].x = 0; /* dest_x = 0 */
  671.         aPoints[0].y = destWindowHeight - height; /* dest_y = 0 */
  672.         aPoints[1].x = dest_x + width;
  673.         aPoints[1].y = destWindowHeight;
  674.         aPoints[2].x = dest_x - gc->clip_x_origin;
  675.         aPoints[2].y = srcWindowHeight - dest_y + gc->clip_y_origin - height;
  676.         rc = GpiBitBlt(memPS, maskPS, 3, aPoints, ROP_SRCAND, BBO_IGNORE);
  677. #ifdef DEBUG
  678.         printf("    GpiBitBlt nr2 %x, %x returns %d\n", destPS, srcPS, rc);
  679. #endif
  680.         /* Translate the Y coordinates to PM coordinates */
  681.         aPoints[0].x = dest_x;
  682.         aPoints[0].y = destWindowHeight - dest_y - height;
  683.         aPoints[1].x = dest_x + width;
  684.         aPoints[1].y = destWindowHeight - dest_y;
  685.         aPoints[2].x = 0; /* src_x = 0 */
  686.         aPoints[2].y = srcWindowHeight - height; /* src_y = 0 */
  687.     GpiSetColor(destPS, gc->foreground);
  688.     GpiSetPattern(destPS, PATSYM_SOLID);
  689.         rc = GpiBitBlt(destPS, memPS, 3, aPoints, MASKPAT, BBO_IGNORE);
  690. #ifdef DEBUG
  691.         printf("    GpiBitBlt nr3 %x, %x returns %d\n", destPS, srcPS, rc);
  692. #endif
  693.  
  694.     /*
  695.      * Set background bits.  Same as foreground, except we use
  696.      * ((NOT source) AND mask) and the background brush.
  697.      */
  698.  
  699.         /* Translate the Y coordinates to PM coordinates */
  700.         aPoints[0].x = 0; /* dest_x = 0 */
  701.         aPoints[0].y = destWindowHeight - height; /* dest_y = 0 */
  702.         aPoints[1].x = width;
  703.         aPoints[1].y = destWindowHeight;
  704.         aPoints[2].x = src_x;
  705.         aPoints[2].y = srcWindowHeight - src_y - height;
  706.         rc = GpiBitBlt(memPS, srcPS, 3, aPoints, ROP_NOTSRCCOPY, BBO_IGNORE);
  707. #ifdef DEBUG
  708.         printf("    GpiBitBlt nr4 %x, %x returns %d\n", destPS, srcPS, rc);
  709. #endif
  710.         /* Translate the Y coordinates to PM coordinates */
  711.         aPoints[0].x = 0; /* dest_x = 0 */
  712.         aPoints[0].y = destWindowHeight - height; /* dest_y = 0 */
  713.         aPoints[1].x = dest_x + width;
  714.         aPoints[1].y = destWindowHeight;
  715.         aPoints[2].x = dest_x - gc->clip_x_origin;
  716.         aPoints[2].y = destWindowHeight - dest_y + gc->clip_y_origin - height;
  717.         rc = GpiBitBlt(memPS, maskPS, 3, aPoints, ROP_SRCAND, BBO_IGNORE);
  718. #ifdef DEBUG
  719.         printf("    GpiBitBlt nr5 %x, %x returns %d\n", destPS, srcPS, rc);
  720. #endif
  721.     GpiSetColor(destPS, gc->background);
  722.     GpiSetPattern(destPS, PATSYM_SOLID);
  723.         /* Translate the Y coordinates to PM coordinates */
  724.         aPoints[0].x = dest_x;
  725.         aPoints[0].y = destWindowHeight - dest_y - height;
  726.         aPoints[1].x = dest_x + width;
  727.         aPoints[1].y = destWindowHeight - dest_y;
  728.         aPoints[2].x = 0; /* src_x = 0 */
  729.         aPoints[2].y = srcWindowHeight - height; /* src_y = 0 */
  730.         rc = GpiBitBlt(destPS, memPS, 3, aPoints, MASKPAT, BBO_IGNORE);
  731. #ifdef DEBUG
  732.         printf("    GpiBitBlt nr6 %x, %x returns %d\n", destPS, srcPS, rc);
  733. #endif
  734.  
  735.     TkOS2ReleaseDrawablePS(gc->clip_mask, maskPS, &maskState);
  736.     GpiSetPattern(destPS, oldPattern);
  737.     GpiSetColor(destPS, oldColor);
  738.     GpiSetBitmap(memPS, oldBitmap);
  739.     GpiDeleteBitmap(bitmap);
  740.     WinReleasePS(memPS);
  741.     }
  742.     if (src != dest) {
  743.     TkOS2ReleaseDrawablePS(dest, destPS, &destState);
  744.     }
  745.     TkOS2ReleaseDrawablePS(src, srcPS, &srcState);
  746. }
  747.  
  748. /*
  749.  *----------------------------------------------------------------------
  750.  *
  751.  * TkPutImage --
  752.  *
  753.  *    Copies a subimage from an in-memory image to a rectangle of
  754.  *    of the specified drawable.
  755.  *
  756.  * Results:
  757.  *    None.
  758.  *
  759.  * Side effects:
  760.  *    Draws the image on the specified drawable.
  761.  *
  762.  *----------------------------------------------------------------------
  763.  */
  764.  
  765. void
  766. TkPutImage(colors, ncolors, display, d, gc, image, src_x, src_y, dest_x,
  767.     dest_y, width, height)
  768.     unsigned long *colors;        /* Array of pixel values used by this
  769.                      * image.  May be NULL. */
  770.     int ncolors;            /* Number of colors used, or 0. */
  771.     Display* display;
  772.     Drawable d;                /* Destination drawable. */
  773.     GC gc;
  774.     XImage* image;            /* Source image. */
  775.     int src_x, src_y;            /* Offset of subimage. */      
  776.     int dest_x, dest_y;            /* Position of subimage origin in
  777.                      * drawable.  */
  778.     unsigned int width, height;        /* Dimensions of subimage. */
  779. {
  780.     HPS hps;
  781.     LONG rc;
  782.     TkOS2PSState state;
  783.     BITMAPINFOHEADER2 bmpInfo;
  784.     BITMAPINFO2 *infoPtr;
  785.     char *data;
  786.     LONG windowHeight;
  787.  
  788.     /* Translate the Y coordinates to PM coordinates */
  789.     windowHeight = TkOS2WindowHeight((TkOS2Drawable *)d);
  790.  
  791.     display->request++;
  792.  
  793.     hps = TkOS2GetDrawablePS(display, d, &state);
  794.  
  795. #ifdef DEBUG
  796.     printf("TkPutImage d %x hps %x (%d,%d) => (%d,%d) %dx%d imgh %d mix %d\n",
  797.            d, hps, src_x, src_y, dest_x, dest_y, width, height, image->height,
  798.            gc->function);
  799.     printf("    nrColors %d, gc->foreground %d, gc->background %d\n", ncolors,
  800.            gc->foreground, gc->background);
  801. #endif
  802.  
  803.     rc = GpiSetMix(hps, mixModes[gc->function]);
  804. #ifdef DEBUG
  805.     if (rc == FALSE) {
  806.         printf("    GpiSetMix ERROR %x\n", WinGetLastError(hab));
  807.     } else {
  808.         printf("    GpiSetMix %x OK\n", mixModes[gc->function]);
  809.     }
  810.     printf("    hps color %d, hps back color %d\n", GpiQueryColor(hps),
  811.            GpiQueryBackColor(hps));
  812. #endif
  813.  
  814.     if (image->bits_per_pixel == 1) {
  815. #ifdef DEBUG
  816.         printf("image->bits_per_pixel == 1\n");
  817. #endif
  818.  
  819.         /* Bitmap must be reversed in OS/2 wrt. the Y direction */
  820.         /* This is done best in a modified version of TkAlignImageData */
  821.     data = TkAlignImageData(image, sizeof(ULONG), MSBFirst);
  822.     bmpInfo.cbFix = 16L;
  823.     bmpInfo.cx = image->width;
  824.     bmpInfo.cy = image->height;
  825.     bmpInfo.cPlanes = 1;
  826.     bmpInfo.cBitCount = 1;
  827.         rc = GpiSetBitmapBits(hps, windowHeight - dest_y - height, height,
  828.                               (PBYTE)data, (BITMAPINFO2*) &bmpInfo);
  829. #ifdef DEBUG
  830.         if (rc == GPI_ALTERROR) {
  831.             SIZEL dim;
  832.             printf("    GpiSetBitmapBits returned GPI_ALTERROR %x\n",
  833.                    WinGetLastError(hab));
  834.             rc=GpiQueryBitmapDimension(((TkOS2Drawable *)d)->bitmap.handle,
  835.                                        &dim);
  836.             if (rc == FALSE) {
  837.                 printf("    GpiQueryBitmapDimension ERROR %x\n",
  838.                        WinGetLastError(hab));
  839.             } else {
  840.                 printf("    GpiQueryBitmapDimension: %dx%d\n", dim.cx, dim.cy);
  841.             }
  842.         } else {
  843.             printf("   GpiSetBitmapBits (%d) set %d scanlines (hps %x, h %x)\n", 
  844.                    windowHeight - dest_y - height, rc, hps,
  845.                    ((TkOS2Drawable *)d)->bitmap.handle);
  846.         }
  847. #endif
  848.  
  849.     ckfree(data);
  850.     } else {
  851.     int usePalette;
  852.  
  853. #ifdef DEBUG
  854.     LONG defBitmapFormat[2];
  855.         printf("image->bits_per_pixel %d\n", image->bits_per_pixel);
  856. #endif
  857.  
  858.     /*
  859.      * Do not use a palette for TrueColor images.
  860.      */
  861.     
  862.     usePalette = (image->bits_per_pixel < 24);
  863.  
  864.     if (usePalette) {
  865. #ifdef DEBUG
  866.         printf("using palette (not TrueColor)\n");
  867. #endif
  868.         infoPtr = (BITMAPINFO2*) ckalloc(sizeof(BITMAPINFO2)
  869.             + sizeof(RGB2)*ncolors);
  870.     } else {
  871. #ifdef DEBUG
  872.         printf("not using palette (TrueColor)\n");
  873. #endif
  874.         infoPtr = (BITMAPINFO2*) ckalloc(sizeof(BITMAPINFO2));
  875.     }
  876.     if (infoPtr == NULL) return;
  877.  
  878.         /* Bitmap must be reversed in OS/2 wrt. the Y direction */
  879.     data = TkOS2ReverseImageLines(image, height);
  880.     
  881.     infoPtr->cbFix = sizeof(BITMAPINFOHEADER2);
  882.     infoPtr->cx = width;
  883.         infoPtr->cy = height;
  884.  
  885. #ifdef DEBUG
  886.     rc = GpiQueryDeviceBitmapFormats(hps, 2, defBitmapFormat);
  887.         if (rc != TRUE) {
  888.             printf("    GpiQueryDeviceBitmapFormats ERROR %x -> mono\n",
  889.                    WinGetLastError(hab));
  890.         infoPtr->cPlanes = 1;
  891.         infoPtr->cBitCount = 1;
  892.         } else {
  893.             printf("    GpiQueryDeviceBitmapFormats OK planes %d, bits %d\n",
  894.                    defBitmapFormat[0], defBitmapFormat[1]);
  895.         infoPtr->cPlanes = defBitmapFormat[0];
  896.         infoPtr->cBitCount = defBitmapFormat[1];
  897.         }
  898. #endif
  899.  
  900.     infoPtr->cPlanes = 1;
  901.     infoPtr->cBitCount = image->bits_per_pixel;
  902.     infoPtr->ulCompression = BCA_UNCOMP;
  903.     infoPtr->cbImage = 0;
  904.     infoPtr->cxResolution = aDevCaps[CAPS_HORIZONTAL_RESOLUTION];
  905.     infoPtr->cyResolution = aDevCaps[CAPS_VERTICAL_RESOLUTION];
  906.     infoPtr->cclrUsed = 0;
  907.     infoPtr->cclrImportant = 0;
  908.     infoPtr->usUnits = BRU_METRIC;
  909.     infoPtr->usReserved = 0;
  910.     infoPtr->usRecording = BRA_BOTTOMUP;
  911.     infoPtr->usRendering = BRH_NOTHALFTONED;
  912.     infoPtr->cSize1 = 0L;
  913.     infoPtr->cSize2 = 0L;
  914.     infoPtr->ulColorEncoding = BCE_RGB;
  915.     infoPtr->ulIdentifier = 0L;
  916.  
  917.     if (usePalette) {
  918.         BOOL palManager = FALSE;
  919.  
  920.         if (aDevCaps[CAPS_ADDITIONAL_GRAPHICS] & CAPS_PALETTE_MANAGER) {
  921.             palManager = TRUE;
  922. #ifdef DEBUG
  923.             printf("    Palette manager\n");
  924. #endif
  925.         }
  926.             if (palManager) {
  927.                 rc = GpiQueryPaletteInfo(GpiQueryPalette(hps), hps, 0, 0,
  928.                                          ncolors, (PLONG) &infoPtr->argbColor);
  929. #ifdef DEBUG
  930.                 if (rc != TRUE) {
  931.                     printf("    GpiQueryPaletteInfo ERROR %x\n",
  932.                            WinGetLastError(hab));
  933.                 }
  934. #endif
  935.             } else {
  936.                 rc = GpiQueryLogColorTable(hps, 0, 0, ncolors,
  937.                                            (PLONG) &infoPtr->argbColor);
  938. #ifdef DEBUG
  939.                 if (rc == QLCT_ERROR) {
  940.                     printf("    GpiQueryLogColorTable ERROR %x\n",
  941.                            WinGetLastError(hab));
  942.                 } else {
  943.                     if (rc == QLCT_RGB) {
  944.                         printf("    table in RGB mode, no element returned");
  945.                     }
  946.                 }
  947. #endif
  948.         }
  949.     } else {
  950.         infoPtr->cclrUsed = 0;
  951.     }
  952.  
  953.         rc = GpiSetBitmapBits(hps, windowHeight - dest_y - height, height,
  954.                               (PBYTE)data, infoPtr);
  955. #ifdef DEBUG
  956.         printf("windowHeight %d, dest_y %d, height %d, image->height %d\n",
  957.                windowHeight, dest_y, height, image->height);
  958.         if (rc == GPI_ALTERROR) {
  959.             printf("GpiSetBitmapBits returned GPI_ALTERROR %x\n",
  960.                    WinGetLastError(hab));
  961.         } else {
  962.             printf("    GpiSetBitmapBits (%d) set %d scanlines (hps %x, h %x)\n", 
  963.                    windowHeight - dest_y - height, rc, hps,
  964.                    ((TkOS2Drawable *)d)->bitmap.handle);
  965.         }
  966. #endif
  967.  
  968.     ckfree((char *)infoPtr);
  969.     ckfree(data);
  970.     }
  971.     TkOS2ReleaseDrawablePS(d, hps, &state);
  972. }
  973.  
  974. /*
  975.  *----------------------------------------------------------------------
  976.  *
  977.  * XDrawString --
  978.  *
  979.  *    Draw a single string in the current font.
  980.  *
  981.  * Results:
  982.  *    None.
  983.  *
  984.  * Side effects:
  985.  *    Renders the specified string in the drawable.
  986.  *
  987.  *----------------------------------------------------------------------
  988.  */
  989.  
  990. void
  991. XDrawString(display, d, gc, x, y, string, length)
  992.     Display* display;
  993.     Drawable d;
  994.     GC gc;
  995.     int x;
  996.     int y;
  997.     _Xconst char* string;
  998.     int length;
  999. {
  1000.     HPS hps;
  1001.     SIZEF oldCharBox;
  1002.     LONG oldFont = 0L;
  1003.     LONG oldHorAlign, oldVerAlign;
  1004.     LONG oldBackMix;
  1005.     LONG oldColor, oldBackColor = 0L;
  1006.     POINTL oldRefPoint;
  1007.     LONG oldPattern;
  1008.     HBITMAP oldBitmap;
  1009.     POINTL noShear= {0, 1};
  1010.     TkOS2PSState state;
  1011.     POINTL aPoints[3]; /* Lower-left, upper-right, lower-left source */
  1012.     CHARBUNDLE cBundle;
  1013.     AREABUNDLE aBundle;
  1014.     LONG windowHeight, l;
  1015.     char *str;
  1016.     POINTL refPoint;
  1017.     BOOL rc;
  1018.  
  1019.     display->request++;
  1020.  
  1021.     if (d == None) {
  1022.     return;
  1023.     }
  1024.  
  1025. #ifdef DEBUG
  1026.     printf("XDrawString %s\"%s\" (%d) on type %s (%x), mixmode %d\n",
  1027.           ( (gc->fill_style == FillStippled
  1028.              || gc->fill_style == FillOpaqueStippled)
  1029.            && gc->stipple != None) ? "stippled " : "", string, length,
  1030.           ((TkOS2Drawable *)d)->type == TOD_BITMAP ? "bitmap" : "window", d,
  1031.           mixModes[gc->function]);
  1032. #endif
  1033.     hps = TkOS2GetDrawablePS(display, d, &state);
  1034.     GpiSetMix(hps, mixModes[gc->function]);
  1035.  
  1036.     /* If this is an outline font, set the char box */
  1037.     if (logfonts[(LONG)gc->font].outline) {
  1038. #ifdef DEBUG
  1039.         SIZEF charBox;
  1040. #endif
  1041.         rc = GpiQueryCharBox(hps, &oldCharBox);
  1042. #ifdef DEBUG
  1043.         if (rc!=TRUE) {
  1044.             printf("GpiQueryCharBox ERROR %x\n", WinGetLastError(hab));
  1045.         } else {
  1046.             printf("GpiQueryCharBox OK: cx %d (%d,%d), cy %d (%d,%d)\n",
  1047.                    oldCharBox.cx, FIXEDINT(oldCharBox.cx),
  1048.                    FIXEDFRAC(oldCharBox.cx), oldCharBox.cy,
  1049.                    FIXEDINT(oldCharBox.cy), FIXEDFRAC(oldCharBox.cy));
  1050.         }
  1051. #endif
  1052.         rc = TkOS2ScaleFont(hps, logfonts[(LONG)gc->font].deciPoints, 0);
  1053. #ifdef DEBUG
  1054.         if (rc!=TRUE) {
  1055.             printf("TkOS2ScaleFont %d ERROR %x\n",
  1056.                    logfonts[(LONG)gc->font].deciPoints, WinGetLastError(hab));
  1057.         } else {
  1058.             printf("TkOS2ScaleFont %d OK\n",
  1059.                    logfonts[(LONG)gc->font].deciPoints);
  1060.         }
  1061.         rc = GpiQueryCharBox(hps, &charBox);
  1062.         if (rc!=TRUE) {
  1063.             printf("GpiQueryCharBox ERROR %x\n");
  1064.         } else {
  1065.             printf("GpiQueryCharBox OK: now cx %d (%d,%d), cy %d (%d,%d)\n",
  1066.                    charBox.cx, FIXEDINT(charBox.cx), FIXEDFRAC(charBox.cx),
  1067.                    charBox.cy, FIXEDINT(charBox.cy), FIXEDFRAC(charBox.cy));
  1068.         }
  1069. #endif
  1070.     }
  1071.  
  1072.     /* Translate the Y coordinates to PM coordinates */
  1073.     windowHeight = TkOS2WindowHeight((TkOS2Drawable *)d);
  1074. #ifdef DEBUG
  1075.     printf("    x %d, y %d (PM: %d)\n", x, y, windowHeight - y);
  1076. #endif
  1077.     y = windowHeight - y;
  1078.  
  1079.     if ((gc->fill_style == FillStippled || gc->fill_style == FillOpaqueStippled)
  1080.         && gc->stipple != None) {
  1081.  
  1082.     TkOS2Drawable *todPtr = (TkOS2Drawable *)gc->stipple;
  1083.     HDC dcMem;
  1084.     HPS psMem;
  1085.         DEVOPENSTRUC dop = {0L, (PSZ)"DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
  1086.         SIZEL sizl = {0,0}; /* use same page size as device */
  1087.     HBITMAP bitmap;
  1088.         BITMAPINFOHEADER2 bmpInfo;
  1089.         RECTL rect;
  1090.         POINTL textBox[TXTBOX_COUNT];
  1091.  
  1092. #ifdef DEBUG
  1093.        printf("XDrawString stippled \"%s\" (%x) at %d,%d; fg %d, bg %d, bmp %x\n",
  1094.               string, gc->stipple, x, y, gc->foreground, gc->background,
  1095.               todPtr->bitmap.handle);
  1096. #endif
  1097.  
  1098.     if (todPtr->type != TOD_BITMAP) {
  1099.         panic("unexpected drawable type in stipple");
  1100.     }
  1101.  
  1102.     /*
  1103.      * Select stipple pattern into destination PS.
  1104.      * gc->ts_x_origin and y_origin are relative to origin of the
  1105.      * destination drawable, while PatternRefPoint is in world coords.
  1106.      */
  1107.  
  1108.     dcMem = DevOpenDC(hab, OD_MEMORY, (PSZ)"*", 5L, (PDEVOPENDATA)&dop,
  1109.                       NULLHANDLE);
  1110.     if (dcMem == DEV_ERROR) {
  1111. #ifdef DEBUG
  1112.             printf("DevOpenDC ERROR %x in XDrawString\n", WinGetLastError(hab));
  1113. #endif
  1114.         return;
  1115.     }
  1116. #ifdef DEBUG
  1117.         printf("DevOpenDC in XDrawString returns %x\n", dcMem);
  1118. #endif
  1119.         psMem = GpiCreatePS(hab, dcMem, &sizl,
  1120.                             PU_PELS | GPIT_NORMAL | GPIA_ASSOC);
  1121.         if (psMem == GPI_ERROR) {
  1122. #ifdef DEBUG
  1123.             printf("GpiCreatePS ERROR %x in XDrawString\n", WinGetLastError(hab));
  1124. #endif
  1125.             DevCloseDC(dcMem);
  1126.             return;
  1127.         }
  1128. #ifdef DEBUG
  1129.         printf("GpiCreatePS in XDrawString returns %x\n", psMem);
  1130. #endif
  1131.     /*
  1132.      * Compute the bounding box and create a compatible bitmap.
  1133.      */
  1134.  
  1135.     rc = WinQueryWindowRect(((TkOS2Drawable *)d)->bitmap.parent, &rect);
  1136. #ifdef DEBUG
  1137.         if (rc != TRUE) {
  1138.             printf("WinQueryWindowRect ERROR %x\n", WinGetLastError(hab));
  1139.         } else {
  1140.             printf("WinQueryWindowRect OK %d,%d->%d,%d\n", rect.xLeft,
  1141.                    rect.yBottom, rect.xRight, rect.yTop);
  1142.         }
  1143. #endif
  1144.     bmpInfo.cbFix = 16L;
  1145.     /*
  1146.     bmpInfo.cx = rect.xRight - rect.xLeft;
  1147.     bmpInfo.cy = rect.yTop - rect.yBottom;
  1148.     */
  1149.     bmpInfo.cx = xScreen;
  1150.     bmpInfo.cy = yScreen;
  1151.     bmpInfo.cPlanes = 1;
  1152.     bmpInfo.cBitCount = display->screens[display->default_screen].root_depth;
  1153.     bitmap = GpiCreateBitmap(psMem, &bmpInfo, 0L, NULL, NULL);
  1154. #ifdef DEBUG
  1155.         if (bitmap == GPI_ERROR) {
  1156.             printf("GpiCreateBitmap (%d,%d) GPI_ERROR %x\n", bmpInfo.cx,
  1157.                    bmpInfo.cy, WinGetLastError(hab));
  1158.         } else {
  1159.             printf("GpiCreateBitmap (%d,%d) returned %x\n", bmpInfo.cx,
  1160.                    bmpInfo.cy, bitmap);
  1161.         }
  1162. #endif
  1163.         oldBitmap = GpiSetBitmap(psMem, bitmap);
  1164. #ifdef DEBUG
  1165.         if (bitmap == HBM_ERROR) {
  1166.             printf("GpiSetBitmap (%x) HBM_ERROR %x\n", bitmap,
  1167.                    WinGetLastError(hab));
  1168.         } else {
  1169.             printf("GpiSetBitmap %x returned %x\n", bitmap, oldBitmap);
  1170.         }
  1171. #endif
  1172.  
  1173.     refPoint.x = gc->ts_x_origin;
  1174.     refPoint.y = windowHeight - gc->ts_y_origin;
  1175.  
  1176. #ifdef DEBUG
  1177.         printf("gc->ts_x_origin=%d (->%d), gc->ts_y_origin=%d (->%d)\n",
  1178.                gc->ts_x_origin, refPoint.x, gc->ts_y_origin, refPoint.y);
  1179. #endif
  1180.         /* The bitmap mustn't be selected in the HPS */
  1181.         TkOS2SetStipple(hps, todPtr->bitmap.hps, todPtr->bitmap.handle,
  1182.                         refPoint.x, refPoint.y, &oldPattern, &oldRefPoint);
  1183.  
  1184.         GpiQueryTextAlignment(psMem, &oldHorAlign, &oldVerAlign);
  1185.         GpiSetTextAlignment(psMem, TA_LEFT, TA_BASE);
  1186.  
  1187.         GpiQueryAttrs(psMem, PRIM_CHAR, LBB_COLOR, (PBUNDLE)&cBundle);
  1188.         oldColor = cBundle.lColor;
  1189.         cBundle.lColor = gc->foreground;
  1190.         rc = GpiSetAttrs(psMem, PRIM_CHAR, LBB_COLOR, 0L, (PBUNDLE)&cBundle);
  1191. #ifdef DEBUG
  1192.         if (rc!=TRUE) {
  1193.             printf("GpiSetAttrs textColor %d ERROR %x\n", cBundle.lColor,
  1194.                    WinGetLastError(hab));
  1195.         } else {
  1196.             printf("GpiSetAttrs textColor %d OK\n", cBundle.lColor);
  1197.         }
  1198. #endif
  1199.         aBundle.lColor = gc->foreground;
  1200.         rc = GpiSetAttrs(hps, PRIM_AREA, LBB_COLOR, 0L, (PBUNDLE)&aBundle);
  1201. #ifdef DEBUG
  1202.         if (rc!=TRUE) {
  1203.             printf("GpiSetAttrs areaColor %d ERROR %x\n", aBundle.lColor,
  1204.                    WinGetLastError(hab));
  1205.         } else {
  1206.             printf("GpiSetAttrs areaColor %d OK\n", aBundle.lColor);
  1207.         }
  1208. #endif
  1209.  
  1210.     oldBackMix = GpiQueryBackMix(psMem);
  1211.     rc = GpiSetBackMix(psMem, BM_LEAVEALONE);
  1212. #ifdef DEBUG
  1213.         if (rc!=TRUE) {
  1214.             printf("GpiSetBackMix ERROR %x\n", WinGetLastError(hab));
  1215.         } else {
  1216.             printf("GpiSetBackMix OK\n");
  1217.         }
  1218. #endif
  1219.         oldBackColor = GpiQueryBackColor(psMem);
  1220.         GpiSetBackColor(psMem, CLR_FALSE);
  1221. #ifdef DEBUG
  1222.         if (rc!=TRUE) {
  1223.             printf("GpiSetBackColor CLR_FALSE ERROR %x\n", WinGetLastError(hab));
  1224.         } else {
  1225.             printf("GpiSetBackColor CLR_FALSE OK\n");
  1226.         }
  1227. #endif
  1228.  
  1229.     if (gc->font != None) {
  1230.             rc = GpiCreateLogFont(psMem, NULL, (LONG)gc->font,
  1231.                                   &(logfonts[(LONG)gc->font].fattrs));
  1232. #ifdef DEBUG
  1233.             if (rc!=GPI_ERROR) {
  1234.                 printf("GpiCreateLogFont (%x, id %d) OK\n", psMem, gc->font);
  1235.             } else {
  1236.                 printf("GpiCreateLogFont (%x, id %d) ERROR, error %x\n", psMem,
  1237.                        gc->font, WinGetLastError(hab));
  1238.             }
  1239. #endif
  1240.         oldFont = GpiQueryCharSet(psMem);
  1241. #ifdef DEBUG
  1242.             if (rc==LCID_ERROR) {
  1243.                 printf("GpiQueryCharSet ERROR %x\n", WinGetLastError(hab));
  1244.             } else {
  1245.                 printf("GpiQueryCharSet OK\n");
  1246.             }
  1247. #endif
  1248.         rc = GpiSetCharSet(psMem, (LONG)gc->font);
  1249. #ifdef DEBUG
  1250.             if (rc!=TRUE) {
  1251.                 printf("GpiSetCharSet (%x, id %d, face [%s]) ERROR, error %x\n",
  1252.                        psMem, gc->font,
  1253.                        logfonts[(LONG)gc->font].fattrs.szFacename,
  1254.                        WinGetLastError(hab));
  1255.             } else {
  1256.                 printf("GpiSetCharSet (%x, id %d, face [%s]) OK\n", psMem,
  1257.                        gc->font, logfonts[(LONG)gc->font].fattrs.szFacename);
  1258.             }
  1259. #endif
  1260.         /* Set slant if necessary */
  1261.         if (logfonts[(LONG)gc->font].setShear) {
  1262.             rc = GpiSetCharShear(psMem, &(logfonts[(LONG)gc->font].shear));
  1263. #ifdef DEBUG
  1264.                 if (rc!=TRUE) {
  1265.                     printf("GpiSetCharShear font %d ERROR %x\n", gc->font,
  1266.                            WinGetLastError(hab));
  1267.                 } else {
  1268.                     printf("GpiSetCharShear font %d OK\n", gc->font);
  1269.                 }
  1270. #endif
  1271.         }
  1272.             /* If this is an outline font, set the char box */
  1273.             if (logfonts[(LONG)gc->font].outline) {
  1274. #ifdef DEBUG
  1275.                 SIZEF charBox;
  1276. #endif
  1277.                 rc = TkOS2ScaleFont(psMem, logfonts[(LONG)gc->font].deciPoints,
  1278.                                     0);
  1279. #ifdef DEBUG
  1280.                 if (rc!=TRUE) {
  1281.                     printf("TkOS2ScaleFont %d ERROR %x\n",
  1282.                            logfonts[(LONG)gc->font].deciPoints,
  1283.                            WinGetLastError(hab));
  1284.                 } else {
  1285.                     printf("TkOS2ScaleFont %d OK\n",
  1286.                            logfonts[(LONG)gc->font].deciPoints);
  1287.                 }
  1288.                 rc = GpiQueryCharBox(psMem, &charBox);
  1289.                 if (rc!=TRUE) {
  1290.                     printf("GpiQueryCharBox ERROR %x\n");
  1291.                 } else {
  1292.                     printf("GpiQueryCharBox OK: now cx %d (%d,%d), cy %d (%d,%d)\n", charBox.cx,
  1293.                            FIXEDINT(charBox.cx), FIXEDFRAC(charBox.cx),
  1294.                            charBox.cy, FIXEDINT(charBox.cy),
  1295.                            FIXEDFRAC(charBox.cy));
  1296.             }
  1297. #endif
  1298.             }
  1299.     }
  1300.  
  1301.         refPoint.x = x;
  1302.         refPoint.y = y;
  1303.         rc = GpiSetCurrentPosition(psMem, &refPoint);
  1304. #ifdef DEBUG
  1305.         if (rc!=TRUE) {
  1306.             printf("GpiSetCurrentPosition %d,%d ERROR %x\n", refPoint.x, refPoint.y,
  1307.                    WinGetLastError(hab));
  1308.         } else {
  1309.             printf("GpiSetCurrentPosition %d,%d OK\n", refPoint.x, refPoint.y);
  1310.         }
  1311. #endif
  1312.     rc = GpiQueryTextBox(psMem, length, (PCH)string, TXTBOX_COUNT, textBox);
  1313. #ifdef DEBUG
  1314.         if (rc != TRUE) {
  1315.             printf("GpiQueryTextBox \"%s\" (%d) ERROR %x\n", string, length,
  1316.                    WinGetLastError(hab));
  1317.         } else {
  1318.             printf("GpiQueryTextBox \"%s\" (%d) OK: (%d,%d)(%d,%d)(%d,%d)(%d,%d), refPoint (%d,%d)\n",
  1319.                    string, length,
  1320.                    textBox[TXTBOX_TOPLEFT].x, textBox[TXTBOX_TOPLEFT].y,
  1321.                    textBox[TXTBOX_BOTTOMLEFT].x, textBox[TXTBOX_BOTTOMLEFT].y,
  1322.                    textBox[TXTBOX_TOPRIGHT].x, textBox[TXTBOX_TOPRIGHT].y,
  1323.                    textBox[TXTBOX_BOTTOMRIGHT].x, textBox[TXTBOX_BOTTOMRIGHT].y,
  1324.                    refPoint.x, refPoint.y);
  1325.         }
  1326. #endif
  1327.  
  1328.         aPoints[0].x = refPoint.x + textBox[TXTBOX_BOTTOMLEFT].x;
  1329.         aPoints[0].y = refPoint.y + textBox[TXTBOX_BOTTOMLEFT].y;
  1330.         aPoints[1].x = refPoint.x + textBox[TXTBOX_TOPRIGHT].x;
  1331.     aPoints[1].y = refPoint.y + textBox[TXTBOX_TOPRIGHT].y;
  1332.         aPoints[2].x = refPoint.x + textBox[TXTBOX_BOTTOMLEFT].x;
  1333.     aPoints[2].y = refPoint.y + textBox[TXTBOX_BOTTOMLEFT].y;
  1334. #ifdef DEBUG
  1335.         printf("aPoints: %d,%d %d,%d <- %d,%d\n", aPoints[0].x, aPoints[0].y,
  1336.                aPoints[1].x, aPoints[1].y, aPoints[2].x, aPoints[2].y);
  1337. #endif
  1338.  
  1339.     /*
  1340.      * The following code is tricky because fonts are rendered in multiple
  1341.      * colors.  First we draw onto a black background and copy the white
  1342.      * bits.  Then we draw onto a white background and copy the black bits.
  1343.      * Both the foreground and background bits of the font are ANDed with
  1344.      * the stipple pattern as they are copied.
  1345.      */
  1346.  
  1347.         rc = GpiBitBlt(psMem, (HPS)0, 2, aPoints, ROP_ZERO, BBO_IGNORE);
  1348. #ifdef DEBUG
  1349.         if (rc!=TRUE) {
  1350.             printf("GpiBitBlt ZERO %d,%d ERROR %x\n", aPoints[0].x, aPoints[0].y,
  1351.                    WinGetLastError(hab));
  1352.         } else {
  1353.             printf("GpiBitBlt ZERO %d,%d OK\n", aPoints[0].x, aPoints[0].y);
  1354.         }
  1355. #endif
  1356.  
  1357.         /* only 512 bytes allowed in string */
  1358.         rc = GpiSetCurrentPosition(psMem, &refPoint);
  1359. #ifdef DEBUG
  1360.         if (rc!=TRUE) {
  1361.             printf("GpiSetCurrentPosition %d,%d ERROR %x\n", refPoint.x, refPoint.y,
  1362.                    WinGetLastError(hab));
  1363.         } else {
  1364.             printf("GpiSetCurrentPosition %d,%d OK\n", refPoint.x, refPoint.y);
  1365.         }
  1366. #endif
  1367.         l = length;
  1368.         str = (char *)string;
  1369.         while (length>512) {
  1370.             rc = GpiCharString(psMem, l, (PCH)str);
  1371. #ifdef DEBUG
  1372.         if (rc==GPI_ERROR) {
  1373.             printf("GpiCharString ERROR %x\n", WinGetLastError(hab));
  1374.         } else {
  1375.             printf("GpiCharString OK\n");
  1376.         }
  1377. #endif
  1378.             l -= 512;
  1379.             str += 512;
  1380.         }
  1381.         rc = GpiCharString(psMem, l, (PCH)str);
  1382. #ifdef DEBUG
  1383.         if (rc==GPI_ERROR) {
  1384.             printf("GpiCharString ERROR %x\n", WinGetLastError(hab));
  1385.         } else {
  1386.             printf("GpiCharString OK\n");
  1387.         }
  1388. #endif
  1389.  
  1390.         rc = GpiBitBlt(hps, psMem, 3, aPoints, (LONG)0x00ea, BBO_IGNORE);
  1391. #ifdef DEBUG
  1392.         if (rc==GPI_ERROR) {
  1393.             printf("GpiBitBlt ERROR %x\n", WinGetLastError(hab));
  1394.         } else {
  1395.             printf("GpiBitBlt OK\n");
  1396.         }
  1397. #endif
  1398.  
  1399.         rc = GpiBitBlt(psMem, (HPS)0, 2, aPoints, ROP_ONE, BBO_IGNORE);
  1400. #ifdef DEBUG
  1401.         if (rc!=TRUE) {
  1402.             printf("GpiBitBlt ONE %d,%d ERROR %x\n", aPoints[0].x, aPoints[0].y,
  1403.                    WinGetLastError(hab));
  1404.         } else {
  1405.             printf("GpiBitBlt ONE %d,%d OK\n", aPoints[0].x, aPoints[0].y);
  1406.         }
  1407. #endif
  1408.  
  1409.         /* only 512 bytes allowed in string */
  1410.         rc = GpiSetCurrentPosition(psMem, &refPoint);
  1411. #ifdef DEBUG
  1412.         if (rc!=TRUE) {
  1413.             printf("GpiSetCurrentPosition %d, %d ERROR %x\n", refPoint.x, refPoint.y,
  1414.                    WinGetLastError(hab));
  1415.         } else {
  1416.             printf("GpiSetCurrentPosition %d,%d OK\n", refPoint.x, refPoint.y);
  1417.         }
  1418. #endif
  1419.         l = length;
  1420.         str = (char *)string;
  1421.         while (length>512) {
  1422.             rc = GpiCharString(psMem, 512, (PCH)str);
  1423. #ifdef DEBUG
  1424.         if (rc==GPI_ERROR) {
  1425.             printf("GpiCharString ERROR %x\n", WinGetLastError(hab));
  1426.         } else {
  1427.             printf("GpiCharString OK\n");
  1428.         }
  1429. #endif
  1430.             l -= 512;
  1431.             str += 512;
  1432.         }
  1433.         rc = GpiCharString(psMem, l, (PCH)str);
  1434. #ifdef DEBUG
  1435.         if (rc==GPI_ERROR) {
  1436.             printf("GpiCharString ERROR %x\n", WinGetLastError(hab));
  1437.         } else {
  1438.             printf("GpiCharString OK\n");
  1439.         }
  1440. #endif
  1441.  
  1442.         rc = GpiBitBlt(hps, psMem, 3, aPoints, (LONG)0x00ba, BBO_IGNORE);
  1443. #ifdef DEBUG
  1444.         if (rc==GPI_ERROR) {
  1445.             printf("GpiBitBlt ERROR %x\n", WinGetLastError(hab));
  1446.         } else {
  1447.             printf("GpiBitBlt OK\n");
  1448.         }
  1449. #endif
  1450.     /*
  1451.      * Destroy the temporary bitmap and restore the device context.
  1452.      */
  1453.  
  1454.     GpiSetBitmap(psMem, oldBitmap);
  1455.     GpiDeleteBitmap(bitmap);
  1456.     GpiDestroyPS(psMem);
  1457.         DevCloseDC(dcMem);
  1458.  
  1459.     if (gc->font != None) {
  1460.         /* Set slant if necessary */
  1461.         if (logfonts[(LONG)gc->font].setShear) {
  1462.             rc = GpiSetCharShear(hps, &noShear);
  1463.         }
  1464.         rc = GpiSetCharSet(hps, oldFont);
  1465.     }
  1466.     rc = GpiSetBackMix(hps, oldBackMix);
  1467.     cBundle.lColor = oldColor;
  1468.     rc = GpiSetAttrs(hps, PRIM_CHAR, LBB_COLOR, 0L, (PBUNDLE)&cBundle);
  1469.         /* The bitmap must be reselected in the HPS */
  1470.         TkOS2UnsetStipple(hps, todPtr->bitmap.hps, todPtr->bitmap.handle,
  1471.                           oldPattern, &oldRefPoint);
  1472.  
  1473.     } else {
  1474.  
  1475.     GpiQueryTextAlignment(hps, &oldHorAlign, &oldVerAlign);
  1476.     GpiSetTextAlignment(hps, TA_LEFT, TA_BASE);
  1477.  
  1478.     GpiQueryAttrs(hps, PRIM_CHAR, LBB_COLOR, (PBUNDLE)&cBundle);
  1479.     oldColor = cBundle.lColor;
  1480.     cBundle.lColor = gc->foreground;
  1481.     rc = GpiSetAttrs(hps, PRIM_CHAR, LBB_COLOR, 0L, (PBUNDLE)&cBundle);
  1482. #ifdef DEBUG
  1483.         if (rc!=TRUE) {
  1484.             printf("GpiSetAttrs color %x ERROR %x\n", gc->foreground,
  1485.                    WinGetLastError(hab));
  1486.         } else {
  1487.             printf("GpiSetAttrs color %x OK\n", gc->foreground);
  1488.         }
  1489. #endif
  1490.  
  1491.     oldBackMix = GpiQueryBackMix(hps);
  1492.     /* We get a crash in PMMERGE.DLL on anything other than BM_LEAVEALONE */
  1493.     GpiSetBackMix(hps, BM_LEAVEALONE);
  1494.  
  1495.     if (gc->font != None) {
  1496.             rc = GpiCreateLogFont(hps, NULL, (LONG)gc->font,
  1497.                                   &(logfonts[(LONG)gc->font].fattrs));
  1498. #ifdef DEBUG
  1499.             if (rc!=GPI_ERROR) {
  1500.                 printf("GpiCreateLogFont (%x, id %d) OK\n", hps, gc->font);
  1501.             } else {
  1502.                 printf("GpiCreateLogFont (%x, id %d) ERROR, error %x\n", hps,
  1503.                        gc->font, WinGetLastError(hab));
  1504.             }
  1505. #endif
  1506.         oldFont = GpiQueryCharSet(hps);
  1507.         rc = GpiSetCharSet(hps, (LONG)gc->font);
  1508. #ifdef DEBUG
  1509.             if (rc==TRUE) {
  1510.                 printf("GpiSetCharSet (%x, id %d, %s) OK\n", hps, gc->font,
  1511.                        logfonts[(LONG)gc->font].fattrs.szFacename);
  1512.             } else {
  1513.                 printf("GpiSetCharSet (%x, id %d, %s) ERROR, error %x\n", hps,
  1514.                        gc->font, logfonts[(LONG)gc->font].fattrs.szFacename,
  1515.                        WinGetLastError(hab));
  1516.             }
  1517. #endif
  1518.         /* Set slant if necessary */
  1519.         if (logfonts[(LONG)gc->font].setShear) {
  1520.             GpiSetCharShear(hps, &(logfonts[(LONG)gc->font].shear));
  1521. #ifdef DEBUG
  1522.                 if (rc!=TRUE) {
  1523.                     printf("GpiSetCharShear font %d ERROR %x\n",
  1524.                            logfonts[(LONG)gc->font],
  1525.                            WinGetLastError(hab));
  1526.                 } else {
  1527.                     printf("GpiSetCharShear font %d OK\n",
  1528.                            logfonts[(LONG)gc->font]);
  1529.                 }
  1530. #endif
  1531.         }
  1532.             /* If this is an outline font, set the char box */
  1533.             if (logfonts[(LONG)gc->font].outline) {
  1534. #ifdef DEBUG
  1535.                 SIZEF charBox;
  1536. #endif
  1537.                 rc = TkOS2ScaleFont(hps, logfonts[(LONG)gc->font].deciPoints, 0);
  1538. #ifdef DEBUG
  1539.                 if (rc!=TRUE) {
  1540.                     printf("TkOS2ScaleFont %d ERROR %x\n",
  1541.                            logfonts[(LONG)gc->font].deciPoints,
  1542.                            WinGetLastError(hab));
  1543.                 } else {
  1544.                     printf("TkOS2ScaleFont %d OK\n",
  1545.                            logfonts[(LONG)gc->font].deciPoints);
  1546.                 }
  1547.                 rc = GpiQueryCharBox(hps, &charBox);
  1548.                 if (rc!=TRUE) {
  1549.                     printf("GpiQueryCharBox ERROR %x\n");
  1550.                 } else {
  1551.                     printf("GpiQueryCharBox OK: now cx %d (%d,%d), cy %d (%d,%d)\n", charBox.cx,
  1552.                            FIXEDINT(charBox.cx), FIXEDFRAC(charBox.cx),
  1553.                            charBox.cy, FIXEDINT(charBox.cy),
  1554.                            FIXEDFRAC(charBox.cy));
  1555.                 }
  1556. #endif
  1557.             }
  1558.     }
  1559.  
  1560.     refPoint.x = x;
  1561.     refPoint.y = y;
  1562.         /* only 512 bytes allowed in string */
  1563.         rc = GpiSetCurrentPosition(hps, &refPoint);
  1564. #ifdef DEBUG
  1565.         if (rc==TRUE) {
  1566.             printf("GpiSetCurrentPosition %d,%d OK\n", refPoint.x, refPoint.y);
  1567.         } else {
  1568.             printf("GpiSetCurrentPosition %d,%d ERROR %x\n", refPoint.x,
  1569.                    refPoint.y, WinGetLastError(hab));
  1570.         }
  1571. #endif
  1572.         l = length;
  1573.         str = (char *)string;
  1574.         while (l>512) {
  1575.             rc = GpiCharString(hps, 512, (PCH)str);
  1576. #ifdef DEBUG
  1577.         if (rc==GPI_OK) {
  1578.             printf("GpiCharString returns GPI_OK\n");
  1579.         } else {
  1580.             printf("GpiCharString returns %d, ERROR %x\n", rc,
  1581.                    WinGetLastError(hab));
  1582.         }
  1583. #endif
  1584.             l -= 512;
  1585.             str += 512;
  1586.         }
  1587.         rc = GpiCharString(hps, l, (PCH)str);
  1588. #ifdef DEBUG
  1589.         if (rc==GPI_OK) {
  1590.             printf("GpiCharString returns GPI_OK\n");
  1591.         } else {
  1592.             printf("GpiCharString returns %d, ERROR %x\n", rc,
  1593.                    WinGetLastError(hab));
  1594.         }
  1595. #endif
  1596.  
  1597.         rc = GpiSetCharSet(hps, LCID_DEFAULT);
  1598. #ifdef DEBUG
  1599.         if (rc==TRUE) {
  1600.             printf("GpiSetCharSet (%x, default) OK\n", hps);
  1601.         } else {
  1602.             printf("GpiSetCharSet (%x, default) ERROR, error %x\n", hps,
  1603.                    WinGetLastError(hab));
  1604.         }
  1605. #endif
  1606.         rc = GpiDeleteSetId(hps, (LONG)gc->font);
  1607. #ifdef DEBUG
  1608.         if (rc==TRUE) {
  1609.             printf("GpiDeleteSetId (%x, id %d) OK\n", hps, gc->font);
  1610.         } else {
  1611.             printf("GpiDeleteSetId (%x, id %d) ERROR, error %x\n", hps,
  1612.                    gc->font, WinGetLastError(hab));
  1613.         }
  1614. #endif
  1615.  
  1616.     if (gc->font != None) {
  1617.         /* Set slant if necessary */
  1618.         if (logfonts[(LONG)gc->font].setShear) {
  1619.             GpiSetCharShear(hps, &noShear);
  1620.         }
  1621.         GpiSetCharSet(hps, oldFont);
  1622.     }
  1623.     GpiSetBackMix(hps, oldBackMix);
  1624.     GpiSetBackColor(hps, oldBackColor);
  1625.     cBundle.lColor = oldColor;
  1626.     GpiSetAttrs(hps, PRIM_CHAR, LBB_COLOR, 0L, (PBUNDLE)&cBundle);
  1627.     GpiSetTextAlignment(hps, oldHorAlign, oldVerAlign);
  1628.     }
  1629.  
  1630.     TkOS2ReleaseDrawablePS(d, hps, &state);
  1631. }
  1632.  
  1633. /*
  1634.  *----------------------------------------------------------------------
  1635.  *
  1636.  * XFillRectangles --
  1637.  *
  1638.  *    Fill multiple rectangular areas in the given drawable.
  1639.  *
  1640.  * Results:
  1641.  *    None.
  1642.  *
  1643.  * Side effects:
  1644.  *    Draws onto the specified drawable.
  1645.  *
  1646.  *----------------------------------------------------------------------
  1647.  */
  1648.  
  1649. void
  1650. XFillRectangles(display, d, gc, rectangles, nrectangles)
  1651.     Display* display;
  1652.     Drawable d;
  1653.     GC gc;
  1654.     XRectangle* rectangles;
  1655.     int nrectangles;
  1656. {
  1657.     HPS hps;
  1658.     int i;
  1659.     RECTL rect;
  1660.     TkOS2PSState state;
  1661.     LONG windowHeight;
  1662.     POINTL refPoint;
  1663.     LONG oldPattern, oldBitmap;
  1664.     TkOS2Drawable *todPtr = (TkOS2Drawable *)d;
  1665.     LONG rc;
  1666.  
  1667.     if (d == None) {
  1668.     return;
  1669.     }
  1670. #ifdef DEBUG
  1671.     if (todPtr->type == TOD_BITMAP) {
  1672.          printf("XFillRectangles bitmap %x, h %x, cmap %x, depth %d, mix %x\n",
  1673.                 todPtr, todPtr->bitmap.handle, todPtr->bitmap.colormap,
  1674.                 todPtr->bitmap.depth, gc->function);
  1675.     } else {
  1676.          printf("XFillRectangles todPtr %x, winPtr %x, h %x, mix %x\n", todPtr,
  1677.                 todPtr->window.winPtr, todPtr->window.handle, gc->function);
  1678.     }
  1679. #endif
  1680.  
  1681.     windowHeight = TkOS2WindowHeight(todPtr);
  1682.  
  1683.     hps = TkOS2GetDrawablePS(display, d, &state);
  1684.     GpiSetMix(hps, mixModes[gc->function]);
  1685.  
  1686.     if ((gc->fill_style == FillStippled
  1687.         || gc->fill_style == FillOpaqueStippled)
  1688.         && gc->stipple != None) {
  1689.     HBITMAP bitmap;
  1690.         BITMAPINFOHEADER2 bmpInfo;
  1691.         LONG rc;
  1692.         DEVOPENSTRUC dop = {0L, (PSZ)"DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
  1693.         SIZEL sizl = {0,0}; /* use same page size as device */
  1694.         HDC dcMem;
  1695.     HPS psMem;
  1696.         POINTL aPoints[3]; /* Lower-left, upper-right, lower-left source */
  1697.         POINTL oldRefPoint;
  1698.  
  1699. #ifdef DEBUG
  1700.         printf("                stippled\n");
  1701. #endif
  1702.     todPtr = (TkOS2Drawable *)gc->stipple;
  1703.  
  1704.     if (todPtr->type != TOD_BITMAP) {
  1705.         panic("unexpected drawable type in stipple");
  1706.     }
  1707.  
  1708.     /*
  1709.      * Select stipple pattern into destination dc.
  1710.      */
  1711.  
  1712.     refPoint.x = gc->ts_x_origin;
  1713.     /* Translate Xlib y to PM y */
  1714.     refPoint.y = windowHeight - gc->ts_y_origin;
  1715.  
  1716.         /* The bitmap mustn't be selected in the HPS */
  1717.         TkOS2SetStipple(hps, todPtr->bitmap.hps, todPtr->bitmap.handle,
  1718.                         refPoint.x, refPoint.y, &oldPattern, &oldRefPoint);
  1719.  
  1720.     dcMem = DevOpenDC(hab, OD_MEMORY, (PSZ)"*", 5L, (PDEVOPENDATA)&dop,
  1721.                       NULLHANDLE);
  1722.     if (dcMem == DEV_ERROR) {
  1723. #ifdef DEBUG
  1724.             printf("DevOpenDC ERROR in XFillRectangles\n");
  1725. #endif
  1726.         return;
  1727.     }
  1728. #ifdef DEBUG
  1729.         printf("DevOpenDC in XFillRectangles returns %x\n", dcMem);
  1730. #endif
  1731.         psMem = GpiCreatePS(hab, dcMem, &sizl,
  1732.                             PU_PELS | GPIT_NORMAL | GPIA_ASSOC);
  1733.         if (psMem == GPI_ERROR) {
  1734. #ifdef DEBUG
  1735.             printf("GpiCreatePS ERROR in XFillRectangles: %x\n",
  1736.                    WinGetLastError(hab));
  1737. #endif
  1738.             DevCloseDC(dcMem);
  1739.             return;
  1740.         }
  1741. #ifdef DEBUG
  1742.         printf("GpiCreatePS in XFillRectangles returns %x\n", psMem);
  1743. #endif
  1744.  
  1745.     /*
  1746.      * For each rectangle, create a drawing surface which is the size of
  1747.      * the rectangle and fill it with the background color.  Then merge the
  1748.      * result with the stipple pattern.
  1749.      */
  1750.  
  1751.     for (i = 0; i < nrectangles; i++) {
  1752.         bmpInfo.cbFix = 16L;
  1753.         bmpInfo.cx = rectangles[i].width + 1;
  1754.         bmpInfo.cy = rectangles[i].height + 1;
  1755.         bmpInfo.cPlanes = 1;
  1756.         bmpInfo.cBitCount = 1;
  1757.         bitmap = GpiCreateBitmap(psMem, &bmpInfo, 0L, NULL, NULL);
  1758. #ifdef DEBUG
  1759.             if (bitmap == GPI_ERROR) {
  1760.                 printf("GpiCreateBitmap (%d,%d) GPI_ERROR %x\n",
  1761.                        bmpInfo.cx, bmpInfo.cy, WinGetLastError(hab));
  1762.             } else {
  1763.                 printf("GpiCreateBitmap (%d,%d) returned %x\n", bmpInfo.cx, bmpInfo.cy, bitmap);
  1764.             }
  1765. #endif
  1766.         oldBitmap = GpiSetBitmap(psMem, bitmap);
  1767. #ifdef DEBUG
  1768.             if (bitmap == HBM_ERROR) {
  1769.                 printf("GpiSetBitmap (%x) HBM_ERROR %x\n", bitmap,
  1770.                        WinGetLastError(hab));
  1771.             } else {
  1772.                 printf("GpiSetBitmap %x returned %x\n", bitmap, oldBitmap);
  1773.             }
  1774. #endif
  1775.  
  1776.             /* Translate the Y coordinates to PM coordinates */
  1777.  
  1778.         rect.xLeft = 0;
  1779.         rect.xRight = rectangles[i].width + 1;
  1780.         rect.yBottom = 0;
  1781.         rect.yTop = rectangles[i].height + 1;
  1782.  
  1783.         oldPattern = GpiQueryPattern(psMem);
  1784.         GpiSetPattern(psMem, PATSYM_SOLID);
  1785.         rc = WinFillRect(psMem, &rect, gc->foreground);
  1786. #ifdef DEBUG
  1787.             if (rc != TRUE) {
  1788.                 printf("WinFillRect3 (%d, %d)->(%d,%d) fg %x ERROR %x\n",
  1789.                        rect.xLeft, rect.yBottom, rect.xRight, rect.yTop,
  1790.                        gc->foreground, WinGetLastError(hab));
  1791.             } else {
  1792.                 printf("WinFillRect3 (%d, %d)->(%d,%d) fg %x OK\n",
  1793.                        rect.xLeft, rect.yBottom, rect.xRight, rect.yTop,
  1794.                        gc->foreground);
  1795.             }
  1796. #endif
  1797.             /* Translate the Y coordinates to PM coordinates */
  1798.             aPoints[0].x = rectangles[i].x;
  1799.             aPoints[0].y = windowHeight - rectangles[i].y -
  1800.                            rectangles[i].height;
  1801.             aPoints[1].x = rectangles[i].x + rectangles[i].width + 1;
  1802.             aPoints[1].y = windowHeight - rectangles[i].y + 1;
  1803.         aPoints[2].x = 0;
  1804.         aPoints[2].y = 0;
  1805.             rc = GpiBitBlt(hps, psMem, 3, aPoints, COPYFG, BBO_IGNORE);
  1806. #ifdef DEBUG
  1807.             if (rc!=TRUE) {
  1808.                 printf("    GpiBitBlt FG %x (%d,%d)(%d,%d) <- (%d,%d) ERROR %x\n",
  1809.                        gc->foreground, aPoints[0].x, aPoints[0].y,
  1810.                        aPoints[1].x, aPoints[1].y,
  1811.                        aPoints[2].x, aPoints[2].y, WinGetLastError(hab));
  1812.             } else {
  1813.                 printf("    GpiBitBlt FG %x (%d,%d)(%d,%d) <- (%d,%d) OK\n",
  1814.                        gc->foreground, aPoints[0].x, aPoints[0].y,
  1815.                        aPoints[1].x, aPoints[1].y,
  1816.                        aPoints[2].x, aPoints[2].y);
  1817.             }
  1818. #endif
  1819.         if (gc->fill_style == FillOpaqueStippled) {
  1820.             rc = WinFillRect(psMem, &rect, gc->background);
  1821. #ifdef DEBUG
  1822.                 if (rc != TRUE) {
  1823.                     printf("WinFillRect4 (%d, %d)->(%d,%d) bg %x ERROR %x\n",
  1824.                            rect.xLeft, rect.yBottom, rect.xRight, rect.yTop,
  1825.                            gc->background, WinGetLastError(hab));
  1826.                 } else {
  1827.                     printf("WinFillRect4 (%d, %d)->(%d,%d) bg %x OK\n",
  1828.                            rect.xLeft, rect.yBottom, rect.xRight, rect.yTop,
  1829.                            gc->background);
  1830.                 }
  1831. #endif
  1832.                 rc = GpiBitBlt(hps, psMem, 3, aPoints, COPYBG, BBO_IGNORE);
  1833. #ifdef DEBUG
  1834.                 if (rc!=TRUE) {
  1835.                     printf("    GpiBitBlt BG %x (%d,%d)(%d,%d) <- (%d,%d) ERROR %x\n",
  1836.                            gc->background, aPoints[0].x, aPoints[0].y,
  1837.                            aPoints[1].x, aPoints[1].y,
  1838.                            aPoints[2].x, aPoints[2].y, WinGetLastError(hab));
  1839.                 } else {
  1840.                     printf("    GpiBitBlt BG %x (%d,%d)(%d,%d) <- (%d,%d) OK\n",
  1841.                            gc->background, aPoints[0].x, aPoints[0].y,
  1842.                            aPoints[1].x, aPoints[1].y,
  1843.                            aPoints[2].x, aPoints[2].y);
  1844.             }
  1845. #endif
  1846.         }
  1847.         GpiSetPattern(psMem, oldPattern);
  1848.         GpiDeleteBitmap(bitmap);
  1849.     }
  1850.     GpiDestroyPS(psMem);
  1851.         DevCloseDC(dcMem);
  1852.         /* The bitmap must be reselected in the HPS */
  1853.         TkOS2UnsetStipple(hps, todPtr->bitmap.hps, todPtr->bitmap.handle,
  1854.                           oldPattern, &oldRefPoint);
  1855.     } else {
  1856.  
  1857.         for (i = 0; i < nrectangles; i++) {
  1858.             rect.xLeft = rectangles[i].x;
  1859.             rect.xRight = rect.xLeft + rectangles[i].width;
  1860.             rect.yBottom = windowHeight - rectangles[i].y -
  1861.                            rectangles[i].height;
  1862.             rect.yTop = windowHeight - rectangles[i].y;
  1863. #ifdef DEBUG
  1864.             printf("rectangle (%d,%d) %dx%d; %s %x\n", rectangles[i].x,
  1865.                    rectangles[i].y, rectangles[i].width, rectangles[i].height,
  1866.                    todPtr->type == TOD_BITMAP ? "bitmap" : "window",
  1867.                    todPtr->type == TOD_BITMAP ? todPtr->bitmap.handle
  1868.                                               : todPtr->window.handle);
  1869. #endif
  1870.             rc = WinFillRect(hps, &rect, gc->foreground);
  1871. #ifdef DEBUG
  1872.             if (rc==TRUE) {
  1873.                 printf("    WinFillRect5(hps %x, fg %x, (%d,%d)(%d,%d)) OK\n",
  1874.                        hps, gc->foreground, rect.xLeft, rect.yBottom,
  1875.                        rect.xRight, rect.yTop);
  1876.             } else {
  1877.                 printf("    WinFillRect5(hps %x, fg %x, (%d,%d)(%d,%d)) ERROR %x\n",
  1878.                        hps, gc->foreground, rect.xLeft, rect.yBottom,
  1879.                        rect.xRight, rect.yTop, WinGetLastError(hab));
  1880.             }
  1881. #endif
  1882.             GpiSetPattern(hps, oldPattern);
  1883.         }
  1884.     }
  1885.  
  1886.     TkOS2ReleaseDrawablePS(d, hps, &state);
  1887. }
  1888.  
  1889. /*
  1890.  *----------------------------------------------------------------------
  1891.  *
  1892.  * RenderObject --
  1893.  *
  1894.  *    This function draws a shape using a list of points, a
  1895.  *    stipple pattern, and the specified drawing function.
  1896.  *
  1897.  * Results:
  1898.  *    None.
  1899.  *
  1900.  * Side effects:
  1901.  *    None.
  1902.  *
  1903.  *----------------------------------------------------------------------
  1904.  */
  1905.  
  1906. static void
  1907. RenderObject(hps, gc, d, points, npoints, mode, pLineBundle, func)
  1908.     HPS hps;
  1909.     GC gc;
  1910.     Drawable d;
  1911.     XPoint* points;
  1912.     int npoints;
  1913.     int mode;
  1914.     PLINEBUNDLE pLineBundle;
  1915.     int func;
  1916. {
  1917.     RECTL rect;
  1918.     LINEBUNDLE oldLineBundle;
  1919.     LONG oldPattern;
  1920.     LONG oldColor;
  1921.     POINTL oldRefPoint;
  1922.     POINTL *os2Points;
  1923.     POINTL refPoint;
  1924.     POINTL aPoints[3]; /* Lower-left, upper-right, lower-left source */
  1925.     LONG windowHeight;
  1926.     POLYGON polygon;
  1927.  
  1928. #ifdef DEBUG
  1929.     printf("RenderObject, GC: line_width %d, line_style %x, cap_style %x,
  1930.            join_style %x, fill_style %x, fill_rule %x, arc_mode %x\n",
  1931.            gc->line_width, gc->line_style, gc->cap_style, gc->join_style,
  1932.            gc->fill_style, gc->fill_rule, gc->arc_mode);
  1933. #endif
  1934.     pLineBundle->lColor = gc->foreground;
  1935.     pLineBundle->lGeomWidth = gc->line_width;
  1936.     if ( func == TOP_POLYGONS) {
  1937.         pLineBundle->usType = LINETYPE_INVISIBLE;
  1938.     } else {
  1939.         pLineBundle->usType = lineStyles[gc->line_style];
  1940.     }
  1941.     pLineBundle->usEnd = capStyles[gc->cap_style];
  1942.     pLineBundle->usJoin = joinStyles[gc->join_style];
  1943.  
  1944.     /* os2Points/rect get *PM* coordinates handed to it by ConvertPoints */
  1945.     os2Points = ConvertPoints(d, points, npoints, mode, &rect);
  1946.  
  1947.     windowHeight = TkOS2WindowHeight((TkOS2Drawable *)d);
  1948.  
  1949.     if ((gc->fill_style == FillStippled
  1950.         || gc->fill_style == FillOpaqueStippled)
  1951.         && gc->stipple != None) {
  1952.  
  1953.     TkOS2Drawable *todPtr = (TkOS2Drawable *)gc->stipple;
  1954.         DEVOPENSTRUC dop = {0L, (PSZ)"DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
  1955.         SIZEL sizl = {0,0}; /* use same page size as device */
  1956.         HDC dcMem;
  1957.     HPS psMem;
  1958.     LONG width, height;
  1959.     int i;
  1960.     HBITMAP bitmap, oldBitmap;
  1961.         BITMAPINFOHEADER2 bmpInfo;
  1962.  
  1963. #ifdef DEBUG
  1964.         printf("RenderObject stippled (%x)\n", todPtr->bitmap.handle);
  1965. #endif
  1966.     
  1967.     if (todPtr->type != TOD_BITMAP) {
  1968.         panic("unexpected drawable type in stipple");
  1969.     }
  1970.  
  1971.     
  1972.     width = rect.xRight - rect.xLeft;
  1973.     /* PM coordinates are just reverse: top - bottom */
  1974.     height = rect.yTop - rect.yBottom;
  1975.  
  1976.     /*
  1977.      * Select stipple pattern into destination hps.
  1978.      */
  1979.     
  1980.     refPoint.x = gc->ts_x_origin;
  1981.     /* Translate Xlib y to PM y */
  1982.     refPoint.y = windowHeight - gc->ts_y_origin;
  1983.  
  1984.         TkOS2SetStipple(hps, todPtr->bitmap.hps, todPtr->bitmap.handle,
  1985.                         refPoint.x, refPoint.y, &oldPattern, &oldRefPoint);
  1986.  
  1987.     /*
  1988.      * Create temporary drawing surface containing a copy of the
  1989.      * destination equal in size to the bounding box of the object.
  1990.      */
  1991.     
  1992.     dcMem = DevOpenDC(hab, OD_MEMORY, (PSZ)"*", 5L, (PDEVOPENDATA)&dop,
  1993.                       NULLHANDLE);
  1994.     if (dcMem == DEV_ERROR) {
  1995. #ifdef DEBUG
  1996.             printf("DevOpenDC ERROR in RenderObject\n");
  1997. #endif
  1998.         return;
  1999.     }
  2000. #ifdef DEBUG
  2001.         printf("DevOpenDC in RenderObject returns %x\n", dcMem);
  2002. #endif
  2003.         psMem = GpiCreatePS(hab, dcMem, &sizl,
  2004.                             PU_PELS | GPIT_NORMAL | GPIA_ASSOC);
  2005.         if (psMem == GPI_ERROR) {
  2006. #ifdef DEBUG
  2007.             printf("GpiCreatePS ERROR in RenderObject: %x\n",
  2008.                    WinGetLastError(hab));
  2009. #endif
  2010.             DevCloseDC(dcMem);
  2011.             return;
  2012.         }
  2013. #ifdef DEBUG
  2014.         printf("GpiCreatePS in RenderObject returns %x\n", psMem);
  2015. #endif
  2016.  
  2017.     TkOS2SelectPalette(psMem, HWND_DESKTOP, todPtr->bitmap.colormap);
  2018.  
  2019.     /*
  2020.      * X filling includes top and left sides, excludes bottom and right sides.
  2021.      * PM filling (WinFillRect) and BitBlt-ing (GpiBitBlt) includes bottom and
  2022.      * left sides, excludes top and right sides.
  2023.      * NB! X fills a box exactly as wide and high as width and height specify,
  2024.      * while PM cuts one pixel off the right and top.
  2025.      * => decrement y (X Window System) by one / increment y (PM) by one AND
  2026.      *    increment height by one, and increment width by one.
  2027.      */
  2028.  
  2029.     bmpInfo.cbFix = sizeof(BITMAPINFOHEADER2);
  2030.     bmpInfo.cx = width + 1;
  2031.     bmpInfo.cy = height + 1;
  2032.     bitmap = GpiCreateBitmap(psMem, &bmpInfo, 0L, NULL, NULL);
  2033. #ifdef DEBUG
  2034.         if (rc==GPI_ERROR) {
  2035.             printf("    GpiCreateBitmap %dx%d ERROR %x\n", width, height,
  2036.                    WinGetLastError(hab));
  2037.         } else {
  2038.             printf("    GpiCreateBitmap %dx%d OK: %x\n", width, height, bitmap);
  2039.         }
  2040. #endif
  2041.     oldBitmap = GpiSetBitmap(psMem, bitmap);
  2042. #ifdef DEBUG
  2043.         if (rc==HBM_ERROR) {
  2044.             printf("    GpiSetBitmap %x ERROR %x\n", bitmap,
  2045.                    WinGetLastError(hab));
  2046.         } else {
  2047.             printf("    GpiSetBitmap %x OK: %x\n", bitmap, oldBitmap);
  2048.         }
  2049. #endif
  2050.     rc = GpiSetAttrs(psMem, PRIM_LINE, LBB_COLOR | LBB_GEOM_WIDTH
  2051.                      | LBB_TYPE | LBB_END | LBB_JOIN, 0L, pLineBundle);
  2052. #ifdef DEBUG
  2053.         if (rc != TRUE) {
  2054.             printf("GpiSetAttrs color %x, width %d, type %x ERROR %x\n",
  2055.                    pLineBundle->lColor, pLineBundle->lGeomWidth,
  2056.                    pLineBundle->usType, WinGetLastError(hab));
  2057.         } else {
  2058.             printf("GpiSetAttrs color %x, width %d, type %x OK\n",
  2059.                    pLineBundle->lColor, pLineBundle->lGeomWidth,
  2060.                    pLineBundle->usType);
  2061.         }
  2062. #endif
  2063.         /* Translate the Y coordinates to PM coordinates */
  2064.         aPoints[0].x = 0;    /* dest_x 0 */
  2065.         aPoints[0].y = 0;    /* dest_y 0 */
  2066.         aPoints[1].x = width + 1;    /* dest_x + width */
  2067.         aPoints[1].y = height + 1;    /* dest_y + height */
  2068.         aPoints[2].x = rect.xLeft;
  2069.         aPoints[2].y = rect.yBottom;
  2070.  
  2071.         GpiBitBlt(psMem, hps, 3, aPoints, ROP_SRCCOPY, BBO_IGNORE);
  2072. #ifdef DEBUG
  2073.         if (rc!=TRUE) {
  2074.             printf("    GpiBitBlt %x->%x ERROR %x\n", hps, psMem,
  2075.         WinGetLastError(hab));
  2076.         } else {
  2077.             printf("    GpiBitBlt %x->%x OK, aPoints (%d,%d)(%d,%d) (%d,%d)\n",
  2078.                    hps, psMem, aPoints[0].x, aPoints[0].y, aPoints[1].x,
  2079.                    aPoints[1].y, aPoints[2].x, aPoints[2].y);
  2080.         }
  2081. #endif
  2082.  
  2083.     /*
  2084.      * Translate the object to 0,0 for rendering in the temporary drawing
  2085.      * surface. 
  2086.      */
  2087.  
  2088.     for (i = 0; i < npoints; i++) {
  2089.         os2Points[i].x -= rect.xLeft;
  2090.         os2Points[i].y -= rect.yBottom;
  2091. #ifdef DEBUG
  2092.             printf("os2Points[%d].x %d, os2Points[%d].y %d\n", i,
  2093.                    os2Points[i].x, i, os2Points[i].y);
  2094. #endif
  2095.     }
  2096.  
  2097.     /*
  2098.      * Draw the object in the foreground color and copy it to the
  2099.      * destination wherever the pattern is set.
  2100.      */
  2101.  
  2102.     rc = GpiSetColor(psMem, gc->foreground);
  2103. #ifdef DEBUG
  2104.         if (rc != TRUE) {
  2105.             printf("GpiSetColor %x ERROR %x\n", gc->foreground,
  2106.                    WinGetLastError(hab));
  2107.         } else {
  2108.             printf("GpiSetColor %x OK\n", gc->foreground);
  2109.         }
  2110. #endif
  2111.     rc = GpiSetPattern(psMem, PATSYM_SOLID);
  2112.     if (func == TOP_POLYGONS) {
  2113.         rc = GpiSetCurrentPosition(psMem, os2Points);
  2114. #ifdef DEBUG
  2115.             if (rc != TRUE) {
  2116.                 printf("GpiSetCurrentPosition %d,%d ERROR %x\n",
  2117.                        os2Points[0].x, os2Points[0].y, WinGetLastError(hab));
  2118.             } else {
  2119.                 printf("GpiSetCurrentPosition %d,%d OK\n",
  2120.                        os2Points[0].x, os2Points[0].y);
  2121.             }
  2122. #endif
  2123.             polygon.ulPoints = npoints-1;
  2124.             polygon.aPointl = os2Points+1;
  2125.         rc = GpiPolygons(psMem, 1, &polygon, POLYGON_BOUNDARY |
  2126.                          (gc->fill_rule == EvenOddRule) ? POLYGON_ALTERNATE
  2127.                                                         : POLYGON_WINDING,
  2128.                          POLYGON_INCL);
  2129. #ifdef DEBUG
  2130.             if (rc == GPI_ERROR) {
  2131.                 printf("GpiPolygons ERROR %x\n", WinGetLastError(hab));
  2132.             } else {
  2133.                 printf("GpiPolygons OK\n");
  2134.             }
  2135. #endif
  2136.     } else { /* TOP_POLYLINE */
  2137.         rc = GpiSetCurrentPosition(psMem, os2Points);
  2138. #ifdef DEBUG
  2139.             if (rc != TRUE) {
  2140.                 printf("GpiSetCurrentPosition %d,%d ERROR %x\n",
  2141.                        os2Points[0].x, os2Points[0].y, WinGetLastError(hab));
  2142.             } else {
  2143.                 printf("GpiSetCurrentPosition %d,%d OK\n",
  2144.                        os2Points[0].x, os2Points[0].y);
  2145.             }
  2146. #endif
  2147.             rc = GpiBeginPath(psMem, 1);
  2148. #ifdef DEBUG
  2149.             if (rc != TRUE) {
  2150.                 printf("GpiBeginPath ERROR %x\n", WinGetLastError(hab));
  2151.             } else {
  2152.                 printf("GpiBeginPath OK\n");
  2153.             }
  2154. #endif
  2155.             rc = GpiPolyLine(psMem, npoints-1, os2Points+1);
  2156. #ifdef DEBUG
  2157.                 if (rc == GPI_ERROR) {
  2158.                     printf("GpiPolyLine ERROR %x\n", WinGetLastError(hab));
  2159.                 } else {
  2160.                     printf("GpiPolyLine OK\n");
  2161.                 }
  2162. #endif
  2163.             rc = GpiEndPath(psMem);
  2164. #ifdef DEBUG
  2165.             if (rc != TRUE) {
  2166.                 printf("GpiEndPath ERROR %x\n", WinGetLastError(hab));
  2167.             } else {
  2168.                 printf("GpiEndPath OK\n");
  2169.             }
  2170. #endif
  2171.             rc = GpiStrokePath(psMem, 1, 0);
  2172. #ifdef DEBUG
  2173.             if (rc == GPI_OK) {
  2174.                 printf("GpiStrokePath OK\n");
  2175.             } else {
  2176.                 printf("GpiStrokePath ERROR %x\n", WinGetLastError(hab));
  2177.             }
  2178. #endif
  2179.     }
  2180.         aPoints[0].x = rect.xLeft;    /* dest_x */
  2181.         aPoints[0].y = rect.yBottom;
  2182.         aPoints[1].x = rect.xRight;    /* dest_x + width */
  2183.         aPoints[1].y = rect.yTop;    /* dest_y */
  2184.         aPoints[2].x = 0;    /* src_x 0 */
  2185.         aPoints[2].y = 0;    /* Src_y */
  2186.         rc = GpiBitBlt(hps, psMem, 3, aPoints, COPYFG, BBO_IGNORE);
  2187. #ifdef DEBUG
  2188.         if (rc!=TRUE) {
  2189.             printf("GpiBitBlt FG %d,%d-%d,%d ERROR %x\n",
  2190.                    aPoints[0].x, aPoints[0].y, aPoints[1].x, aPoints[1].y,
  2191.                    WinGetLastError(hab));
  2192.         } else {
  2193.             printf("GpiBitBlt FG %d,%d-%d,%d OK\n",
  2194.                    aPoints[0].x, aPoints[0].y, aPoints[1].x, aPoints[1].y);
  2195.         }
  2196. #endif
  2197.  
  2198.     /*
  2199.      * If we are rendering an opaque stipple, then draw the polygon in the
  2200.      * background color and copy it to the destination wherever the pattern
  2201.      * is clear.
  2202.      */
  2203.  
  2204.     if (gc->fill_style == FillOpaqueStippled) {
  2205.         GpiSetColor(psMem, gc->background);
  2206.         if (func == TOP_POLYGONS) {
  2207.                 polygon.ulPoints = npoints;
  2208.                 polygon.aPointl = os2Points;
  2209.             rc = GpiPolygons(psMem, 1, &polygon,
  2210.                           (gc->fill_rule == EvenOddRule) ? POLYGON_ALTERNATE
  2211.                                                          : POLYGON_WINDING,
  2212.                           0);
  2213. #ifdef DEBUG
  2214.                 if (rc == GPI_ERROR) {
  2215.                     printf("GpiPolygons ERROR %x\n", WinGetLastError(hab));
  2216.                 } else {
  2217.                     printf("GpiPolygons OK\n");
  2218.                 }
  2219. #endif
  2220.             } else { /* TOP_POLYLINE */
  2221.                 rc = GpiBeginPath(psMem, 1);
  2222. #ifdef DEBUG
  2223.                 if (rc != TRUE) {
  2224.                     printf("GpiBeginPath ERROR %x\n", WinGetLastError(hab));
  2225.                 } else {
  2226.                     printf("GpiBeginPath OK\n");
  2227.                 }
  2228. #endif
  2229.                 rc = GpiPolyLine(psMem, npoints, os2Points);
  2230. #ifdef DEBUG
  2231.                 if (rc == GPI_ERROR) {
  2232.                     printf("GpiPolyLine ERROR %x\n", WinGetLastError(hab));
  2233.                 } else {
  2234.                     printf("GpiPolyLine OK\n");
  2235.                 }
  2236. #endif
  2237.                 rc = GpiEndPath(psMem);
  2238. #ifdef DEBUG
  2239.                 if (rc != TRUE) {
  2240.                     printf("GpiEndPath ERROR %x\n", WinGetLastError(hab));
  2241.                 } else {
  2242.                     printf("GpiEndPath OK\n");
  2243.                 }
  2244. #endif
  2245.                 rc = GpiStrokePath(psMem, 1, 0);
  2246. #ifdef DEBUG
  2247.                 if (rc == GPI_OK) {
  2248.                     printf("GpiStrokePath OK\n");
  2249.                 } else {
  2250.                     printf("GpiStrokePath ERROR %x\n", WinGetLastError(hab));
  2251.                 }
  2252. #endif
  2253.         }
  2254.             rc = GpiBitBlt(hps, psMem, 3, aPoints, COPYBG, BBO_IGNORE);
  2255. #ifdef DEBUG
  2256.             if (rc!=TRUE) {
  2257.                 printf("GpiBitBlt BG %d,%d-%d,%d ERROR %x\n",
  2258.                        aPoints[0].x, aPoints[0].y, aPoints[1].x, aPoints[1].y,
  2259.                        WinGetLastError(hab));
  2260.             } else {
  2261.                 printf("GpiBitBlt BG %d,%d-%d,%d OK\n",
  2262.                        aPoints[0].x, aPoints[0].y, aPoints[1].x, aPoints[1].y);
  2263.             }
  2264. #endif
  2265.     }
  2266.     /* end of using 254 */
  2267.         TkOS2UnsetStipple(hps, todPtr->bitmap.hps, todPtr->bitmap.handle,
  2268.                           oldPattern, &oldRefPoint);
  2269.     GpiDestroyPS(psMem);
  2270.         DevCloseDC(dcMem);
  2271.     } else {
  2272.  
  2273.     GpiQueryAttrs(hps, PRIM_LINE, LBB_COLOR | LBB_GEOM_WIDTH | LBB_TYPE,
  2274.                   &oldLineBundle);
  2275.     rc = GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR | LBB_GEOM_WIDTH | LBB_TYPE
  2276.                      | LBB_END | LBB_JOIN, 0L, pLineBundle);
  2277. #ifdef DEBUG
  2278.         if (rc != TRUE) {
  2279.             printf("GpiSetAttrs color %x, width %d, type %x ERROR %x\n",
  2280.                    pLineBundle->lColor, pLineBundle->lGeomWidth,
  2281.                    pLineBundle->usType, WinGetLastError(hab));
  2282.         } else {
  2283.             printf("GpiSetAttrs color %x, width %d, type %x OK\n",
  2284.                    pLineBundle->lColor, pLineBundle->lGeomWidth,
  2285.                    pLineBundle->usType);
  2286.         }
  2287. #endif
  2288.         oldColor = GpiQueryColor(hps);
  2289.         oldPattern = GpiQueryPattern(hps);
  2290.     rc = GpiSetColor(hps, gc->foreground);
  2291. #ifdef DEBUG
  2292.         if (rc != TRUE) {
  2293.             printf("GpiSetColor %x ERROR %x\n", gc->foreground,
  2294.                    WinGetLastError(hab));
  2295.         } else {
  2296.             printf("GpiSetColor %x OK\n", gc->foreground);
  2297.         }
  2298. #endif
  2299.     rc = GpiSetPattern(hps, PATSYM_SOLID);
  2300.     rc = GpiSetMix(hps, mixModes[gc->function]);
  2301.  
  2302.         if (func == TOP_POLYGONS) {
  2303.         rc = GpiSetCurrentPosition(hps, os2Points);
  2304. #ifdef DEBUG
  2305.             if (rc != TRUE) {
  2306.                 printf("GpiSetCurrentPosition %d,%d ERROR %x\n",
  2307.                        os2Points[0].x, os2Points[0].y, WinGetLastError(hab));
  2308.             } else {
  2309.                 printf("GpiSetCurrentPosition %d,%d OK\n",
  2310.                        os2Points[0].x, os2Points[0].y);
  2311.             }
  2312. #endif
  2313.             polygon.ulPoints = npoints-1;
  2314.             polygon.aPointl = os2Points+1;
  2315.             rc = GpiPolygons(hps, 1, &polygon, POLYGON_BOUNDARY |
  2316.                              (gc->fill_rule == EvenOddRule) ? POLYGON_ALTERNATE
  2317.                                                             : POLYGON_WINDING,
  2318.                          POLYGON_INCL);
  2319. #ifdef DEBUG
  2320.             if (rc == GPI_ERROR) {
  2321.                 printf("GpiPolygons ERROR %x\n", WinGetLastError(hab));
  2322.             } else {
  2323.                 printf("GpiPolygons OK\n");
  2324.             }
  2325. #endif
  2326.         } else { /* TOP_POLYLINE */
  2327.         rc = GpiSetCurrentPosition(hps, os2Points);
  2328. #ifdef DEBUG
  2329.             if (rc != TRUE) {
  2330.                 printf("GpiSetCurrentPosition %d,%d ERROR %x\n",
  2331.                        os2Points[0].x, os2Points[0].y, WinGetLastError(hab));
  2332.             } else {
  2333.                 printf("GpiSetCurrentPosition %d,%d OK\n",
  2334.                        os2Points[0].x, os2Points[0].y);
  2335.             }
  2336. #endif
  2337.             rc = GpiBeginPath(hps, 1);
  2338. #ifdef DEBUG
  2339.             if (rc != TRUE) {
  2340.                 printf("GpiBeginPath ERROR %x\n", WinGetLastError(hab));
  2341.             } else {
  2342.                 printf("GpiBeginPath OK\n");
  2343.             }
  2344. #endif
  2345.             rc = GpiPolyLine(hps, npoints-1, os2Points+1);
  2346. #ifdef DEBUG
  2347.             if (rc == GPI_ERROR) {
  2348.                 printf("GpiPolyLine ERROR %x\n", WinGetLastError(hab));
  2349.             } else {
  2350.                 printf("GpiPolyLine OK\n");
  2351.             }
  2352. #endif
  2353.  
  2354.             rc = GpiEndPath(hps);
  2355. #ifdef DEBUG
  2356.             if (rc != TRUE) {
  2357.                 printf("GpiEndPath ERROR %x\n", WinGetLastError(hab));
  2358.             } else {
  2359.                 printf("GpiEndPath OK\n");
  2360.             }
  2361. #endif
  2362.             rc = GpiStrokePath(hps, 1, 0);
  2363. #ifdef DEBUG
  2364.             if (rc == GPI_OK) {
  2365.                 printf("GpiStrokePath OK\n");
  2366.             } else {
  2367.                 printf("GpiStrokePath ERROR %x\n", WinGetLastError(hab));
  2368.             }
  2369. #endif
  2370.         }
  2371.  
  2372.     GpiSetColor(hps, oldColor);
  2373.     GpiSetPattern(hps, oldPattern);
  2374.     GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR | LBB_GEOM_WIDTH | LBB_TYPE, 0L,
  2375.                 &oldLineBundle);
  2376.     }
  2377. }
  2378.  
  2379. /*
  2380.  *----------------------------------------------------------------------
  2381.  *
  2382.  * XDrawLines --
  2383.  *
  2384.  *    Draw connected lines.
  2385.  *
  2386.  * Results:
  2387.  *    None.
  2388.  *
  2389.  * Side effects:
  2390.  *    Renders a series of connected lines.
  2391.  *
  2392.  *----------------------------------------------------------------------
  2393.  */
  2394.  
  2395. void
  2396. XDrawLines(display, d, gc, points, npoints, mode)
  2397.     Display* display;
  2398.     Drawable d;
  2399.     GC gc;
  2400.     XPoint* points;
  2401.     int npoints;
  2402.     int mode;
  2403. {
  2404.     LINEBUNDLE lineBundle;
  2405.     TkOS2PSState state;
  2406.     HPS hps;
  2407.  
  2408. #ifdef DEBUG
  2409.     printf("XDrawLines fg %x, bg %x, width %d\n", gc->foreground,
  2410.            gc->background, gc->line_width);
  2411. #endif
  2412.     
  2413.     if (d == None) {
  2414.     return;
  2415.     }
  2416.  
  2417.     hps = TkOS2GetDrawablePS(display, d, &state);
  2418.  
  2419.     RenderObject(hps, gc, d, points, npoints, mode, &lineBundle, TOP_POLYLINE);
  2420.     
  2421.     TkOS2ReleaseDrawablePS(d, hps, &state);
  2422. }
  2423.  
  2424. /*
  2425.  *----------------------------------------------------------------------
  2426.  *
  2427.  * XFillPolygon --
  2428.  *
  2429.  *    Draws a filled polygon.
  2430.  *
  2431.  * Results:
  2432.  *    None.
  2433.  *
  2434.  * Side effects:
  2435.  *    Draws a filled polygon on the specified drawable.
  2436.  *
  2437.  *----------------------------------------------------------------------
  2438.  */
  2439.  
  2440. void
  2441. XFillPolygon(display, d, gc, points, npoints, shape, mode)
  2442.     Display* display;
  2443.     Drawable d;
  2444.     GC gc;
  2445.     XPoint* points;
  2446.     int npoints;
  2447.     int shape;
  2448.     int mode;
  2449. {
  2450.     LINEBUNDLE lineBundle;
  2451.     TkOS2PSState state;
  2452.     HPS hps;
  2453.  
  2454. #ifdef DEBUG
  2455.     printf("XFillPolygon\n");
  2456. #endif
  2457.  
  2458.     if (d == None) {
  2459.     return;
  2460.     }
  2461.  
  2462.     hps = TkOS2GetDrawablePS(display, d, &state);
  2463.  
  2464.     RenderObject(hps, gc, d, points, npoints, mode, &lineBundle, TOP_POLYGONS);
  2465.  
  2466.     TkOS2ReleaseDrawablePS(d, hps, &state);
  2467. }
  2468.  
  2469. /*
  2470.  *----------------------------------------------------------------------
  2471.  *
  2472.  * XDrawRectangle --
  2473.  *
  2474.  *    Draws a rectangle.
  2475.  *
  2476.  * Results:
  2477.  *    None.
  2478.  *
  2479.  * Side effects:
  2480.  *    Draws a rectangle on the specified drawable.
  2481.  *
  2482.  *----------------------------------------------------------------------
  2483.  */
  2484.  
  2485. void
  2486. XDrawRectangle(display, d, gc, x, y, width, height)
  2487.     Display* display;
  2488.     Drawable d;
  2489.     GC gc;
  2490.     int x;
  2491.     int y;
  2492.     unsigned int width;
  2493.     unsigned int height;
  2494. {
  2495.     LINEBUNDLE lineBundle, oldLineBundle;
  2496.     TkOS2PSState state;
  2497.     LONG oldPattern;
  2498.     HPS hps;
  2499.     POINTL oldCurrent, changePoint;
  2500.     LONG windowHeight;
  2501.  
  2502. #ifdef DEBUG
  2503.     printf("XDrawRectangle\n");
  2504. #endif
  2505.  
  2506.     if (d == None) {
  2507.     return;
  2508.     }
  2509.  
  2510.     windowHeight = TkOS2WindowHeight((TkOS2Drawable *)d);
  2511.  
  2512.     hps = TkOS2GetDrawablePS(display, d, &state);
  2513.  
  2514.     GpiQueryAttrs(hps, PRIM_LINE, LBB_COLOR | LBB_GEOM_WIDTH | LBB_TYPE,
  2515.                   &oldLineBundle);
  2516.     lineBundle.lColor = gc->foreground;
  2517.     lineBundle.lGeomWidth = gc->line_width;
  2518.     lineBundle.usType = LINETYPE_SOLID;
  2519.     GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR | LBB_GEOM_WIDTH | LBB_TYPE, 0L,
  2520.                 &lineBundle);
  2521.     oldPattern = GpiQueryPattern(hps);
  2522.     GpiSetPattern(hps, PATSYM_NOSHADE);
  2523.     GpiSetMix(hps, mixModes[gc->function]);
  2524.  
  2525.     GpiQueryCurrentPosition(hps, &oldCurrent);
  2526.     changePoint.x = x;
  2527.     /* Translate the Y coordinates to PM coordinates */
  2528.     changePoint.y = windowHeight - y;
  2529.     GpiSetCurrentPosition(hps, &changePoint);
  2530.     /*
  2531.      * Now put other point of box in changePoint.
  2532.      * NB! X draws a box 1 pixel wider and higher than width and height
  2533.      * specify.
  2534.      */
  2535.     changePoint.x += width + 1;
  2536.     changePoint.y -= (height + 1);    /* PM coordinates are reverse */
  2537.     GpiBox(hps, DRO_OUTLINE, &changePoint, 0L, 0L);
  2538.     GpiSetCurrentPosition(hps, &oldCurrent);
  2539.  
  2540.     GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR | LBB_GEOM_WIDTH | LBB_TYPE, 0L,
  2541.                 &oldLineBundle);
  2542.     GpiSetPattern(hps, oldPattern);
  2543.     TkOS2ReleaseDrawablePS(d, hps, &state);
  2544. }
  2545.  
  2546. /*
  2547.  *----------------------------------------------------------------------
  2548.  *
  2549.  * XDrawArc --
  2550.  *
  2551.  *    Draw an arc.
  2552.  *
  2553.  * Results:
  2554.  *    None.
  2555.  *
  2556.  * Side effects:
  2557.  *    Draws an arc on the specified drawable.
  2558.  *
  2559.  *----------------------------------------------------------------------
  2560.  */
  2561.  
  2562. void
  2563. XDrawArc(display, d, gc, x, y, width, height, angle1, angle2)
  2564.     Display* display;
  2565.     Drawable d;
  2566.     GC gc;
  2567.     int x;
  2568.     int y;
  2569.     unsigned int width;
  2570.     unsigned int height;
  2571.     int angle1;
  2572.     int angle2;
  2573. {
  2574. #ifdef DEBUG
  2575.     printf("XDrawArc d %x (%d,%d) %dx%d, a1 %d a2 %d\n", d, x, y, width, height,
  2576.            angle1, angle2);
  2577. #endif
  2578.     display->request++;
  2579.  
  2580.     DrawOrFillArc(display, d, gc, x, y, width, height, angle1, angle2, 0);
  2581. }
  2582.  
  2583. /*
  2584.  *----------------------------------------------------------------------
  2585.  *
  2586.  * XFillArc --
  2587.  *
  2588.  *    Draw a filled arc.
  2589.  *
  2590.  * Results:
  2591.  *    None.
  2592.  *
  2593.  * Side effects:
  2594.  *    Draws a filled arc on the specified drawable.
  2595.  *
  2596.  *----------------------------------------------------------------------
  2597.  */
  2598.  
  2599. void
  2600. XFillArc(display, d, gc, x, y, width, height, angle1, angle2)
  2601.     Display* display;
  2602.     Drawable d;
  2603.     GC gc;
  2604.     int x;
  2605.     int y;
  2606.     unsigned int width;
  2607.     unsigned int height;
  2608.     int angle1;
  2609.     int angle2;
  2610. {
  2611. #ifdef DEBUG
  2612.     printf("XFillArc d %x (%d,%d) %dx%d, a1 %d a2 %d\n", d, x, y, width, height,
  2613.            angle1, angle2);
  2614. #endif
  2615.     display->request++;
  2616.  
  2617.     DrawOrFillArc(display, d, gc, x, y, width, height, angle1, angle2, 1);
  2618. }
  2619.  
  2620. /*
  2621.  *----------------------------------------------------------------------
  2622.  *
  2623.  * DrawOrFillArc --
  2624.  *
  2625.  *    This procedure handles the rendering of drawn or filled
  2626.  *    arcs and chords.
  2627.  *
  2628.  * Results:
  2629.  *    None.
  2630.  *
  2631.  * Side effects:
  2632.  *    Renders the requested arc.
  2633.  *
  2634.  *----------------------------------------------------------------------
  2635.  */
  2636.  
  2637. static void
  2638. DrawOrFillArc(display, d, gc, x, y, width, height, angle1, angle2, fill)
  2639.     Display *display;
  2640.     Drawable d;
  2641.     GC gc;
  2642.     int x, y;            /* left top */
  2643.     unsigned int width, height;
  2644.     int angle1;            /* angle1: three-o'clock (deg*64) */
  2645.     int angle2;            /* angle2: relative (deg*64) */
  2646.     int fill;            /* ==0 draw, !=0 fill */
  2647. {
  2648.     HPS hps;
  2649.     LONG oldColor, oldMix, oldPattern;
  2650.     LINEBUNDLE lineBundle, oldLineBundle;
  2651.     AREABUNDLE aBundle;
  2652.     int sign;
  2653.     POINTL center, curPt;
  2654.     TkOS2PSState state;
  2655.     LONG windowHeight;
  2656.     ARCPARAMS arcParams, oldArcParams;
  2657.     double a1sin, a1cos;
  2658.     TkOS2Drawable *todPtr = (TkOS2Drawable *)d;
  2659.     POINTL refPoint;
  2660.  
  2661.     if (d == None) {
  2662.     return;
  2663.     }
  2664.     a1sin = sin(XAngleToRadians(angle1));
  2665.     a1cos = cos(XAngleToRadians(angle1));
  2666.     windowHeight = TkOS2WindowHeight(todPtr);
  2667.  
  2668. #ifdef DEBUG
  2669.     printf("DrawOrFillArc %d,%d (PM %d), %dx%d, c %x, a1 %d (%f), a2 %d, %s, %s, %s\n",
  2670.            x, y, windowHeight - y, width, height, gc->foreground, angle1,
  2671.            XAngleToRadians(angle1), angle2, fill ? "fill" : "nofill",
  2672.            gc->arc_mode == ArcChord ? "Chord" : "Arc/Pie",
  2673.            ((gc->fill_style == FillStippled || gc->fill_style == FillOpaqueStippled)
  2674.              && gc->stipple != None) ? "stippled " : "not stippled");
  2675. #endif
  2676.  
  2677.     /* Translate the Y coordinates to PM coordinates */
  2678.     y = windowHeight - y;
  2679.     /* Translate angles back to positive degrees */
  2680.     angle1 = abs(angle1 / 64);
  2681.     if (angle2 < 0) {
  2682.         sign = -1;
  2683.         /*
  2684.          * Not only the sweep but also the starting angle gets computed
  2685.          * counter-clockwise when Arc Param Q is negative (p*q actually).
  2686.          */
  2687.         angle1 = 360 - angle1;
  2688.     }
  2689.     else {
  2690.         sign = 1;
  2691.     }
  2692.     angle2 = abs(angle2 / 64);
  2693.  
  2694.     hps = TkOS2GetDrawablePS(display, d, &state);
  2695.  
  2696.     oldColor = GpiQueryColor(hps);
  2697.     oldPattern = GpiQueryPattern(hps);
  2698.     oldMix = GpiQueryMix(hps);
  2699.     GpiSetColor(hps, gc->foreground);
  2700.     GpiSetPattern(hps, PATSYM_SOLID);
  2701.     GpiSetMix(hps, mixModes[gc->function]);
  2702.  
  2703.     /*
  2704.      * Now draw a filled or open figure.
  2705.      */
  2706.  
  2707.     GpiQueryAttrs(hps, PRIM_LINE, LBB_COLOR | LBB_GEOM_WIDTH | LBB_TYPE,
  2708.                   &oldLineBundle);
  2709.     if ((gc->fill_style == FillStippled || gc->fill_style == FillOpaqueStippled)
  2710.         && gc->stipple != None) {
  2711.         HBITMAP bitmap, oldBitmap;
  2712.         BITMAPINFOHEADER2 bmpInfo;
  2713.         LONG rc;
  2714.         DEVOPENSTRUC dop = {0L, (PSZ)"DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
  2715.         SIZEL sizl = {0,0}; /* use same page size as device */
  2716.         HDC dcMem;
  2717.         HPS psMem;
  2718.         POINTL aPoints[3]; /* Lower-left, upper-right, lower-left source */
  2719.         POINTL oldRefPoint;
  2720.  
  2721.         todPtr = (TkOS2Drawable *)gc->stipple;
  2722.  
  2723.         if (todPtr->type != TOD_BITMAP) {
  2724.             panic("unexpected drawable type in stipple");
  2725.         }
  2726.  
  2727.         /*
  2728.          * Select stipple pattern into destination dc.
  2729.          */
  2730.         /* Translate Xlib y to PM y */
  2731.         refPoint.x = gc->ts_x_origin;
  2732.         refPoint.y = windowHeight - gc->ts_y_origin;
  2733.  
  2734.         dcMem = DevOpenDC(hab, OD_MEMORY, (PSZ)"*", 5L, (PDEVOPENDATA)&dop,
  2735.                           NULLHANDLE);
  2736.         if (dcMem == DEV_ERROR) {
  2737. #ifdef DEBUG
  2738.             printf("DevOpenDC ERROR in DrawOrFillArc\n");
  2739. #endif
  2740.             return;
  2741.         }
  2742. #ifdef DEBUG
  2743.         printf("DevOpenDC in DrawOrFillArc returns %x\n", dcMem);
  2744. #endif
  2745.         psMem = GpiCreatePS(hab, dcMem, &sizl,
  2746.                             PU_PELS | GPIT_NORMAL | GPIA_ASSOC);
  2747.         if (psMem == GPI_ERROR) {
  2748. #ifdef DEBUG
  2749.             printf("GpiCreatePS ERROR in DrawOrFillArc: %x\n",
  2750.                    WinGetLastError(hab));
  2751. #endif
  2752.             DevCloseDC(dcMem);
  2753.             return;
  2754.         }
  2755. #ifdef DEBUG
  2756.         printf("GpiCreatePS in DrawOrFillArc returns %x\n", psMem);
  2757. #endif
  2758.  
  2759.         rc = GpiQueryArcParams(psMem, &oldArcParams);
  2760.         arcParams.lP = width / 2;
  2761.         arcParams.lQ = sign * (height / 2);
  2762.         arcParams.lR = 0;
  2763.         arcParams.lS = 0;
  2764.         rc = GpiSetArcParams(psMem, &arcParams);
  2765. #ifdef DEBUG
  2766.         if (rc != TRUE) {
  2767.             printf("GpiSetArcParams p %d q %d (%d) ERROR %x\n", arcParams.lP,
  2768.                    arcParams.lQ, arcParams.lP * arcParams.lQ,
  2769.                    WinGetLastError(hab));
  2770.         } else {
  2771.             printf("GpiSetArcParams p %d q %d (%d) OK\n", arcParams.lP,
  2772.                    arcParams.lQ, arcParams.lP * arcParams.lQ);
  2773.         }
  2774. #endif
  2775.  
  2776.     /*
  2777.      * Draw the object in the foreground color and copy it to the
  2778.      * destination wherever the pattern is set.
  2779.      */
  2780.  
  2781.     rc = GpiSetColor(psMem, gc->foreground);
  2782. #ifdef DEBUG
  2783.         if (rc != TRUE) {
  2784.             printf("GpiSetColor %x ERROR %x\n", gc->foreground,
  2785.                    WinGetLastError(hab));
  2786.         } else {
  2787.             printf("GpiSetColor %x OK\n", gc->foreground);
  2788.         }
  2789. #endif
  2790.  
  2791.     /*
  2792.      * X filling includes top and left sides, excludes bottom and right sides.
  2793.      * PM filling (WinFillRect) and BitBlt-ing (GpiBitBlt) includes bottom and
  2794.      * left sides, excludes top and right sides.
  2795.      * NB! X fills a box exactly as wide and high as width and height specify,
  2796.      * while PM cuts one pixel off the right and top.
  2797.      * => decrement y (X Window System) by one / increment y (PM) by one AND
  2798.      *    increment height by one, and increment width by one.
  2799.      */
  2800.  
  2801.         bmpInfo.cbFix = 16L;
  2802.     /* Bitmap must be able to contain a thicker line! */
  2803.         bmpInfo.cx = width + gc->line_width + 1;
  2804.         bmpInfo.cy = height + gc->line_width + 1;
  2805.         bmpInfo.cPlanes = 1;
  2806.         bmpInfo.cBitCount = display->screens[display->default_screen].root_depth;
  2807.         bitmap = GpiCreateBitmap(psMem, &bmpInfo, 0L, NULL, NULL);
  2808. #ifdef DEBUG
  2809.         if (bitmap == GPI_ERROR) {
  2810.             printf("GpiCreateBitmap (%d,%d) GPI_ERROR %x\n", bmpInfo.cx,
  2811.                    bmpInfo.cy, WinGetLastError(hab));
  2812.         } else {
  2813.             printf("GpiCreateBitmap (%d,%d) returned %x\n", bmpInfo.cx,
  2814.                    bmpInfo.cy, bitmap);
  2815.         }
  2816. #endif
  2817.         oldBitmap = GpiSetBitmap(psMem, bitmap);
  2818. #ifdef DEBUG
  2819.         if (bitmap == HBM_ERROR) {
  2820.             printf("GpiSetBitmap (%x) HBM_ERROR %x\n", bitmap,
  2821.                    WinGetLastError(hab));
  2822.         } else {
  2823.             printf("GpiSetBitmap %x returned %x\n", bitmap, oldBitmap);
  2824.         }
  2825. #endif
  2826.  
  2827.         TkOS2SelectPalette(psMem, HWND_DESKTOP, todPtr->bitmap.colormap);
  2828.  
  2829.         /* Line width! */
  2830.         aPoints[0].x = 0;
  2831.         aPoints[0].y = 0;
  2832.         aPoints[1].x = width + gc->line_width + 1;
  2833.         aPoints[1].y = height + gc->line_width + 1;
  2834.         aPoints[2].x = x - (gc->line_width/2);
  2835.         aPoints[2].y = y - height + 1 - (gc->line_width/2);
  2836.  
  2837.         rc = GpiBitBlt(psMem, hps, 3, aPoints, ROP_SRCCOPY, BBO_IGNORE);
  2838. #ifdef DEBUG
  2839.         if (rc!=TRUE) {
  2840.             printf("    GpiBitBlt %x->%x ERROR %x\n", hps, psMem,
  2841.                    WinGetLastError(hab));
  2842.         } else {
  2843.             printf("    GpiBitBlt %x->%x OK, aPoints (%d,%d)(%d,%d) (%d,%d)\n", hps,
  2844.                    psMem, aPoints[0].x, aPoints[0].y, aPoints[1].x,
  2845.                    aPoints[1].y, aPoints[2].x, aPoints[2].y);
  2846.         }
  2847. #endif
  2848.  
  2849.         /* The bitmap mustn't be selected in the HPS */
  2850.         TkOS2SetStipple(hps, todPtr->bitmap.hps, todPtr->bitmap.handle,
  2851.                         refPoint.x, refPoint.y, &oldPattern, &oldRefPoint);
  2852.         /* Drawing */
  2853.         /* Center of arc is at x+(0.5*width),y-(0.5*height) */
  2854.         /* Translate to 0,0 for rendering in psMem */
  2855.         center.x = (0.5 * width) + (gc->line_width/2);
  2856.         center.y = (0.5 * height) + (gc->line_width/2);
  2857.         lineBundle.lColor = gc->foreground;
  2858.         lineBundle.lGeomWidth = gc->line_width;
  2859.         lineBundle.usType = LINETYPE_SOLID;
  2860.         rc = GpiSetAttrs(psMem, PRIM_LINE,
  2861.                          LBB_COLOR | LBB_GEOM_WIDTH | LBB_TYPE,
  2862.                          0L, &lineBundle);
  2863. #ifdef DEBUG
  2864.         if (rc != TRUE) {
  2865.             printf("GpiSetAttrs ERROR %x\n", WinGetLastError(hab));
  2866.         } else {
  2867.             printf("GpiSetAttrs OK\n");
  2868.         }
  2869. #endif
  2870.         aBundle.lColor = gc->foreground;
  2871.         rc = GpiSetAttrs(psMem, PRIM_AREA, LBB_COLOR, 0L, (PBUNDLE)&aBundle);
  2872. #ifdef DEBUG
  2873.         if (rc!=TRUE) {
  2874.             printf("GpiSetAttrs areaColor %d ERROR %x\n", aBundle.lColor,
  2875.                    WinGetLastError(hab));
  2876.         } else {
  2877.             printf("GpiSetAttrs areaColor %d OK\n", aBundle.lColor);
  2878.         }
  2879. #endif
  2880.         if (!fill) {
  2881.             curPt.x = center.x + (int) (0.5 * width * a1cos);
  2882.             curPt.y = center.y + (int) (0.5 * height * a1sin);
  2883.             rc = GpiSetCurrentPosition(psMem, &curPt);
  2884. #ifdef DEBUG
  2885.             if (rc != TRUE) {
  2886.                 printf("GpiSetCurrentPosition %d,%d -> %d,%d ERROR %x\n",
  2887.                        center.x, center.y, curPt.x, curPt.y,
  2888.                        WinGetLastError(hab));
  2889.             } else {
  2890.                 printf("GpiSetCurrentPosition %d,%d -> %d,%d OK\n",
  2891.                        center.x, center.y, curPt.x, curPt.y);
  2892.             }
  2893. #endif
  2894.             rc = GpiBeginPath(psMem, 1);
  2895. #ifdef DEBUG
  2896.             if (rc != TRUE) {
  2897.                 printf("GpiBeginPath ERROR %x\n", WinGetLastError(hab));
  2898.             } else {
  2899.                 printf("GpiBeginPath OK\n");
  2900.             }
  2901. #endif
  2902.             rc= GpiPartialArc(psMem, ¢er, MAKEFIXED(1, 0),
  2903.                               MAKEFIXED(angle1, 0), MAKEFIXED(angle2, 0));
  2904. #ifdef DEBUG
  2905.             if (rc == GPI_ERROR) {
  2906.                 printf("GpiPartialArc a1 %d, a2 %d ERROR %x\n", angle1, angle2,
  2907.                        WinGetLastError(hab));
  2908.             } else {
  2909.                 printf("GpiPartialArc a1 %d, a2 %d OK\n", angle1, angle2);
  2910.             }
  2911. #endif
  2912.             rc = GpiEndPath(psMem);
  2913. #ifdef DEBUG
  2914.             if (rc != TRUE) {
  2915.                 printf("GpiEndPath ERROR %x\n", WinGetLastError(hab));
  2916.             } else {
  2917.                 printf("GpiEndPath OK\n");
  2918.             }
  2919. #endif
  2920.             rc = GpiStrokePath(psMem, 1, 0);
  2921. #ifdef DEBUG
  2922.             if (rc == GPI_OK) {
  2923.                 printf("GpiStrokePath OK\n");
  2924.             } else {
  2925.                 printf("GpiStrokePath ERROR %x\n", WinGetLastError(hab));
  2926.             }
  2927. #endif
  2928.         } else {
  2929.             curPt.x = center.x + (int) (0.5 * width * a1cos);
  2930.             curPt.y = center.y + (int) (0.5 * height * a1sin);
  2931.             rc = GpiSetCurrentPosition(psMem, &curPt);
  2932.             if (gc->arc_mode == ArcChord) {
  2933.                 /* Chord */
  2934.                 /*
  2935.                  * See GPI reference: first do GpiPartialArc with invisible,
  2936.                  * line then again with visible line, in an Area for filling.
  2937.                  */
  2938.                 rc = GpiSetLineType(psMem, LINETYPE_INVISIBLE);
  2939. #ifdef DEBUG
  2940.                 if (rc != TRUE) {
  2941.                     printf("GpiSetLineType ERROR %x\n", WinGetLastError(hab));
  2942.                 } else {
  2943.                     printf("GpiSetLineType OK\n");
  2944.                 }
  2945. #endif
  2946.                 rc = GpiPartialArc(psMem, ¢er, MAKEFIXED(1, 0),
  2947.                                    MAKEFIXED(angle1, 0), MAKEFIXED(angle2, 0));
  2948. #ifdef DEBUG
  2949.                 if (rc == GPI_ERROR) {
  2950.                     printf("GpiPartialArc a1 %d, a2 %d ERROR %x\n", angle1,
  2951.                            angle2, WinGetLastError(hab));
  2952.                 } else {
  2953.                     printf("GpiPartialArc a1 %d, a2 %d OK\n", angle1, angle2);
  2954.                 }
  2955. #endif
  2956.                 rc = GpiSetLineType(psMem, LINETYPE_SOLID);
  2957. #ifdef DEBUG
  2958.                 if (rc != TRUE) {
  2959.                     printf("GpiSetLineType ERROR %x\n", WinGetLastError(hab));
  2960.                 } else {
  2961.                     printf("GpiSetLineType OK\n");
  2962.                 }
  2963. #endif
  2964.                 rc = GpiBeginArea(psMem, BA_NOBOUNDARY|BA_ALTERNATE);
  2965. #ifdef DEBUG
  2966.                 if (rc != TRUE) {
  2967.                     printf("GpiBeginArea ERROR %x\n", WinGetLastError(hab));
  2968.                 } else {
  2969.                     printf("GpiBeginArea OK\n");
  2970.                 }
  2971. #endif
  2972.                 rc = GpiPartialArc(psMem, ¢er, MAKEFIXED(1, 0),
  2973.                                    MAKEFIXED(angle1, 0), MAKEFIXED(angle2, 0));
  2974. #ifdef DEBUG
  2975.                 if (rc == GPI_ERROR) {
  2976.                     printf("GpiPartialArc a1 %d, a2 %d ERROR %x\n", angle1,
  2977.                            angle2, WinGetLastError(hab));
  2978.                 } else {
  2979.                     printf("GpiPartialArc a1 %d, a2 %d OK\n", angle1, angle2);
  2980.                 }
  2981. #endif
  2982.                 rc = GpiEndArea(psMem);
  2983. #ifdef DEBUG
  2984.                 if (rc == GPI_OK) {
  2985.                     printf("GpiEndArea OK\n");
  2986.                 } else {
  2987.                     printf("GpiEndArea ERROR %x\n", WinGetLastError(hab));
  2988.                 }
  2989. #endif
  2990.             } else if ( gc->arc_mode == ArcPieSlice ) {
  2991.                 /* Pie */
  2992.                 rc = GpiSetCurrentPosition(psMem, ¢er);
  2993.                 rc = GpiBeginArea(psMem, BA_NOBOUNDARY|BA_ALTERNATE);
  2994. #ifdef DEBUG
  2995.                 if (rc != TRUE) {
  2996.                     printf("GpiBeginArea ERROR %x\n", WinGetLastError(hab));
  2997.                 } else {
  2998.                     printf("GpiBeginArea OK\n");
  2999.                 }
  3000. #endif
  3001.                 rc = GpiPartialArc(psMem, ¢er, MAKEFIXED(1, 0),
  3002.                                    MAKEFIXED(angle1, 0), MAKEFIXED(angle2, 0));
  3003. #ifdef DEBUG
  3004.                 if (rc == GPI_ERROR) {
  3005.                     printf("GpiPartialArc a1 %d, a2 %d ERROR %x\n", angle1,
  3006.                            angle2, WinGetLastError(hab));
  3007.                 } else {
  3008.                     printf("GpiPartialArc a1 %d, a2 %d OK\n", angle1, angle2);
  3009.                 }
  3010. #endif
  3011.                 rc = GpiLine(psMem, ¢er);
  3012. #ifdef DEBUG
  3013.                 if (rc == GPI_OK) {
  3014.                     printf("GpiLine OK\n");
  3015.                 } else {
  3016.                     printf("GpiLine ERROR %x\n", WinGetLastError(hab));
  3017.                 }
  3018. #endif
  3019.                 rc = GpiEndArea(psMem);
  3020. #ifdef DEBUG
  3021.                 if (rc == GPI_OK) {
  3022.                     printf("GpiEndArea OK\n");
  3023.                 } else {
  3024.                     printf("GpiEndArea ERROR %x\n", WinGetLastError(hab));
  3025.                 }
  3026. #endif
  3027.             }
  3028.         }
  3029.         /* Translate the Y coordinates to PM coordinates */
  3030.         aPoints[0].x = x - (gc->line_width/2);
  3031.         aPoints[0].y = y - height + 1 - (gc->line_width/2);
  3032.         aPoints[1].x = x + width + 1 + (gc->line_width/2);
  3033.         aPoints[1].y = y + 2 + (gc->line_width/2);
  3034.         aPoints[2].x = 0;
  3035.         aPoints[2].y = 0;
  3036.         rc = GpiBitBlt(hps, psMem, 3, aPoints, COPYFG, BBO_IGNORE);
  3037. #ifdef DEBUG
  3038.         if (rc!=TRUE) {
  3039.             printf("    GpiBitBlt FG %x (%d,%d)(%d,%d) <- (%d,%d) ERROR %x\n",
  3040.                    gc->foreground, aPoints[0].x, aPoints[0].y,
  3041.                    aPoints[1].x, aPoints[1].y,
  3042.                    aPoints[2].x, aPoints[2].y, WinGetLastError(hab));
  3043.         } else {
  3044.             printf("    GpiBitBlt FG %x (%d,%d)(%d,%d) <- (%d,%d) OK\n",
  3045.                    gc->foreground, aPoints[0].x, aPoints[0].y,
  3046.                    aPoints[1].x, aPoints[1].y,
  3047.                    aPoints[2].x, aPoints[2].y);
  3048.         }
  3049. #endif
  3050.         GpiSetAttrs(psMem, PRIM_LINE, LBB_COLOR | LBB_GEOM_WIDTH | LBB_TYPE, 0L,
  3051.                     &oldLineBundle);
  3052.         /*
  3053.          * Destroy the temporary bitmap and restore the device context.
  3054.          */
  3055.  
  3056.         GpiSetBitmap(psMem, oldBitmap);
  3057.         GpiDeleteBitmap(bitmap);
  3058.         GpiDestroyPS(psMem);
  3059.         DevCloseDC(dcMem);
  3060.         /* The bitmap must be reselected in the HPS */
  3061.         TkOS2UnsetStipple(hps, todPtr->bitmap.hps, todPtr->bitmap.handle,
  3062.                           oldPattern, &oldRefPoint);
  3063.     } else {
  3064.  
  3065.         /* Not stippled */
  3066.  
  3067.         rc = GpiQueryArcParams(hps, &oldArcParams);
  3068.         arcParams.lP = width / 2;
  3069.         arcParams.lQ = sign * (height / 2);
  3070.         arcParams.lR = 0;
  3071.         arcParams.lS = 0;
  3072.         rc = GpiSetArcParams(hps, &arcParams);
  3073. #ifdef DEBUG
  3074.         if (rc != TRUE) {
  3075.             printf("GpiSetArcParams p %d q %d (%d) ERROR %x\n", arcParams.lP,
  3076.                    arcParams.lQ, arcParams.lP * arcParams.lQ,
  3077.                    WinGetLastError(hab));
  3078.         } else {
  3079.             printf("GpiSetArcParams p %d q %d (%d) OK\n", arcParams.lP,
  3080.                    arcParams.lQ, arcParams.lP * arcParams.lQ);
  3081.         }
  3082. #endif
  3083.  
  3084.         /* Center of arc is at x+(0.5*width),y-(0.5*height) */
  3085.         center.x = x + (0.5 * width);
  3086.         center.y = y - (0.5 * height);    /* PM y coordinate reversed */
  3087.         lineBundle.lColor = gc->foreground;
  3088.         lineBundle.lGeomWidth = gc->line_width;
  3089.         lineBundle.usType = LINETYPE_SOLID;
  3090.         rc = GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR | LBB_GEOM_WIDTH | LBB_TYPE,
  3091.                          0L, &lineBundle);
  3092. #ifdef DEBUG
  3093.         if (rc != TRUE) {
  3094.             printf("GpiSetAttrs ERROR %x\n", WinGetLastError(hab));
  3095.         } else {
  3096.             printf("GpiSetAttrs OK\n");
  3097.         }
  3098. #endif
  3099.         if (!fill) {
  3100.         /* direction of arc is determined by arc parameters, while angles
  3101.          * are always positive
  3102.          * p*q > r*s -> direction counterclockwise
  3103.          * p*q < r*s -> direction clockwise
  3104.          * p*q = r*s -> straight line
  3105.          * When comparing the Remarks for function GpiSetArcParams in the
  3106.          * GPI Guide and Reference with the Xlib Programming Manual
  3107.          * (Fig.6-1), * the 3 o'clock point of the unit arc is defined by
  3108.          * (p,s) and the 12 * o'clock point by (r,q), when measuring from
  3109.          * (0,0) -> (cx+p, cy+s) and * (cx+r, cy+q) from center of arc at
  3110.          * (cx, cy). => p = 0.5 width, q = (sign*)0.5 height, r=s=0
  3111.          * GpiPartialArc draws a line from the current point to the start
  3112.          * of the partial arc, so we have to set the current point to it
  3113.          * first.
  3114.          * this is (cx+0.5*width*cos(angle1), cy+0.5*height*sin(angle1))
  3115.          */
  3116.         curPt.x = center.x + (int) (0.5 * width * a1cos);
  3117.         curPt.y = center.y + (int) (0.5 * height * a1sin);
  3118.         rc = GpiSetCurrentPosition(hps, &curPt);
  3119. #ifdef DEBUG
  3120.             if (rc != TRUE) {
  3121.                 printf("GpiSetCurrentPosition %d,%d -> %d,%d ERROR %x\n",
  3122.                        center.x, center.y, curPt.x, curPt.y,
  3123.                        WinGetLastError(hab));
  3124.             } else {
  3125.                 printf("GpiSetCurrentPosition %d,%d -> %d,%d OK\n",
  3126.                        center.x, center.y, curPt.x, curPt.y);
  3127.             }
  3128. #endif
  3129.             rc = GpiBeginPath(hps, 1);
  3130. #ifdef DEBUG
  3131.             if (rc != TRUE) {
  3132.                 printf("GpiBeginPath ERROR %x\n", WinGetLastError(hab));
  3133.             } else {
  3134.                 printf("GpiBeginPath OK\n");
  3135.             }
  3136. #endif
  3137.         rc= GpiPartialArc(hps, ¢er, MAKEFIXED(1, 0),
  3138.                           MAKEFIXED(angle1, 0), MAKEFIXED(angle2, 0));
  3139. #ifdef DEBUG
  3140.             if (rc == GPI_ERROR) {
  3141.                 printf("GpiPartialArc a1 %d, a2 %d ERROR %x\n", angle1, angle2,
  3142.                        WinGetLastError(hab));
  3143.             } else {
  3144.                 printf("GpiPartialArc a1 %d, a2 %d OK\n", angle1, angle2);
  3145.             }
  3146. #endif
  3147.             rc = GpiEndPath(hps);
  3148. #ifdef DEBUG
  3149.             if (rc != TRUE) {
  3150.                 printf("GpiEndPath ERROR %x\n", WinGetLastError(hab));
  3151.             } else {
  3152.                 printf("GpiEndPath OK\n");
  3153.             }
  3154. #endif
  3155.             rc = GpiStrokePath(hps, 1, 0);
  3156. #ifdef DEBUG
  3157.             if (rc == GPI_OK) {
  3158.                 printf("GpiStrokePath OK\n");
  3159.             } else {
  3160.                 printf("GpiStrokePath ERROR %x\n", WinGetLastError(hab));
  3161.             }
  3162. #endif
  3163.         } else {
  3164.             curPt.x = center.x + (int) (0.5 * width * a1cos);
  3165.             curPt.y = center.y + (int) (0.5 * height * a1sin);
  3166.             rc = GpiSetCurrentPosition(hps, &curPt);
  3167.         if (gc->arc_mode == ArcChord) {
  3168.                 /* Chord */
  3169.                 /*
  3170.                  * See GPI reference: first do GpiPartialArc with invisible
  3171.                  * line, then again with visible line, in an Area for filling.
  3172.                  */
  3173.             GpiSetLineType(hps, LINETYPE_INVISIBLE);
  3174.             GpiPartialArc(hps, ¢er, MAKEFIXED(1, 0),
  3175.                           MAKEFIXED(angle1, 0), MAKEFIXED(angle2, 0));
  3176.             GpiSetLineType(hps, LINETYPE_SOLID);
  3177.             rc = GpiBeginArea(hps, BA_NOBOUNDARY|BA_ALTERNATE);
  3178. #ifdef DEBUG
  3179.                     if (rc != TRUE) {
  3180.                     printf("GpiBeginArea ERROR %x\n", WinGetLastError(hab));
  3181.                 } else {
  3182.                     printf("GpiBeginArea OK\n");
  3183.                 }
  3184. #endif
  3185.             rc = GpiPartialArc(hps, ¢er, MAKEFIXED(1, 0),
  3186.                                MAKEFIXED(angle1, 0), MAKEFIXED(angle2, 0));
  3187. #ifdef DEBUG
  3188.                 if (rc == GPI_ERROR) {
  3189.                     printf("GpiPartialArc a1 %d, a2 %d ERROR %x\n", angle1,
  3190.                            angle2, WinGetLastError(hab));
  3191.                 } else {
  3192.                     printf("GpiPartialArc a1 %d, a2 %d OK\n", angle1, angle2);
  3193.                 }
  3194. #endif
  3195.             rc = GpiEndArea(hps);
  3196. #ifdef DEBUG
  3197.                 if (rc == GPI_OK) {
  3198.                     printf("GpiEndArea OK\n");
  3199.                 } else {
  3200.                     printf("GpiEndArea ERROR %x\n", WinGetLastError(hab));
  3201.                 }
  3202. #endif
  3203.         } else if ( gc->arc_mode == ArcPieSlice ) {
  3204.                 /* Pie */
  3205.             GpiSetCurrentPosition(hps, ¢er);
  3206.             GpiBeginArea(hps, BA_NOBOUNDARY|BA_ALTERNATE);
  3207.                 rc = GpiPartialArc(hps, ¢er, MAKEFIXED(1, 0),
  3208.                                    MAKEFIXED(angle1, 0), MAKEFIXED(angle2, 0));
  3209. #ifdef DEBUG
  3210.                 if (rc == GPI_ERROR) {
  3211.                     printf("GpiPartialArc a1 %d, a2 %d ERROR %x\n", angle1,
  3212.                            angle2, WinGetLastError(hab));
  3213.                 } else {
  3214.                     printf("GpiPartialArc a1 %d, a2 %d OK\n", angle1, angle2);
  3215.                 }
  3216. #endif
  3217.                 GpiLine(hps, ¢er);
  3218.             GpiEndArea(hps);
  3219.         }
  3220.         }
  3221.         GpiSetAttrs(hps, PRIM_LINE, LBB_COLOR | LBB_GEOM_WIDTH | LBB_TYPE, 0L,
  3222.                     &oldLineBundle);
  3223.     } /* not Stippled */
  3224.     GpiSetPattern(hps, oldPattern);
  3225.     GpiSetColor(hps, oldColor);
  3226.     GpiSetMix(hps, oldMix);
  3227.     rc = GpiSetArcParams(hps, &oldArcParams);
  3228.     TkOS2ReleaseDrawablePS(d, hps, &state);
  3229. }
  3230.  
  3231. /*
  3232.  *----------------------------------------------------------------------
  3233.  *
  3234.  * TkScrollWindow --
  3235.  *
  3236.  *    Scroll a rectangle of the specified window and accumulate
  3237.  *    a damage region.
  3238.  *
  3239.  * Results:
  3240.  *    Returns 0 if the scroll genereated no additional damage.
  3241.  *    Otherwise, sets the region that needs to be repainted after
  3242.  *    scrolling and returns 1.
  3243.  *
  3244.  * Side effects:
  3245.  *    Scrolls the bits in the window.
  3246.  *
  3247.  *----------------------------------------------------------------------
  3248.  */
  3249.  
  3250. int
  3251. TkScrollWindow(tkwin, gc, x, y, width, height, dx, dy, damageRgn)
  3252.     Tk_Window tkwin;        /* The window to be scrolled. */
  3253.     GC gc;            /* GC for window to be scrolled. */
  3254.     int x, y, width, height;    /* Position rectangle to be scrolled. */
  3255.     int dx, dy;            /* Distance rectangle should be moved. */
  3256.     TkRegion damageRgn;        /* Region to accumulate damage in. */
  3257. {
  3258.     HWND hwnd = TkOS2GetHWND(Tk_WindowId(tkwin));
  3259.     RECTL scrollRect;
  3260.     LONG lReturn;
  3261.     LONG windowHeight;
  3262.  
  3263. #ifdef DEBUG
  3264.     printf("TkScrollWindow\n");
  3265. #endif
  3266.  
  3267.     windowHeight = TkOS2WindowHeight((TkOS2Drawable *)Tk_WindowId(tkwin));
  3268.  
  3269.     /* Translate the Y coordinates to PM coordinates */
  3270.     y = windowHeight - y;
  3271.     dy = -dy;
  3272.     scrollRect.xLeft = x;
  3273.     scrollRect.yTop = y;
  3274.     scrollRect.xRight = x + width;
  3275.     scrollRect.yBottom = y - height;    /* PM coordinate reversed */
  3276.     /* Hide cursor, just in case */
  3277.     WinShowCursor(hwnd, FALSE);
  3278.     lReturn = WinScrollWindow(hwnd, dx, dy, &scrollRect, NULL, (HRGN) damageRgn,
  3279.                               NULL, 0);
  3280.     /* Show cursor again */
  3281.     WinShowCursor(hwnd, TRUE);
  3282.     return ( lReturn == RGN_NULL ? 0 : 1);
  3283. }
  3284.  
  3285. /*
  3286.  *----------------------------------------------------------------------
  3287.  *
  3288.  * TkOS2SetStipple --
  3289.  *
  3290.  *    Set the pattern set of a HPS to a "stipple" (bitmap).
  3291.  *
  3292.  * Results:
  3293.  *    Returns the old pattern set and reference point.
  3294.  *
  3295.  * Side effects:
  3296.  *    Unsets the bitmap in/from "its" HPS, appoints a bitmap ID to it,
  3297.  *    sets that ID as the pattern set, with its reference point as given.
  3298.  *
  3299.  *----------------------------------------------------------------------
  3300.  */
  3301.  
  3302. void
  3303. TkOS2SetStipple(destPS, bmpPS, stipple, x, y, oldPatternSet, oldRefPoint)
  3304.     HPS destPS;        /* The HPS to receive the stipple. */
  3305.     HPS bmpPS;        /* The HPS of the stipple-bitmap. */
  3306.     HBITMAP stipple;    /* Stipple-bitmap. */
  3307.     LONG x, y;            /* Reference point for the stipple. */
  3308.     LONG *oldPatternSet;    /* Pattern set that was in effect in the HPS. */
  3309.     PPOINTL oldRefPoint;    /* Reference point that was in effect. */
  3310. {
  3311.     POINTL refPoint;
  3312.  
  3313. #ifdef DEBUG
  3314.     printf("TkOS2SetStipple destPS %x, bmpPS %x, stipple %x, (%d,%d)\n", destPS,
  3315.            bmpPS, stipple, x, y);
  3316. #endif
  3317.     refPoint.x = x;
  3318.     refPoint.y = y;
  3319.     rc = GpiQueryPatternRefPoint(destPS, oldRefPoint);
  3320. #ifdef DEBUG
  3321.     if (rc!=TRUE) {
  3322.         printf("    GpiQueryPatternRefPoint ERROR %x\n", WinGetLastError(hab));
  3323.     } else  {
  3324.         printf("    GpiQueryPatternRefPoint OK: %d,%d\n", oldRefPoint->x,
  3325.                oldRefPoint->y);
  3326.     }
  3327. #endif
  3328.     rc = GpiSetPatternRefPoint(destPS, &refPoint);
  3329. #ifdef DEBUG
  3330.     if (rc!=TRUE) {
  3331.         printf("    GpiSetPatternRefPoint ERROR %x\n", WinGetLastError(hab));
  3332.     } else {
  3333.         printf("    GpiSetPatternRefPoint %d,%d OK\n", refPoint.x, refPoint.y);
  3334.     }
  3335. #endif
  3336.     *oldPatternSet = GpiQueryPatternSet(destPS);
  3337. #ifdef DEBUG
  3338.     if (rc==LCID_ERROR) {
  3339.         printf("    GpiQueryPatternSet ERROR %x\n", WinGetLastError(hab));
  3340.     } else {
  3341.         printf("    GpiQueryPatternSet %x\n", oldPatternSet);
  3342.     }
  3343. #endif
  3344.     GpiSetBitmap(bmpPS, NULLHANDLE);
  3345.     rc = GpiSetBitmapId(destPS, stipple, 254L);
  3346. #ifdef DEBUG
  3347.     if (rc!=TRUE) {
  3348.         printf("    GpiSetBitmapId %x ERROR %x\n", stipple,
  3349.                WinGetLastError(hab));
  3350.     } else {
  3351.         printf("    GpiSetBitmapId %x OK\n", stipple);
  3352.     }
  3353. #endif
  3354.     rc = GpiSetPatternSet(destPS, 254L);
  3355. #ifdef DEBUG
  3356.     if (rc!=TRUE) {
  3357.         printf("    GpiSetPatternSet ERROR %x\n", WinGetLastError(hab));
  3358.     } else {
  3359.         printf("    GpiSetPatternSet OK\n");
  3360.     }
  3361. #endif
  3362. }
  3363.  
  3364. /*
  3365.  *----------------------------------------------------------------------
  3366.  *
  3367.  * TkOS2UnsetStipple --
  3368.  *
  3369.  *    Unset the "stipple" (bitmap) from a HPS.
  3370.  *
  3371.  * Results:
  3372.  *    None.
  3373.  *
  3374.  * Side effects:
  3375.  *    Resets the pattern set and refpoint of the hps to their original
  3376.  *    (given) values and reassociates the bitmap with its "own" HPS.
  3377.  *
  3378.  *----------------------------------------------------------------------
  3379.  */
  3380.  
  3381. void
  3382. TkOS2UnsetStipple(destPS, bmpPS, stipple, oldPatternSet, oldRefPoint)
  3383.     HPS destPS;        /* The HPS to give up the stipple. */
  3384.     HPS bmpPS;        /* The HPS of the stipple-bitmap. */
  3385.     HBITMAP stipple;    /* Stipple-bitmap. */
  3386.     LONG oldPatternSet;        /* Pattern set to be put back in effect. */
  3387.     PPOINTL oldRefPoint;    /* Reference point to put back in effect. */
  3388. {
  3389. #ifdef DEBUG
  3390.     printf("TkOS2UnsetStipple destPS %x, bmpPS %x, stipple %x, oldRP %d,%d\n",
  3391.            destPS, bmpPS, stipple, oldRefPoint->x, oldRefPoint->y);
  3392. #endif
  3393.     rc = GpiSetPatternSet(destPS, oldPatternSet);
  3394.     rc = GpiSetPatternRefPoint(destPS, oldRefPoint);
  3395.  
  3396.     rc = GpiDeleteSetId(destPS, 254L);
  3397.     /* end of using 254 */
  3398.     /* The bitmap must be reselected in the HPS */
  3399.     GpiSetBitmap(bmpPS, stipple);
  3400. }
  3401.