Mercurial > kinput2.yaz
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; |