From: n.winton@axion.bt.co.uk (Neil Winton)
Newsgroups: comp.lang.tcl
Subject: Re: Font problem in tk2.2 ? (Workaround)
Keywords: tk2.2, font
Date: 19 Aug 92 15:49:53 GMT
Organization: BT Laboratories

In article <1992Aug14.133705.22017@rchland.ibm.com>, shmdgljd@rchland.vnet.ibm.com (Jay Schmidgall) writes:
|> In article <16e5u6INN4ge@agate.berkeley.edu>, ouster@sprite.Berkeley.EDU (John Ousterhout) writes:
|> |> redisplays, so this is a serious problem.  Is there anyone out there with
|> |> contacts at IBM that can see if there's a server patch to fix the problem?
|> 
|> I'm following up on this w/IBM Software Service.  I've just got the ball
|> rolling so I don't know if this problem has been reported and/or any fix.
|> Let you know what happens...
|> 
|> -- 
|> : jay          jay@vnet.ibm.com    My opinions and ideas, not my employer's.
|> : shmdgljd@rchland.vnet.ibm.com    (c) Copyright 1992.  All rights reserved.

Thanks to John for investigating and isolating this problem and Jay for raising
this with the `appropriate authoritioes'.  Meanwhile I have developed a
work-around for any other would-be Tk-on-AIX users.  You should recompile Tk with
a -DXDrawString=AIXDrawString and link in the object module from the source
below.  It's as simple as that.  Or at least, it was for me ...

	Regards,

		Neil

*   Neil Winton			306, SSFT, BT Labs, Martlesham Heath    *
*   nwinton@axion.bt.co.uk	IPSWICH IP5, 7RE   (Tel +44 473 646079) *
*   The works of the Lord are great, sought out of all them that have   *
*   pleasure therein.					Psalm 111 v 2   *
*       (Found at the entrance to the Cavendish Labs, Cambridge.)       *

------ Cut Here for AIXDrawString.c
/*
**  Replacement for XDrawString() for AIX.
**
**  This works around a bug in the AIX3.1 and 3.2 X servers which causes
**  text written to an off-screen pixmap to be mangled (each character
**  truncated to 8 pixels wide).  Substitute this for XDrawString with
**  a suitable macro.
**
**  WARNING: This is neither pretty nor efficient.  Its sole purpose
**  is to make Tk useable.  In particular it will fail miserably if
**  used in a program managing multiple displays.  Use at your own
**  risk.  (That said, it works for me and my RS/6000 320H, AIX 3.2 :-)
**
**  Neil Winton (N.Winton@axion.bt.co.uk)
*/

#include <X11/Xlib.h>

void
AIXDrawString(Display *display, Drawable d, GC gc, int x, int y,
	      char *string, int length)
{
    Window root;
    int x_pos, y_pos;
    unsigned int width, height;
    unsigned int border;
    unsigned int depth;
    static Pixmap bm = None;
    static unsigned int bm_w = 0, bm_h = 0;
    static GC bm_gc = (GC) NULL;
    static GC tmpgc = (GC) NULL;
    XGCValues gcv;
    XID fid;
    static XID last_fid = None;
    static int direction, ascent, descent;
    static XCharStruct info;


    if (XGetGeometry(display, d, &root, &x_pos, &y_pos,
		     &width, &height, &border, &depth) != True)
    {
	return;
    }

    if (width > bm_w || height > bm_h)
    {
	if (bm != None)
	{
	    XFreePixmap(display, bm);
	    XFreeGC(display, bm_gc);
	}
	bm = XCreatePixmap(display, d, width, height, 1);
	bm_w = width;
	bm_h = height;
	gcv.function = GXcopy;
	gcv.foreground = 1;
	gcv.background = 0;
	bm_gc = XCreateGC(display, bm, (GCForeground | GCBackground | GCFunction), &gcv); 
    }

    XGetGCValues(display, gc, GCFont, &gcv);
    fid = gcv.font;
    gcv.foreground = 0;
    XChangeGC(display, bm_gc, (GCFont | GCForeground), &gcv);
    XFillRectangle(display, bm, bm_gc, 0, 0, bm_w, bm_h);
    XSetForeground(display, bm_gc, 1);

    XDrawString(display, bm, bm_gc, x, y, string, length);

    if (fid != last_fid)
    {
	XQueryTextExtents(display, fid, string, length, &direction, &ascent,
			  &descent, &info);
    }

    if (tmpgc == (GC) NULL)
    {
	tmpgc = XCreateGC(display, d, 0, &gcv);
    }
    XCopyGC(display, gc, (GCFunction | GCPlaneMask | GCForeground |
			  GCBackground | GCLineWidth | GCLineStyle |
			  GCCapStyle | GCJoinStyle | GCFillStyle |
			  GCFillRule | GCTile | GCStipple |
			  GCTileStipXOrigin | GCTileStipYOrigin |
			  GCFont | GCSubwindowMode | GCGraphicsExposures |
			  GCClipXOrigin | GCClipYOrigin | GCClipMask |
			  GCDashOffset | GCDashList | GCArcMode), tmpgc);
    gcv.clip_mask = bm;
    XChangeGC(display, tmpgc, GCClipMask, &gcv);
    XFillRectangle(display, d, tmpgc, x + info.lbearing,
		   y - ascent,
		   info.rbearing,
		   ascent + descent);

    return;
}