diff lib/xwstr.c @ 0:92745d501b9a

initial import from kinput2-v3.1
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Mon, 08 Mar 2010 04:44:30 +0900
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/xwstr.c	Mon Mar 08 04:44:30 2010 +0900
@@ -0,0 +1,500 @@
+/*
+ *	xwstr.c
+ */
+
+/*
+ * Copyright (c) 1989  Software Research Associates, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Software Research Associates not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  Software Research
+ * Associates makes no representations about the suitability of this software
+ * for any purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * Author:  Makoto Ishisone, Software Research Associates, Inc., Japan
+ *		ishisone@sra.co.jp
+ */
+
+/*
+ * wide character string $B$rMQ$$$F%F%-%9%H$rI=<($9$k$?$a$N%i%$%V%i%j(B
+ *
+ * wide character $B$NFCD9$r@8$+$7!":GBgF1;~$K(B 4 $B<oN`$N%U%)%s%H$r(B
+ * $B07$&$3$H$,$G$-$k!#(B
+ *
+ *	GSet	bit $BI=8=(B		UJIS $B$G$N3d$jEv$F(B
+ *	----------------------------------------------
+ *	G0	0xxxxxxx0xxxxxxx	ASCII
+ *	G1	1xxxxxxx1xxxxxxx	$B4A;z(B
+ *	G2	0xxxxxxx1xxxxxxx	$BH>3Q$+$J(B
+ *	G3	1xxxxxxx0xxxxxxx	$B30;z(B
+ *
+ * XWSGC XWSSetGCSet(GC gc0, GC gc1, GC gc2, GC gc3)
+ *	$B;XDj$5$l$?(B 4$B$D$N(B GC $B$rAH$_9g$o$;$F(B XWSGC $B$r:n$k!#(B
+ *	G0, G1, G2, G3 $B$NJ8;z$KBP$7$F$=$l$>$l(B gc0, gc1, gc2, gc3 $B$,(B
+ *	$B;H$o$l$k!#0z?t(B gc? $B$K$O(B NULL $B$r;XDj$7$F$b$h$$!#$=$N>l9g$K$O(B
+ *	$BBP1~$9$k%-%c%i%/%?%;%C%H$NJ8;z$O=q$+$l$J$$!#(B
+ *	$B$J$*(B Xt $B$NCf$G;HMQ$9$k;~$K$O!"(Bxtwstr.c $B$NCf$N(B XtWSGetGCSet()
+ *	$B$r;H$&J}$,$h$$$@$m$&!#(B
+ *
+ * void XWSSetMapping(XWSGC gcset, int g0map, int g1map, int g2map, int g3map)
+ *	G0, G1, G2, G3 $B$NJ8;z$rIA2h$9$k;~$K%U%)%s%H$N(B GL / GR $B$N$I$A$i$r(B
+ *	$B;HMQ$9$k$+$r@_Dj$9$k!#(B0 $B$r;XDj$9$k$H(B GL $B$,;HMQ$5$l!"(B1 $B$r;XDj$9$k$H(B
+ *	GR $B$,;HMQ$5$l$k!#(B-1 $B$,;XDj$5$l$?>l9g$K$OA0$N@_Dj$,$=$N$^$^;H$o$l$k!#(B
+ *	$B%G%U%)%k%H$N@_Dj(B ($B$D$^$j(B XWSSetGCSet() $B$^$?$O(B XtWSGetGCSet() $B$G(B
+ *	gcset $B$,:n$i$l$?;~(B) $B$O$9$Y$F(B GL $B$r;HMQ$9$k$h$&$K$J$C$F$$$k!#(B
+ *
+ * int XWSDrawString(Display *d, Drawable w, XWSGC gcset,
+ *		      int x, int y, wchar *wstr, int len)
+ * int XWSDrawImageString(Display *d, Drawable w, XWSGC gcset,
+ *		   int x, int y, wchar *wstr, int len)
+ *	$B$=$l$>$l!"(BXlib $B$N(B XDrawString() / XDrawImageString() $B$K(B
+ *	$BBP1~$9$k4X?t!#;XDj$5$l$?0LCV$K;XDj$5$l$?(B GC $B%;%C%H$rMQ$$$F(B
+ *	$B%F%-%9%H$r=q$/!#0z?t(B len $B$OJ8;zNs(B wstr $B$NJ8;z?t$G$"$k!#(B
+ *	$B%P%$%H?t$G$O$J$$$3$H$KCm0U!#(B
+ *	$B$J$*!"(BXDrawString() $B$J$I$H$O0[$J$j!"%j%?!<%s%P%j%e!<$H$7$F(B
+ *	$B=q$$$?J8;z$NI}$rJV$9!#(B
+ *
+ * int XWSTextWidth(XWSGC gcset, wchar *wstr, int len)
+ * void XWSTextExtents(XWSGC gcset, wchar *wstr, int len,
+ *			int *ascent, int *descent, XCharStruct *overall)
+ *	$B$=$l$>$l!"(BXlib $B$N(B XTextWidth() / XTextExtents() $B$KBP1~$9$k(B
+ *	$B4X?t!#;XDj$5$l$?J8;zNs$NI}!&Bg$-$5$rJV$9!#(B
+ *
+ * void XWSFontHeight(XWSGC gcset, wchar *wstr, int len,
+ *			int *ascent, int *descent)
+ *	$B0z?t(B wstr $B$G;XDj$5$l$?J8;z$KBP1~$9$k%U%)%s%H$N(B ascent/descent $B$N(B
+ *	$B:GBgCM$rJV$9!#(Bwstr $B$K(B NULL $B$r;XDj$9$k$H!"(BXWSGC $B$K%;%C%H$5$l$?(B
+ *	$B$9$Y$F$N%U%)%s%H$N(B ascent/descent $B$N:GBgCM$rJV$9!#(B
+ */
+
+#ifndef lint
+static char	*rcsid = "$Id: xwstr.c,v 2.9 1999/01/07 03:13:03 ishisone Exp $";
+#endif
+
+#include <X11/Xlib.h>
+#if defined(XlibSpecificationRelease) && XlibSpecificationRelease > 4
+#include <X11/Xfuncs.h>
+#endif
+#include "WStr.h"
+#include "XWStr.h"
+
+#ifdef __STDC__
+#include <stdlib.h>
+#else
+extern char *malloc();
+#endif
+
+#define G0MASK	0x0000
+#define G1MASK	0x8080
+#define G2MASK	0x0080
+#define G3MASK	0x8000
+
+#define IS2B(f)	(((f)->max_byte1 > 0) || ((f)->max_char_or_byte2 > 255))
+#define MIN(a, b)	((a) > (b) ? (b) : (a))
+#define MAX(a, b)	((a) > (b) ? (a) : (b))
+
+#ifndef NULL
+#define NULL	0
+#endif
+
+#define bufsize	256
+
+#ifdef __STDC__
+/* static function prototype */
+static int flushstr(Display *, Drawable,  FontEnt *, int, int,
+		    XChar2b *, XChar2b *, int);
+static int wsdrawstring(Display *, Drawable, XWSGC, int, int,
+			wchar *, int, int);
+#else
+static int flushstr();
+static int wsdrawstring();
+#endif
+
+XWSGC
+XWSSetGCSet(dpy, gc0, gc1, gc2, gc3)
+Display *dpy;
+GC gc0;
+GC gc1;
+GC gc2;
+GC gc3;
+{
+	XWSGC	gcset;
+	int	i;
+
+	gcset = (XWSGC)malloc(sizeof(XWSGCSet));
+	if (gcset == NULL)
+		return (XWSGC)NULL;
+
+	gcset->fe[0].gc = gc0;
+	gcset->fe[1].gc = gc1;
+	gcset->fe[2].gc = gc2;
+	gcset->fe[3].gc = gc3;
+
+	for (i = 0; i < 4; i++) {
+		if (gcset->fe[i].gc == NULL) {
+			gcset->fe[i].font = NULL;
+		} else {
+			XFontStruct	*font;
+			gcset->fe[i].font = font = XQueryFont(dpy, XGContextFromGC(gcset->fe[i].gc));
+			gcset->fe[i].flag = FONTQUERY;
+			if (IS2B(font))
+				gcset->fe[i].flag = TWOB;
+		}
+	}
+
+	return gcset;
+}
+
+void
+XWSSetMapping(gcset, g0map, g1map, g2map, g3map)
+XWSGC gcset;
+int g0map;
+int g1map;
+int g2map;
+int g3map;
+{
+	int	map[4];
+	int	i;
+
+	map[0] = g0map; map[1] = g1map; map[2] = g2map; map[3] = g3map;
+	for (i = 0; i < 4; i++) {
+		if (map[i] < 0)
+			continue;
+		else if (map[i] == 0)
+			gcset->fe[i].flag &= ~GRMAPPING;
+		else
+			gcset->fe[i].flag |= GRMAPPING;
+	}
+}
+
+int
+XWSDrawString(d, w, gcset, x, y, wstr, len)
+Display *d;
+Drawable w;
+XWSGC gcset;
+int x;
+int y;
+wchar *wstr;
+int len;
+{
+	return wsdrawstring(d, w, gcset, x, y, wstr, len, 0);
+}
+
+int
+XWSDrawImageString(d, w, gcset, x, y, wstr, len)
+Display *d;
+Drawable w;
+XWSGC gcset;
+int x;
+int y;
+wchar *wstr;
+int len;
+{
+	return wsdrawstring(d, w, gcset, x, y, wstr, len, 1);
+}
+
+void
+XWSFontHeight(gcset, wstr, len, ascent, descent)
+XWSGC gcset;
+wchar *wstr;
+int len;
+int *ascent;
+int *descent;
+{
+	FontEnt	*fep = &(gcset->fe[0]);
+	int	i;
+	int	asc = 0;
+	int	dsc = 0;
+
+	if (wstr) {
+		while (len-- > 0) {
+			i = GSET(*wstr++);
+			if (fep[i].font) {
+				if ((fep[i].font)->ascent > asc)
+					asc = (fep[i].font)->ascent;
+				if ((fep[i].font)->descent > dsc)
+					dsc = (fep[i].font)->descent;
+			}
+		}
+	} else {
+		for (i = 0; i < 4; i++) {
+			if (fep[i].font) {
+				if ((fep[i].font)->ascent > asc)
+					asc = (fep[i].font)->ascent;
+				if ((fep[i].font)->descent > dsc)
+					dsc = (fep[i].font)->descent;
+			}
+		}
+	}
+	*ascent = asc;
+	*descent = dsc;
+}
+
+int
+XWSTextWidth(gcset, wstr, len)
+XWSGC gcset;
+wchar *wstr;
+int len;
+{
+	XChar2b			buf[bufsize];
+	XChar2b			*cp;
+	wchar			*wstr1 = wstr + len;
+	XChar2b			*cpend = buf + bufsize;
+	int			c;
+	int			width = 0;
+	int			gmask, gset;
+	FontEnt			*fe;
+	int			is2b;
+	int			grmap;
+
+	while (wstr < wstr1) {
+		gmask = *wstr & 0x8080;
+
+		switch (gmask) {
+		case G0MASK:
+			gset = 0;
+			break;
+		case G1MASK:
+			gset = 1;
+			break;
+		case G2MASK:
+			gset = 2;
+			break;
+		case G3MASK:
+			gset = 3;
+			break;
+		}
+
+		fe = &gcset->fe[gset];
+		is2b = fe->flag & TWOB;
+		grmap = (fe->flag & GRMAPPING) ? 0x80 : 0;
+		cp = buf;
+
+		if (fe->font == NULL) {
+			while (wstr < wstr1 && (*wstr & 0x8080) == gmask)
+				wstr++;
+			continue;
+		}
+
+		while (wstr < wstr1 && ((c = *wstr) & 0x8080) == gmask) {
+			if (cp >= cpend - 1) {
+				/* flush */
+				width += XTextWidth16(fe->font, buf, cp - buf);
+				cp = buf;
+			}
+			if (is2b)
+				cp->byte1 = ((c >> 8) & 0x7f) | grmap;
+			else
+				cp->byte1 = 0;
+			cp->byte2 = (c & 0x7f) | grmap;
+			cp++;
+			wstr++;
+		}
+
+		if (cp == buf)
+			continue;
+
+		/* flush */
+		width += XTextWidth16(fe->font, buf, cp - buf);
+	}
+
+	return width;
+}
+
+void
+XWSTextExtents(gcset, wstr, len, ascent, descent, overall)
+XWSGC gcset;
+wchar *wstr;
+int len;
+int *ascent;
+int *descent;
+XCharStruct *overall;
+{
+	XChar2b			buf[bufsize];
+	XChar2b			*cp;
+	wchar			*wstr1 = wstr + len;
+	XChar2b			*cpend = buf + bufsize;
+	int			c;
+	int			gmask, gset;
+	FontEnt			*fe;
+	int			is2b;
+	int			grmap;
+	int			dir, as, ds;
+	XCharStruct		oa;
+
+	*ascent = *descent = 0;
+	(void)bzero(overall, sizeof(XCharStruct));
+
+	while (wstr < wstr1) {
+		gmask = *wstr & 0x8080;
+
+		switch (gmask) {
+		case G0MASK:
+			gset = 0;
+			break;
+		case G1MASK:
+			gset = 1;
+			break;
+		case G2MASK:
+			gset = 2;
+			break;
+		case G3MASK:
+			gset = 3;
+			break;
+		}
+
+		fe = &gcset->fe[gset];
+		is2b = fe->flag & TWOB;
+		grmap = (fe->flag & GRMAPPING) ? 0x80 : 0;
+		cp = buf;
+
+		if (fe->font == NULL) {
+			while (wstr < wstr1 && (*wstr & 0x8080) == gmask)
+				wstr++;
+			continue;
+		}
+
+		while (wstr < wstr1 && ((c = *wstr) & 0x8080) == gmask) {
+			if (cp >= cpend - 1) {
+				/* flush */
+				XTextExtents16(fe->font, buf, cp - buf,
+					       &dir, &as, &ds, &oa);
+				cp = buf;
+				*ascent = MAX(*ascent, as);
+				*descent = MAX(*descent, ds);
+				overall->lbearing = MIN(overall->lbearing,
+							overall->width + oa.lbearing);
+				overall->rbearing = MAX(overall->rbearing,
+							overall->width + oa.rbearing);
+				overall->width += oa.width;
+				overall->ascent = MAX(overall->ascent, oa.ascent);
+				overall->descent = MAX(overall->descent, oa.descent);
+			}
+			if (is2b)
+				cp->byte1 = ((c >> 8) & 0x7f) | grmap;
+			else
+				cp->byte1 = 0;
+			cp->byte2 = (c & 0x7f) | grmap;
+			cp++;
+			wstr++;
+		}
+
+		if (cp == buf)
+			continue;
+
+		/* flush */
+		XTextExtents16(fe->font, buf, cp - buf, &dir, &as, &ds, &oa);
+		*ascent = MAX(*ascent, as);
+		*descent = MAX(*descent, ds);
+		overall->lbearing = MIN(overall->lbearing,
+					overall->width + oa.lbearing);
+		overall->rbearing = MAX(overall->rbearing,
+					overall->width + oa.rbearing);
+		overall->width += oa.width;
+		overall->ascent = MAX(overall->ascent, oa.ascent);
+		overall->descent = MAX(overall->descent, oa.descent);
+	}
+}
+
+
+/*
+ * private functions
+ */
+
+static int
+wsdrawstring(d, w, gcset, x, y, wstr, len, image)
+Display *d;
+Drawable w;
+XWSGC gcset;
+int x;
+int y;
+wchar *wstr;
+int len;
+int image;
+{
+	XChar2b			buf[bufsize];
+	XChar2b			*cp;
+	wchar			*wstr1 = wstr + len;
+	XChar2b			*cpend = buf + bufsize;
+	int			c;
+	int			sx = x;
+	int			gmask, gset;
+	FontEnt			*fe;
+	int			is2b;
+	int			grmap;
+
+	while (wstr < wstr1) {
+		gmask = *wstr & 0x8080;
+
+		switch (gmask) {
+		case G0MASK:
+			gset = 0;
+			break;
+		case G1MASK:
+			gset = 1;
+			break;
+		case G2MASK:
+			gset = 2;
+			break;
+		case G3MASK:
+			gset = 3;
+			break;
+		}
+
+		fe = &gcset->fe[gset];
+		is2b = fe->flag & TWOB;
+		grmap = (fe->flag & GRMAPPING) ? 0x80 : 0;
+		cp = buf;
+
+		if (fe->gc == NULL) {
+			while (wstr < wstr1 && (*wstr & 0x8080) == gmask)
+				wstr++;
+			continue;
+		}
+		while (wstr < wstr1 && ((c = *wstr) & 0x8080) == gmask) {
+			if (cp >= cpend - 1) {
+				/* flush */
+				x += flushstr(d, w, fe, x, y, buf, cp, image);
+				cp = buf;
+			}
+			if (is2b)
+				cp->byte1 = ((c >> 8) & 0x7f) | grmap;
+			else
+				cp->byte1 = 0;
+			cp->byte2 = (c & 0x7f) | grmap;
+			cp++;
+			wstr++;
+		}
+		/* flush */
+		x += flushstr(d, w, fe, x, y, buf, cp, image);
+		cp = buf;
+	}
+
+	return x - sx;
+}
+
+static int
+flushstr(d, w, fe, x, y, cp0, cp1, image)
+Display *d;
+Drawable w;
+FontEnt *fe;
+int x;
+int y;
+XChar2b *cp0;
+XChar2b *cp1;
+int image;
+{
+	if (cp0 >= cp1 || fe->gc == NULL)
+		return 0;
+
+	if (image)
+		XDrawImageString16(d, w, fe->gc, x, y, cp0, cp1 - cp0);
+	else
+		XDrawString16(d, w, fe->gc, x, y, cp0, cp1 - cp0);
+	return XTextWidth16(fe->font, cp0, cp1 - cp0);
+}