comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:92745d501b9a
1 /*
2 * xwstr.c
3 */
4
5 /*
6 * Copyright (c) 1989 Software Research Associates, Inc.
7 *
8 * Permission to use, copy, modify, and distribute this software and its
9 * documentation for any purpose and without fee is hereby granted, provided
10 * that the above copyright notice appear in all copies and that both that
11 * copyright notice and this permission notice appear in supporting
12 * documentation, and that the name of Software Research Associates not be
13 * used in advertising or publicity pertaining to distribution of the
14 * software without specific, written prior permission. Software Research
15 * Associates makes no representations about the suitability of this software
16 * for any purpose. It is provided "as is" without express or implied
17 * warranty.
18 *
19 * Author: Makoto Ishisone, Software Research Associates, Inc., Japan
20 * ishisone@sra.co.jp
21 */
22
23 /*
24 * wide character string $B$rMQ$$$F%F%-%9%H$rI=<($9$k$?$a$N%i%$%V%i%j(B
25 *
26 * wide character $B$NFCD9$r@8$+$7!":GBgF1;~$K(B 4 $B<oN`$N%U%)%s%H$r(B
27 * $B07$&$3$H$,$G$-$k!#(B
28 *
29 * GSet bit $BI=8=(B UJIS $B$G$N3d$jEv$F(B
30 * ----------------------------------------------
31 * G0 0xxxxxxx0xxxxxxx ASCII
32 * G1 1xxxxxxx1xxxxxxx $B4A;z(B
33 * G2 0xxxxxxx1xxxxxxx $BH>3Q$+$J(B
34 * G3 1xxxxxxx0xxxxxxx $B30;z(B
35 *
36 * XWSGC XWSSetGCSet(GC gc0, GC gc1, GC gc2, GC gc3)
37 * $B;XDj$5$l$?(B 4$B$D$N(B GC $B$rAH$_9g$o$;$F(B XWSGC $B$r:n$k!#(B
38 * G0, G1, G2, G3 $B$NJ8;z$KBP$7$F$=$l$>$l(B gc0, gc1, gc2, gc3 $B$,(B
39 * $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
40 * $BBP1~$9$k%-%c%i%/%?%;%C%H$NJ8;z$O=q$+$l$J$$!#(B
41 * $B$J$*(B Xt $B$NCf$G;HMQ$9$k;~$K$O!"(Bxtwstr.c $B$NCf$N(B XtWSGetGCSet()
42 * $B$r;H$&J}$,$h$$$@$m$&!#(B
43 *
44 * void XWSSetMapping(XWSGC gcset, int g0map, int g1map, int g2map, int g3map)
45 * 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
46 * $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
47 * GR $B$,;HMQ$5$l$k!#(B-1 $B$,;XDj$5$l$?>l9g$K$OA0$N@_Dj$,$=$N$^$^;H$o$l$k!#(B
48 * $B%G%U%)%k%H$N@_Dj(B ($B$D$^$j(B XWSSetGCSet() $B$^$?$O(B XtWSGetGCSet() $B$G(B
49 * 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
50 *
51 * int XWSDrawString(Display *d, Drawable w, XWSGC gcset,
52 * int x, int y, wchar *wstr, int len)
53 * int XWSDrawImageString(Display *d, Drawable w, XWSGC gcset,
54 * int x, int y, wchar *wstr, int len)
55 * $B$=$l$>$l!"(BXlib $B$N(B XDrawString() / XDrawImageString() $B$K(B
56 * $BBP1~$9$k4X?t!#;XDj$5$l$?0LCV$K;XDj$5$l$?(B GC $B%;%C%H$rMQ$$$F(B
57 * $B%F%-%9%H$r=q$/!#0z?t(B len $B$OJ8;zNs(B wstr $B$NJ8;z?t$G$"$k!#(B
58 * $B%P%$%H?t$G$O$J$$$3$H$KCm0U!#(B
59 * $B$J$*!"(BXDrawString() $B$J$I$H$O0[$J$j!"%j%?!<%s%P%j%e!<$H$7$F(B
60 * $B=q$$$?J8;z$NI}$rJV$9!#(B
61 *
62 * int XWSTextWidth(XWSGC gcset, wchar *wstr, int len)
63 * void XWSTextExtents(XWSGC gcset, wchar *wstr, int len,
64 * int *ascent, int *descent, XCharStruct *overall)
65 * $B$=$l$>$l!"(BXlib $B$N(B XTextWidth() / XTextExtents() $B$KBP1~$9$k(B
66 * $B4X?t!#;XDj$5$l$?J8;zNs$NI}!&Bg$-$5$rJV$9!#(B
67 *
68 * void XWSFontHeight(XWSGC gcset, wchar *wstr, int len,
69 * int *ascent, int *descent)
70 * $B0z?t(B wstr $B$G;XDj$5$l$?J8;z$KBP1~$9$k%U%)%s%H$N(B ascent/descent $B$N(B
71 * $B:GBgCM$rJV$9!#(Bwstr $B$K(B NULL $B$r;XDj$9$k$H!"(BXWSGC $B$K%;%C%H$5$l$?(B
72 * $B$9$Y$F$N%U%)%s%H$N(B ascent/descent $B$N:GBgCM$rJV$9!#(B
73 */
74
75 #ifndef lint
76 static char *rcsid = "$Id: xwstr.c,v 2.9 1999/01/07 03:13:03 ishisone Exp $";
77 #endif
78
79 #include <X11/Xlib.h>
80 #if defined(XlibSpecificationRelease) && XlibSpecificationRelease > 4
81 #include <X11/Xfuncs.h>
82 #endif
83 #include "WStr.h"
84 #include "XWStr.h"
85
86 #ifdef __STDC__
87 #include <stdlib.h>
88 #else
89 extern char *malloc();
90 #endif
91
92 #define G0MASK 0x0000
93 #define G1MASK 0x8080
94 #define G2MASK 0x0080
95 #define G3MASK 0x8000
96
97 #define IS2B(f) (((f)->max_byte1 > 0) || ((f)->max_char_or_byte2 > 255))
98 #define MIN(a, b) ((a) > (b) ? (b) : (a))
99 #define MAX(a, b) ((a) > (b) ? (a) : (b))
100
101 #ifndef NULL
102 #define NULL 0
103 #endif
104
105 #define bufsize 256
106
107 #ifdef __STDC__
108 /* static function prototype */
109 static int flushstr(Display *, Drawable, FontEnt *, int, int,
110 XChar2b *, XChar2b *, int);
111 static int wsdrawstring(Display *, Drawable, XWSGC, int, int,
112 wchar *, int, int);
113 #else
114 static int flushstr();
115 static int wsdrawstring();
116 #endif
117
118 XWSGC
119 XWSSetGCSet(dpy, gc0, gc1, gc2, gc3)
120 Display *dpy;
121 GC gc0;
122 GC gc1;
123 GC gc2;
124 GC gc3;
125 {
126 XWSGC gcset;
127 int i;
128
129 gcset = (XWSGC)malloc(sizeof(XWSGCSet));
130 if (gcset == NULL)
131 return (XWSGC)NULL;
132
133 gcset->fe[0].gc = gc0;
134 gcset->fe[1].gc = gc1;
135 gcset->fe[2].gc = gc2;
136 gcset->fe[3].gc = gc3;
137
138 for (i = 0; i < 4; i++) {
139 if (gcset->fe[i].gc == NULL) {
140 gcset->fe[i].font = NULL;
141 } else {
142 XFontStruct *font;
143 gcset->fe[i].font = font = XQueryFont(dpy, XGContextFromGC(gcset->fe[i].gc));
144 gcset->fe[i].flag = FONTQUERY;
145 if (IS2B(font))
146 gcset->fe[i].flag = TWOB;
147 }
148 }
149
150 return gcset;
151 }
152
153 void
154 XWSSetMapping(gcset, g0map, g1map, g2map, g3map)
155 XWSGC gcset;
156 int g0map;
157 int g1map;
158 int g2map;
159 int g3map;
160 {
161 int map[4];
162 int i;
163
164 map[0] = g0map; map[1] = g1map; map[2] = g2map; map[3] = g3map;
165 for (i = 0; i < 4; i++) {
166 if (map[i] < 0)
167 continue;
168 else if (map[i] == 0)
169 gcset->fe[i].flag &= ~GRMAPPING;
170 else
171 gcset->fe[i].flag |= GRMAPPING;
172 }
173 }
174
175 int
176 XWSDrawString(d, w, gcset, x, y, wstr, len)
177 Display *d;
178 Drawable w;
179 XWSGC gcset;
180 int x;
181 int y;
182 wchar *wstr;
183 int len;
184 {
185 return wsdrawstring(d, w, gcset, x, y, wstr, len, 0);
186 }
187
188 int
189 XWSDrawImageString(d, w, gcset, x, y, wstr, len)
190 Display *d;
191 Drawable w;
192 XWSGC gcset;
193 int x;
194 int y;
195 wchar *wstr;
196 int len;
197 {
198 return wsdrawstring(d, w, gcset, x, y, wstr, len, 1);
199 }
200
201 void
202 XWSFontHeight(gcset, wstr, len, ascent, descent)
203 XWSGC gcset;
204 wchar *wstr;
205 int len;
206 int *ascent;
207 int *descent;
208 {
209 FontEnt *fep = &(gcset->fe[0]);
210 int i;
211 int asc = 0;
212 int dsc = 0;
213
214 if (wstr) {
215 while (len-- > 0) {
216 i = GSET(*wstr++);
217 if (fep[i].font) {
218 if ((fep[i].font)->ascent > asc)
219 asc = (fep[i].font)->ascent;
220 if ((fep[i].font)->descent > dsc)
221 dsc = (fep[i].font)->descent;
222 }
223 }
224 } else {
225 for (i = 0; i < 4; i++) {
226 if (fep[i].font) {
227 if ((fep[i].font)->ascent > asc)
228 asc = (fep[i].font)->ascent;
229 if ((fep[i].font)->descent > dsc)
230 dsc = (fep[i].font)->descent;
231 }
232 }
233 }
234 *ascent = asc;
235 *descent = dsc;
236 }
237
238 int
239 XWSTextWidth(gcset, wstr, len)
240 XWSGC gcset;
241 wchar *wstr;
242 int len;
243 {
244 XChar2b buf[bufsize];
245 XChar2b *cp;
246 wchar *wstr1 = wstr + len;
247 XChar2b *cpend = buf + bufsize;
248 int c;
249 int width = 0;
250 int gmask, gset;
251 FontEnt *fe;
252 int is2b;
253 int grmap;
254
255 while (wstr < wstr1) {
256 gmask = *wstr & 0x8080;
257
258 switch (gmask) {
259 case G0MASK:
260 gset = 0;
261 break;
262 case G1MASK:
263 gset = 1;
264 break;
265 case G2MASK:
266 gset = 2;
267 break;
268 case G3MASK:
269 gset = 3;
270 break;
271 }
272
273 fe = &gcset->fe[gset];
274 is2b = fe->flag & TWOB;
275 grmap = (fe->flag & GRMAPPING) ? 0x80 : 0;
276 cp = buf;
277
278 if (fe->font == NULL) {
279 while (wstr < wstr1 && (*wstr & 0x8080) == gmask)
280 wstr++;
281 continue;
282 }
283
284 while (wstr < wstr1 && ((c = *wstr) & 0x8080) == gmask) {
285 if (cp >= cpend - 1) {
286 /* flush */
287 width += XTextWidth16(fe->font, buf, cp - buf);
288 cp = buf;
289 }
290 if (is2b)
291 cp->byte1 = ((c >> 8) & 0x7f) | grmap;
292 else
293 cp->byte1 = 0;
294 cp->byte2 = (c & 0x7f) | grmap;
295 cp++;
296 wstr++;
297 }
298
299 if (cp == buf)
300 continue;
301
302 /* flush */
303 width += XTextWidth16(fe->font, buf, cp - buf);
304 }
305
306 return width;
307 }
308
309 void
310 XWSTextExtents(gcset, wstr, len, ascent, descent, overall)
311 XWSGC gcset;
312 wchar *wstr;
313 int len;
314 int *ascent;
315 int *descent;
316 XCharStruct *overall;
317 {
318 XChar2b buf[bufsize];
319 XChar2b *cp;
320 wchar *wstr1 = wstr + len;
321 XChar2b *cpend = buf + bufsize;
322 int c;
323 int gmask, gset;
324 FontEnt *fe;
325 int is2b;
326 int grmap;
327 int dir, as, ds;
328 XCharStruct oa;
329
330 *ascent = *descent = 0;
331 (void)bzero(overall, sizeof(XCharStruct));
332
333 while (wstr < wstr1) {
334 gmask = *wstr & 0x8080;
335
336 switch (gmask) {
337 case G0MASK:
338 gset = 0;
339 break;
340 case G1MASK:
341 gset = 1;
342 break;
343 case G2MASK:
344 gset = 2;
345 break;
346 case G3MASK:
347 gset = 3;
348 break;
349 }
350
351 fe = &gcset->fe[gset];
352 is2b = fe->flag & TWOB;
353 grmap = (fe->flag & GRMAPPING) ? 0x80 : 0;
354 cp = buf;
355
356 if (fe->font == NULL) {
357 while (wstr < wstr1 && (*wstr & 0x8080) == gmask)
358 wstr++;
359 continue;
360 }
361
362 while (wstr < wstr1 && ((c = *wstr) & 0x8080) == gmask) {
363 if (cp >= cpend - 1) {
364 /* flush */
365 XTextExtents16(fe->font, buf, cp - buf,
366 &dir, &as, &ds, &oa);
367 cp = buf;
368 *ascent = MAX(*ascent, as);
369 *descent = MAX(*descent, ds);
370 overall->lbearing = MIN(overall->lbearing,
371 overall->width + oa.lbearing);
372 overall->rbearing = MAX(overall->rbearing,
373 overall->width + oa.rbearing);
374 overall->width += oa.width;
375 overall->ascent = MAX(overall->ascent, oa.ascent);
376 overall->descent = MAX(overall->descent, oa.descent);
377 }
378 if (is2b)
379 cp->byte1 = ((c >> 8) & 0x7f) | grmap;
380 else
381 cp->byte1 = 0;
382 cp->byte2 = (c & 0x7f) | grmap;
383 cp++;
384 wstr++;
385 }
386
387 if (cp == buf)
388 continue;
389
390 /* flush */
391 XTextExtents16(fe->font, buf, cp - buf, &dir, &as, &ds, &oa);
392 *ascent = MAX(*ascent, as);
393 *descent = MAX(*descent, ds);
394 overall->lbearing = MIN(overall->lbearing,
395 overall->width + oa.lbearing);
396 overall->rbearing = MAX(overall->rbearing,
397 overall->width + oa.rbearing);
398 overall->width += oa.width;
399 overall->ascent = MAX(overall->ascent, oa.ascent);
400 overall->descent = MAX(overall->descent, oa.descent);
401 }
402 }
403
404
405 /*
406 * private functions
407 */
408
409 static int
410 wsdrawstring(d, w, gcset, x, y, wstr, len, image)
411 Display *d;
412 Drawable w;
413 XWSGC gcset;
414 int x;
415 int y;
416 wchar *wstr;
417 int len;
418 int image;
419 {
420 XChar2b buf[bufsize];
421 XChar2b *cp;
422 wchar *wstr1 = wstr + len;
423 XChar2b *cpend = buf + bufsize;
424 int c;
425 int sx = x;
426 int gmask, gset;
427 FontEnt *fe;
428 int is2b;
429 int grmap;
430
431 while (wstr < wstr1) {
432 gmask = *wstr & 0x8080;
433
434 switch (gmask) {
435 case G0MASK:
436 gset = 0;
437 break;
438 case G1MASK:
439 gset = 1;
440 break;
441 case G2MASK:
442 gset = 2;
443 break;
444 case G3MASK:
445 gset = 3;
446 break;
447 }
448
449 fe = &gcset->fe[gset];
450 is2b = fe->flag & TWOB;
451 grmap = (fe->flag & GRMAPPING) ? 0x80 : 0;
452 cp = buf;
453
454 if (fe->gc == NULL) {
455 while (wstr < wstr1 && (*wstr & 0x8080) == gmask)
456 wstr++;
457 continue;
458 }
459 while (wstr < wstr1 && ((c = *wstr) & 0x8080) == gmask) {
460 if (cp >= cpend - 1) {
461 /* flush */
462 x += flushstr(d, w, fe, x, y, buf, cp, image);
463 cp = buf;
464 }
465 if (is2b)
466 cp->byte1 = ((c >> 8) & 0x7f) | grmap;
467 else
468 cp->byte1 = 0;
469 cp->byte2 = (c & 0x7f) | grmap;
470 cp++;
471 wstr++;
472 }
473 /* flush */
474 x += flushstr(d, w, fe, x, y, buf, cp, image);
475 cp = buf;
476 }
477
478 return x - sx;
479 }
480
481 static int
482 flushstr(d, w, fe, x, y, cp0, cp1, image)
483 Display *d;
484 Drawable w;
485 FontEnt *fe;
486 int x;
487 int y;
488 XChar2b *cp0;
489 XChar2b *cp1;
490 int image;
491 {
492 if (cp0 >= cp1 || fe->gc == NULL)
493 return 0;
494
495 if (image)
496 XDrawImageString16(d, w, fe->gc, x, y, cp0, cp1 - cp0);
497 else
498 XDrawString16(d, w, fe->gc, x, y, cp0, cp1 - cp0);
499 return XTextWidth16(fe->font, cp0, cp1 - cp0);
500 }