comparison lib/WcharDisp.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 5a32b68b627d
comparison
equal deleted inserted replaced
-1:000000000000 0:92745d501b9a
1 #ifndef lint
2 static char *rcsid = "$Id: WcharDisp.c,v 1.23 1994/10/27 08:29:05 ishisone Exp $";
3 #endif
4 /*
5 * Copyright (c) 1990 Software Research Associates, Inc.
6 *
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation for any purpose and without fee is hereby granted, provided
9 * that the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of Software Research Associates not be
12 * used in advertising or publicity pertaining to distribution of the
13 * software without specific, written prior permission. Software Research
14 * Associates makes no representations about the suitability of this software
15 * for any purpose. It is provided "as is" without express or implied
16 * warranty.
17 *
18 * Author: Makoto Ishisone, Software Research Associates, Inc., Japan
19 */
20
21 #include <X11/IntrinsicP.h>
22 #include <X11/StringDefs.h>
23 #include <X11/Xmu/CharSet.h>
24 #include "CachedAtom.h"
25 #include "WcharDispP.h"
26 #include "LocalAlloc.h"
27
28 #define DEBUG_VAR debug_wcharDisplay
29 #include "DebugPrint.h"
30
31 /*
32 * R5 servers implicitly changes font properties when an alias name is
33 * used. The character set properties (CHARSET_REGISTRY and
34 * CHARSET_ENCODING) are taken from the XLFD fontname. So if the
35 * fontname is represented in lower-case letters, for example:
36 * -jis-fixed-medium-r-normal--16-110-100-100-c-160-jisx0208.1983-0
37 * (this example is taken from R5 fonts/misc/fonts.alias file)
38 * then, the value of CHARSET_REGISTRY becomes "jisx0208.1983",
39 * instead of the registered charset name "JISX0208.1983".
40 * The following flag forces kinput2 to accept these invalid lower
41 * case charset names as well.
42 */
43 #define ALLOW_LOWERCASE_CHARSET_NAME
44
45 static FontMapping defaultMapping = { { False, False, False, False } };
46
47 static XtResource resources[] = {
48 #define offset(field) XtOffset(WcharDisplayObject, wcharDisplay.field)
49 { XtNfontG0, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
50 offset(defaultfonts[0]), XtRString, XtDefaultFont },
51 { XtNfontG1, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
52 offset(defaultfonts[1]), XtRImmediate, (XtPointer)NULL },
53 { XtNfontG2, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
54 offset(defaultfonts[2]), XtRImmediate, (XtPointer)NULL },
55 { XtNfontG3, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
56 offset(defaultfonts[3]), XtRImmediate, (XtPointer)NULL },
57 { XtNfontMapping, XtCFontMapping, XtRFontMapping, sizeof (FontMapping),
58 offset(defaultmapping), XtRFontMapping, (XtPointer)&defaultMapping },
59 #undef offset
60 };
61
62 static WDCharSet defCharSet[] = {
63 { "ISO8859-1", G0LCharSet },
64 { "JISX0201.1976-0", G0LCharSet }, /* alternative */
65 #ifdef ALLOW_LOWERCASE_CHARSET_NAME
66 { "iso8859-1", G0LCharSet },
67 { "jisx0201.1976-0", G0LCharSet }, /* alternative */
68 #endif
69 };
70
71 static void ClassInitialize();
72 static void StringToFontMapping();
73
74 static void Initialize();
75 static void Destroy();
76 static Boolean SetValues();
77
78 static void GetAtoms();
79 static void GetGC();
80 static void ChangeFont();
81
82 static int StringWidth();
83 static int LineHeight();
84 static void DrawString();
85 static int MaxChar();
86 static void SetFonts();
87
88 static int countControlChars();
89 static void expandControlChars();
90 static int charWidth();
91
92 WcharDisplayClassRec wcharDisplayClassRec = {
93 { /* object fields */
94 /* superclass */ (WidgetClass)&convDisplayClassRec,
95 /* class_name */ "WcharDisplay",
96 /* widget_size */ sizeof(WcharDisplayRec),
97 /* class_initialize */ ClassInitialize,
98 /* class_part_initialize */ NULL,
99 /* class_inited */ FALSE,
100 /* initialize */ Initialize,
101 /* initialize_hook */ NULL,
102 /* obj1 */ NULL,
103 /* obj2 */ NULL,
104 /* obj3 */ 0,
105 /* resources */ resources,
106 /* num_resources */ XtNumber(resources),
107 /* xrm_class */ NULLQUARK,
108 /* obj4 */ FALSE,
109 /* obj5 */ FALSE,
110 /* obj6 */ FALSE,
111 /* obj7 */ FALSE,
112 /* destroy */ Destroy,
113 /* obj8 */ NULL,
114 /* obj9 */ NULL,
115 /* set_values */ SetValues,
116 /* set_values_hook */ NULL,
117 /* obj10 */ NULL,
118 /* get_values_hook */ NULL,
119 /* obj11 */ NULL,
120 /* version */ XtVersion,
121 /* callback_private */ NULL,
122 /* obj12 */ NULL,
123 /* obj13 */ NULL,
124 /* obj14 */ NULL,
125 /* extension */ NULL
126 },
127 { /* convDisplay fields */
128 /* StringWidth */ StringWidth,
129 /* LineHeight */ LineHeight,
130 /* DrawString */ DrawString,
131 /* MaxChar */ MaxChar,
132 /* DrawCursor */ XtInheritDrawCursor,
133 /* GetCursorBounds */ XtInheritGetCursorBounds,
134 /* SetFonts */ SetFonts,
135 },
136 { /* wcharDisplay fields */
137 /* charset_specs */ defCharSet,
138 /* num_specs */ XtNumber(defCharSet),
139 }
140 };
141
142 WidgetClass wcharDisplayObjectClass = (WidgetClass)&wcharDisplayClassRec;
143
144 /* ARGSUSED */
145 static void
146 ClassInitialize()
147 {
148 /* add String -> FontMapping converter */
149 XtAddConverter(XtRString, XtRFontMapping, StringToFontMapping,
150 (XtConvertArgList)NULL, (Cardinal)0);
151 }
152
153 /* ARGSUSED */
154 static void
155 StringToFontMapping(args, num_args, from, to)
156 XrmValue *args;
157 Cardinal *num_args;
158 XrmValue *from;
159 XrmValue *to;
160 {
161 char *s = (char *)from->addr;
162 char buf[128];
163 static FontMapping fm;
164 int c;
165 int i;
166
167 for (i = 0; i < 4; i++) fm.grmapping[i] = False;
168 to->size = sizeof(FontMapping);
169 to->addr = (caddr_t)&fm;
170
171 if (strlen(s) + 1 > sizeof(buf)) return;
172
173 XmuCopyISOLatin1Lowered(buf, s);
174 s = buf;
175 for (i = 0; i < 4; i++) {
176 while ((c = *s) != '\0' && (c == ' ' || c == '\t' || c == '\n')) s++;
177 if (c == '\0') break;
178 if (c == '/' || c == ',') {
179 s++;
180 continue;
181 }
182 if (!strncmp(s, "gl", 2)) {
183 fm.grmapping[i] = False;
184 } else if (!strncmp(s, "gr", 2)) {
185 fm.grmapping[i] = True;
186 } else {
187 XtStringConversionWarning(s, XtRFontMapping);
188 }
189 s += 2;
190 while ((c = *s) != '\0' && (c == ' ' || c == '\t' || c == '\n')) s++;
191 if (c == '\0') break;
192 if (c == '/' || c == ',') s++;
193 }
194 }
195
196 /* ARGSUSED */
197 static void
198 Initialize(req, new, args, num_args)
199 Widget req;
200 Widget new;
201 ArgList args;
202 Cardinal *num_args;
203 {
204 WcharDisplayObjectClass class = (WcharDisplayObjectClass)XtClass(new);
205 WcharDisplayObject obj = (WcharDisplayObject)new;
206 int i;
207 static char stipple_bits[] = {
208 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,
209 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00,
210 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00
211 };
212
213 /* create a Stipple Bitmap (for drawing CurrentSubSegment) */
214 obj->wcharDisplay.stipple =
215 XCreateBitmapFromData(XtDisplayOfObject((Widget)obj),
216 RootWindowOfScreen(XtScreenOfObject((Widget)obj)),
217 stipple_bits, 16, 16);
218
219 for (i = 0; i < 4; i++) {
220 obj->wcharDisplay.fonts[i] = obj->wcharDisplay.defaultfonts[i];
221 obj->wcharDisplay.grmapping[i] =
222 obj->wcharDisplay.defaultmapping.grmapping[i];
223 }
224
225 obj->wcharDisplay.num_specs = class->wcharDisplay_class.num_specs;
226 obj->wcharDisplay.charset_specs = class->wcharDisplay_class.charset_specs;
227
228 GetAtoms(obj);
229 GetGC(obj);
230 }
231
232 static void
233 Destroy(w)
234 Widget w;
235 {
236 WcharDisplayObject obj = (WcharDisplayObject)w;
237
238 XtFree((char *)obj->wcharDisplay.fontspecs);
239 XtWSReleaseGCSet(w, obj->wcharDisplay.gcset_normal);
240 XtWSReleaseGCSet(w, obj->wcharDisplay.gcset_rev);
241 XFreePixmap(XtDisplayOfObject((Widget)obj), obj->wcharDisplay.stipple);
242 }
243
244 /* ARGSUSED */
245 static Boolean
246 SetValues(cur, req, wid, args, num_args)
247 Widget cur;
248 Widget req;
249 Widget wid;
250 ArgList args;
251 Cardinal *num_args;
252 {
253 WcharDisplayObject old = (WcharDisplayObject)cur;
254 WcharDisplayObject new = (WcharDisplayObject)wid;
255 Boolean redraw = False;
256 int i;
257
258 #define wd wcharDisplay
259 for (i = 0; i < 4; i++) {
260 if ((new->wd.defaultfonts[i] != old->wd.defaultfonts[i] ||
261 new->wd.defaultmapping.grmapping[i] !=
262 new->wd.defaultmapping.grmapping[i]) &&
263 new->wd.fonts[i] == old->wd.defaultfonts[i]) {
264 redraw = True;
265 break;
266 }
267 }
268 if (redraw ||
269 new->convDisplay.foreground != old->convDisplay.foreground ||
270 new->convDisplay.background != old->convDisplay.background) {
271 XtWSReleaseGCSet(wid, new->wcharDisplay.gcset_normal);
272 XtWSReleaseGCSet(wid, new->wcharDisplay.gcset_rev);
273 GetGC(new);
274 redraw = True;
275 }
276 #undef wd
277
278 return redraw;
279 }
280
281 static void
282 GetAtoms(obj)
283 WcharDisplayObject obj;
284 {
285 Display *dpy = XtDisplayOfObject((Widget)obj);
286 WDCharSet *csp;
287 FontSpec *fsp;
288 Cardinal nspecs;
289 char buf[128];
290 char *p, *q;
291 int i;
292 String params[1];
293 Cardinal num_params;
294
295 if ((nspecs = obj->wcharDisplay.num_specs) == 0) {
296 params[0] = XtClass((Widget)obj)->core_class.class_name;
297 num_params = 1;
298 XtAppErrorMsg(XtWidgetToApplicationContext((Widget)obj),
299 "noEntry", "charSpec", "WidgetError",
300 "%s: has no character set spec.",
301 params, &num_params);
302 }
303
304 csp = obj->wcharDisplay.charset_specs;
305 fsp = (FontSpec *)XtMalloc(sizeof(FontSpec) * obj->wcharDisplay.num_specs);
306 obj->wcharDisplay.fontspecs = fsp;
307
308 for (i = 0; i < nspecs; i++, csp++, fsp++) {
309 p = csp->charset;
310 q = buf;
311 while (*p != '\0' && *p != '-') *q++ = *p++;
312 if (*p++ == '\0' || *p == '\0') {
313 params[0] = XtClass((Widget)obj)->core_class.class_name;
314 num_params = 1;
315 XtAppErrorMsg(XtWidgetToApplicationContext((Widget)obj),
316 "invalidSpec", "charSetSpec", "WidgetError",
317 "%s: has invalid character set spec.",
318 params, &num_params);
319 }
320 *q = '\0';
321 fsp->registry = CachedInternAtom(dpy, buf, False);
322 fsp->encoding = CachedInternAtom(dpy, p, False);
323 }
324 }
325
326 static void
327 GetGC(obj)
328 WcharDisplayObject obj;
329 {
330 XtGCMask mask = GCFont|GCForeground|GCBackground;
331 XGCValues values;
332 int ascent, descent;
333 Boolean *map = obj->wcharDisplay.grmapping;
334
335 values.function = GXcopy;
336 values.foreground = obj->convDisplay.foreground;
337 values.background = obj->convDisplay.background;
338 mask = GCFunction|GCForeground|GCBackground;
339 obj->wcharDisplay.gc_normal = XtGetGC((Widget)obj, mask, &values);
340
341 values.foreground = obj->convDisplay.background;
342 values.fill_style = FillStippled;
343 values.stipple = obj->wcharDisplay.stipple;
344 mask = GCFunction|GCForeground|GCFillStyle|GCStipple;
345 obj->wcharDisplay.gc_stipple = XtGetGC((Widget)obj, mask, &values);
346
347 mask = GCFont|GCFunction|GCForeground|GCBackground;
348 values.function = GXcopy;
349 values.foreground = obj->convDisplay.foreground;
350 values.background = obj->convDisplay.background;
351 obj->wcharDisplay.gcset_normal = XtWSGetGCSet((Widget)obj, mask, &values,
352 obj->wcharDisplay.fonts[0],
353 obj->wcharDisplay.fonts[1],
354 obj->wcharDisplay.fonts[2],
355 obj->wcharDisplay.fonts[3]);
356 values.foreground = obj->convDisplay.background;
357 values.background = obj->convDisplay.foreground;
358 obj->wcharDisplay.gcset_rev = XtWSGetGCSet((Widget)obj, mask, &values,
359 obj->wcharDisplay.fonts[0],
360 obj->wcharDisplay.fonts[1],
361 obj->wcharDisplay.fonts[2],
362 obj->wcharDisplay.fonts[3]);
363
364 /* set font mapping */
365 XWSSetMapping(obj->wcharDisplay.gcset_normal,
366 map[0], map[1], map[2], map[3]);
367 XWSSetMapping(obj->wcharDisplay.gcset_rev,
368 map[0], map[1], map[2], map[3]);
369
370 XWSFontHeight(obj->wcharDisplay.gcset_normal, NULL, 0, &ascent, &descent);
371 obj->wcharDisplay.ascent = ascent;
372 obj->wcharDisplay.fontheight = ascent + descent;
373 }
374
375 static void
376 ChangeFont(obj, fonts, mapping)
377 WcharDisplayObject obj;
378 XFontStruct **fonts;
379 Boolean *mapping;
380 {
381 Boolean newgc = False;
382 int i;
383
384 for (i = 0; i < 4; i++) {
385 if (fonts[i] != obj->wcharDisplay.fonts[i] ||
386 mapping[i] != obj->wcharDisplay.grmapping[i]) {
387 obj->wcharDisplay.fonts[i] = fonts[i];
388 obj->wcharDisplay.grmapping[i] = mapping[i];
389 newgc = True;
390 }
391 }
392 if (newgc) {
393 XtWSReleaseGCSet((Widget)obj, obj->wcharDisplay.gcset_normal);
394 XtWSReleaseGCSet((Widget)obj, obj->wcharDisplay.gcset_rev);
395 GetGC(obj);
396 }
397 }
398
399 static int
400 StringWidth(w, seg, start, end)
401 Widget w;
402 ICString *seg;
403 int start;
404 int end;
405 {
406 WcharDisplayObject obj = (WcharDisplayObject)w;
407 wchar *wstr;
408 int len = seg->nchars;
409 int nctl;
410 int width;
411
412 if (end < 0 || len < end) end = len;
413 if (start >= end || start >= len) return 0;
414
415 wstr = (wchar *)seg->data + start;
416 len = end - start;
417
418 /*
419 * searching for control characters -- if found, convert them
420 * into '^?' format for readability.
421 */
422 if ((nctl = countControlChars(wstr, len)) == 0) {
423 /* no control characters */
424 width = XWSTextWidth(obj->wcharDisplay.gcset_normal, wstr, len);
425 } else {
426 wchar *s = (wchar *)LOCAL_ALLOC(sizeof(wchar) * (len + nctl));
427
428 expandControlChars(wstr, len, s);
429 width = XWSTextWidth(obj->wcharDisplay.gcset_normal, s, len + nctl);
430 LOCAL_FREE(s);
431 }
432 return width;
433 }
434
435 static int
436 LineHeight(w, ascentp)
437 Widget w;
438 Position *ascentp;
439 {
440 WcharDisplayObject obj = (WcharDisplayObject)w;
441
442 if (ascentp != NULL) *ascentp = obj->wcharDisplay.ascent;
443 return obj->wcharDisplay.fontheight;
444 }
445
446 static void
447 DrawString(w, canvas, seg, start, end, x, y)
448 Widget w;
449 Widget canvas;
450 ICString *seg;
451 int start;
452 int end;
453 int x;
454 int y;
455 {
456 WcharDisplayObject obj = (WcharDisplayObject)w;
457 wchar *wstr;
458 XWSGC gcset;
459 int len = seg->nchars;
460 int nctl;
461 Display *dpy = XtDisplay(canvas);
462 Window win = XtWindow(canvas);
463 int width;
464 int attr;
465
466 if (end < 0 || len < end) end = len;
467 if (start >= end || start >= len) return;
468
469 wstr = (wchar *)seg->data + start;
470 len = end - start;
471
472 #define STIPPLED 1
473 #define UNDERLINED 2
474
475 if (seg->attr == ICAttrNormalString) {
476 gcset = obj->wcharDisplay.gcset_normal;
477 attr = 0;
478 } else if (seg->attr & ICAttrConverted) {
479 /* converted segment */
480 if (seg->attr & ICAttrCurrentSegment) {
481 gcset = obj->wcharDisplay.gcset_rev;
482 attr = 0;
483 } else if (seg->attr & ICAttrCurrentSubSegment) {
484 gcset = obj->wcharDisplay.gcset_rev;
485 attr = STIPPLED;
486 } else {
487 gcset = obj->wcharDisplay.gcset_normal;
488 attr = 0;
489 }
490 } else { /* ICAttrNotConverted */
491 gcset = obj->wcharDisplay.gcset_normal;
492 attr = UNDERLINED;
493 }
494
495 if ((nctl = countControlChars(wstr, len)) == 0) {
496 width = XWSDrawImageString(dpy, win, gcset,
497 x, y + obj->wcharDisplay.ascent,
498 wstr, len);
499 } else {
500 wchar *s = (wchar *)LOCAL_ALLOC((len + nctl) * sizeof(wchar));
501 expandControlChars(wstr, len, s);
502 width = XWSDrawImageString(dpy, win, gcset,
503 x, y + obj->wcharDisplay.ascent,
504 s, len + nctl);
505 LOCAL_FREE(s);
506 }
507
508 if (attr == UNDERLINED) {
509 int uloffset = 1;
510 int descent = obj->wcharDisplay.fontheight - obj->wcharDisplay.ascent;
511
512 if (descent <= 1) {
513 /* font descent is 0 or 1 */
514 uloffset = descent - 1;
515 }
516 XDrawLine(dpy, win, obj->wcharDisplay.gc_normal,
517 x, y + obj->wcharDisplay.ascent + uloffset,
518 x + width - 1, y + obj->wcharDisplay.ascent + uloffset);
519 } else if (attr == STIPPLED) {
520 XFillRectangle(dpy, win, obj->wcharDisplay.gc_stipple, x, y,
521 (unsigned int)width,
522 (unsigned int)obj->wcharDisplay.fontheight);
523 }
524 }
525
526 static int
527 MaxChar(w, seg, start, width)
528 Widget w;
529 ICString *seg;
530 int start;
531 int width;
532 {
533 WcharDisplayObject obj = (WcharDisplayObject)w;
534 XWSGC gcset = obj->wcharDisplay.gcset_normal;
535 wchar *sp = (wchar *)seg->data + start;
536 wchar *ep = (wchar *)seg->data + seg->nchars;
537 int cwidth;
538 int chars;
539
540 chars = 0;
541 while (sp < ep) {
542 cwidth = charWidth(*sp++, gcset);
543 if (width < cwidth) break;
544 chars++;
545 if ((width -= cwidth) == 0) break;
546 }
547 return chars;
548 }
549
550 static void
551 SetFonts(w, fonts, num_fonts)
552 Widget w;
553 XFontStruct **fonts;
554 Cardinal num_fonts;
555 {
556 WcharDisplayObject obj = (WcharDisplayObject)w;
557 WDCharSet *csp = obj->wcharDisplay.charset_specs;
558 FontSpec *fsp = obj->wcharDisplay.fontspecs;
559 Cardinal nspecs = obj->wcharDisplay.num_specs;
560 Cardinal i, j;
561 XFontStruct *pickedfonts[4];
562 Boolean mapping[4];
563 static int csetmask[4] = {
564 G0LCharSet|G0RCharSet,
565 G1LCharSet|G1RCharSet,
566 G2LCharSet|G2RCharSet,
567 G3LCharSet|G3RCharSet,
568 };
569
570 if (num_fonts == 0) {
571 ChangeFont(obj, obj->wcharDisplay.defaultfonts,
572 obj->wcharDisplay.defaultmapping.grmapping);
573 return;
574 }
575
576 for (i = 0; i < 4; i++) pickedfonts[i] = NULL;
577
578 (void)_CDPickupFonts(w, fsp, nspecs, fonts, num_fonts);
579
580 #define GRMAP (G0RCharSet|G1RCharSet|G2RCharSet|G3RCharSet)
581 for (j = 0; j < nspecs; j++, fsp++, csp++) {
582 if (fsp->font == NULL) continue;
583 for (i = 0; i < 4; i++) {
584 if (pickedfonts[i] == NULL && (csp->flag & csetmask[i])) {
585 pickedfonts[i] = fsp->font;
586 mapping[i] = (csp->flag & csetmask[i] & GRMAP) ? True : False;
587 }
588 }
589 }
590 #undef GRMAP
591 for (i = 0; i < 4; i++) {
592 if (pickedfonts[i] == NULL) {
593 pickedfonts[i] = obj->wcharDisplay.defaultfonts[i];
594 mapping[i] = obj->wcharDisplay.defaultmapping.grmapping[i];
595 }
596 }
597
598 ChangeFont(obj, pickedfonts, mapping);
599 }
600
601 /* countControlChars -- count number of control characters in a string */
602 static int
603 countControlChars(wstr, len)
604 register wchar *wstr;
605 int len;
606 {
607 register wchar *end = wstr + len;
608 register int n = 0;
609
610 while (wstr < end) {
611 if (*wstr < 0x20 || *wstr == 0x7f) n++;
612 wstr++;
613 }
614 return n;
615 }
616
617 /* expandControlChars -- convert control characters into '^?' format */
618 static void
619 expandControlChars(org, orglen, res)
620 wchar *org;
621 int orglen;
622 wchar *res;
623 {
624 wchar *end;
625
626 for (end = org + orglen; org < end; org++) {
627 if (*org < 0x20 || *org == 0x7f) {
628 *res++ = '^';
629 *res++ = *org ^ 0x40;
630 } else {
631 *res++ = *org;
632 }
633 }
634 }
635
636 #define WITHIN_RANGE_2D(row, col, fs) \
637 ((fs)->min_byte1 <= (row) && (row) <= (fs)->max_byte1 && \
638 (fs)->min_char_or_byte2 <= (col) && (col) <= (fs)->max_char_or_byte2)
639
640 #define WITHIN_RANGE(c, fs) \
641 ((fs)->min_char_or_byte2 <= (c) && (c) <= (fs)->max_char_or_byte2)
642
643 #define CHAR_INFO_2D(row, col, fs) \
644 ((fs)->per_char + ((row) - (fs)->min_byte1) * \
645 ((fs)->max_char_or_byte2 - (fs)->min_char_or_byte2 + 1) + \
646 ((col) - (fs)->min_char_or_byte2))
647
648 #define CHAR_INFO(c, fs) \
649 ((fs)->per_char + ((c) - (fs)->min_char_or_byte2))
650
651 #define CHAR_EXIST(csp) \
652 ((csp)->width != 0 || ((csp)->rbearing != 0) || ((csp)->lbearing != 0))
653
654 static int
655 defaultCharWidth(font)
656 XFontStruct *font;
657 {
658 int defchar = font->default_char;
659
660 if (font->min_byte1 || font->max_byte1) {
661 int row = defchar >> 8;
662 int col = defchar & 0xff;
663 if (WITHIN_RANGE_2D(row, col, font)) {
664 if (font->per_char == NULL) {
665 return font->min_bounds.width;
666 } else {
667 XCharStruct *csp = CHAR_INFO_2D(row, col, font);
668 return CHAR_EXIST(csp) ? csp->width : 0;
669 }
670 } else {
671 return 0;
672 }
673 } else {
674 if (WITHIN_RANGE(defchar, font)) {
675 if (font->per_char == NULL) {
676 return font->min_bounds.width;
677 } else {
678 XCharStruct *csp = CHAR_INFO(defchar, font);
679 return CHAR_EXIST(csp) ? csp->width : 0;
680 }
681 } else {
682 return 0;
683 }
684 }
685 }
686
687 /* charWidth -- returns width of the specified character */
688 static int
689 charWidth(c, gcset)
690 register int c;
691 XWSGC gcset;
692 {
693 register XFontStruct *font;
694 int width;
695 int gset;
696 int nonPrinting = (c < 0x20 || c == 0x7f);
697
698 if (nonPrinting) c ^= 0x40;
699
700 switch (c & 0x8080) {
701 case 0x0000: gset = 0; break;
702 case 0x8080: gset = 1; break;
703 case 0x0080: gset = 2; break;
704 case 0x8000: gset = 3; break;
705 }
706
707 if ((font = gcset->fe[gset].font) == NULL) return 0;
708
709 if (gcset->fe[gset].flag & GRMAPPING) {
710 c |= 0x8080;
711 } else {
712 c &= 0x7f7f;
713 }
714
715 if (gcset->fe[gset].flag & TWOB) {
716 register int row = (c >> 8) & 0xff;
717 register int col = c & 0xff;
718 if (WITHIN_RANGE_2D(row, col, font)) {
719 if (font->per_char == NULL) {
720 width = font->min_bounds.width;
721 } else {
722 XCharStruct *csp = CHAR_INFO_2D(row, col, font);
723
724 width = CHAR_EXIST(csp) ? csp->width : defaultCharWidth(font);
725 }
726 } else {
727 width = defaultCharWidth(font);
728 }
729 } else {
730 c &= 0xff;
731 if (WITHIN_RANGE(c, font)) {
732 if (font->per_char == NULL) {
733 width = font->min_bounds.width;
734 } else {
735 XCharStruct *csp = CHAR_INFO(c, font);
736
737 width = CHAR_EXIST(csp) ? csp->width : defaultCharWidth(font);
738 }
739 } else {
740 width = defaultCharWidth(font);
741 }
742 }
743 if (nonPrinting) width += charWidth('^', gcset);
744
745 return width;
746 }
747
748
749 /*
750 * jpWcharDisplay definition
751 *
752 * character set assignment for Japanese wchar:
753 * G0: ascii (ISO8859/1 left-half)
754 * G1: kanji (JISX0208)
755 * G2: half-width kana (JISX0201 right-half)
756 * G3: unused
757 */
758
759 static FontMapping jpDefaultMapping = { { False, False, True, False } };
760
761 #define JPFONT_ASCII "-Misc-Fixed-Medium-R-*--14-*-*-*-C-*-ISO8859-1"
762 #define JPFONT_KANJI "-Misc-Fixed-Medium-R-*--14-*-*-*-C-*-JISX0208.1983-0"
763 #define JPFONT_KANA "-Misc-Fixed-Medium-R-*--14-*-*-*-C-*-JISX0201.1976-0"
764
765 static XtResource jpresources[] = {
766 /* only override superclass's default */
767 #define offset(field) XtOffset(JpWcharDisplayObject, wcharDisplay.field)
768 { XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
769 offset(defaultfonts[0]), XtRString, JPFONT_ASCII },
770 { XtNkanjiFont, XtCKanjiFont, XtRFontStruct, sizeof (XFontStruct *),
771 offset(defaultfonts[1]), XtRString, JPFONT_KANJI },
772 { XtNkanaFont, XtCKanaFont, XtRFontStruct, sizeof (XFontStruct *),
773 offset(defaultfonts[2]), XtRString, JPFONT_KANA },
774 { XtNfontG3, "Not.used", XtRFontStruct, sizeof (XFontStruct *),
775 offset(defaultfonts[3]), XtRImmediate, (XtPointer)NULL },
776 { XtNfontMapping, XtCFontMapping, XtRFontMapping, sizeof (FontMapping),
777 offset(defaultmapping), XtRFontMapping, (XtPointer)&jpDefaultMapping },
778 #undef offset
779 };
780
781 static WDCharSet jpCharSet[] = {
782 { "ISO8859-1", G0LCharSet }, /* my preference */
783 { "JISX0201.1976-0", G0LCharSet | G2RCharSet },
784 { "JISX0208.1990-0", G1LCharSet },
785 { "JISX0208.1983-0", G1LCharSet },
786 { "JISX0208.1978-0", G1LCharSet },
787 { "JISX0208.1983-1", G1RCharSet },
788 { "JISX0208.1978-1", G1RCharSet },
789 #ifdef ALLOW_LOWERCASE_CHARSET_NAME
790 { "iso8859-1", G0LCharSet }, /* my preference */
791 { "jisx0201.1976-0", G0LCharSet | G2RCharSet },
792 { "jisx0208.1990-0", G1LCharSet },
793 { "jisx0208.1983-0", G1LCharSet },
794 { "jisx0208.1978-0", G1LCharSet },
795 { "jisx0208.1983-1", G1RCharSet },
796 { "jisx0208.1978-1", G1RCharSet },
797 #endif
798 };
799
800 JpWcharDisplayClassRec jpWcharDisplayClassRec = {
801 { /* object fields */
802 /* superclass */ (WidgetClass)&wcharDisplayClassRec,
803 /* class_name */ "JpWcharDisplay",
804 /* widget_size */ sizeof(JpWcharDisplayRec),
805 /* class_initialize */ NULL,
806 /* class_part_initialize */ NULL,
807 /* class_inited */ FALSE,
808 /* initialize */ NULL,
809 /* initialize_hook */ NULL,
810 /* obj1 */ NULL,
811 /* obj2 */ NULL,
812 /* obj3 */ 0,
813 /* resources */ jpresources,
814 /* num_resources */ XtNumber(jpresources),
815 /* xrm_class */ NULLQUARK,
816 /* obj4 */ FALSE,
817 /* obj5 */ FALSE,
818 /* obj6 */ FALSE,
819 /* obj7 */ FALSE,
820 /* destroy */ NULL,
821 /* obj8 */ NULL,
822 /* obj9 */ NULL,
823 /* set_values */ NULL,
824 /* set_values_hook */ NULL,
825 /* obj10 */ NULL,
826 /* get_values_hook */ NULL,
827 /* obj11 */ NULL,
828 /* version */ XtVersion,
829 /* callback_private */ NULL,
830 /* obj12 */ NULL,
831 /* obj13 */ NULL,
832 /* obj14 */ NULL,
833 /* extension */ NULL
834 },
835 { /* convDisplay fields */
836 /* StringWidth */ XtInheritStringWidth,
837 /* LineHeight */ XtInheritLineHeight,
838 /* DrawString */ XtInheritDrawString,
839 /* MaxChar */ XtInheritMaxChar,
840 /* DrawCursor */ XtInheritDrawCursor,
841 /* GetCursorBounds */ XtInheritGetCursorBounds,
842 /* SetFonts */ XtInheritSetFonts,
843 },
844 { /* wcharDisplay fields */
845 /* charset_specs */ jpCharSet,
846 /* num_specs */ XtNumber(jpCharSet),
847 },
848 { /* jpWcharDisplay fields */
849 /* empty */ 0,
850 },
851 };
852
853 WidgetClass jpWcharDisplayObjectClass = (WidgetClass)&jpWcharDisplayClassRec;