Mercurial > kinput2.yaz
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/WcharDisp.c Mon Mar 08 04:44:30 2010 +0900 @@ -0,0 +1,853 @@ +#ifndef lint +static char *rcsid = "$Id: WcharDisp.c,v 1.23 1994/10/27 08:29:05 ishisone Exp $"; +#endif +/* + * Copyright (c) 1990 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 + */ + +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/CharSet.h> +#include "CachedAtom.h" +#include "WcharDispP.h" +#include "LocalAlloc.h" + +#define DEBUG_VAR debug_wcharDisplay +#include "DebugPrint.h" + +/* + * R5 servers implicitly changes font properties when an alias name is + * used. The character set properties (CHARSET_REGISTRY and + * CHARSET_ENCODING) are taken from the XLFD fontname. So if the + * fontname is represented in lower-case letters, for example: + * -jis-fixed-medium-r-normal--16-110-100-100-c-160-jisx0208.1983-0 + * (this example is taken from R5 fonts/misc/fonts.alias file) + * then, the value of CHARSET_REGISTRY becomes "jisx0208.1983", + * instead of the registered charset name "JISX0208.1983". + * The following flag forces kinput2 to accept these invalid lower + * case charset names as well. + */ +#define ALLOW_LOWERCASE_CHARSET_NAME + +static FontMapping defaultMapping = { { False, False, False, False } }; + +static XtResource resources[] = { +#define offset(field) XtOffset(WcharDisplayObject, wcharDisplay.field) + { XtNfontG0, XtCFont, XtRFontStruct, sizeof (XFontStruct *), + offset(defaultfonts[0]), XtRString, XtDefaultFont }, + { XtNfontG1, XtCFont, XtRFontStruct, sizeof (XFontStruct *), + offset(defaultfonts[1]), XtRImmediate, (XtPointer)NULL }, + { XtNfontG2, XtCFont, XtRFontStruct, sizeof (XFontStruct *), + offset(defaultfonts[2]), XtRImmediate, (XtPointer)NULL }, + { XtNfontG3, XtCFont, XtRFontStruct, sizeof (XFontStruct *), + offset(defaultfonts[3]), XtRImmediate, (XtPointer)NULL }, + { XtNfontMapping, XtCFontMapping, XtRFontMapping, sizeof (FontMapping), + offset(defaultmapping), XtRFontMapping, (XtPointer)&defaultMapping }, +#undef offset +}; + +static WDCharSet defCharSet[] = { + { "ISO8859-1", G0LCharSet }, + { "JISX0201.1976-0", G0LCharSet }, /* alternative */ +#ifdef ALLOW_LOWERCASE_CHARSET_NAME + { "iso8859-1", G0LCharSet }, + { "jisx0201.1976-0", G0LCharSet }, /* alternative */ +#endif +}; + +static void ClassInitialize(); +static void StringToFontMapping(); + +static void Initialize(); +static void Destroy(); +static Boolean SetValues(); + +static void GetAtoms(); +static void GetGC(); +static void ChangeFont(); + +static int StringWidth(); +static int LineHeight(); +static void DrawString(); +static int MaxChar(); +static void SetFonts(); + +static int countControlChars(); +static void expandControlChars(); +static int charWidth(); + +WcharDisplayClassRec wcharDisplayClassRec = { + { /* object fields */ + /* superclass */ (WidgetClass)&convDisplayClassRec, + /* class_name */ "WcharDisplay", + /* widget_size */ sizeof(WcharDisplayRec), + /* class_initialize */ ClassInitialize, + /* class_part_initialize */ NULL, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* obj1 */ NULL, + /* obj2 */ NULL, + /* obj3 */ 0, + /* resources */ resources, + /* num_resources */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* obj4 */ FALSE, + /* obj5 */ FALSE, + /* obj6 */ FALSE, + /* obj7 */ FALSE, + /* destroy */ Destroy, + /* obj8 */ NULL, + /* obj9 */ NULL, + /* set_values */ SetValues, + /* set_values_hook */ NULL, + /* obj10 */ NULL, + /* get_values_hook */ NULL, + /* obj11 */ NULL, + /* version */ XtVersion, + /* callback_private */ NULL, + /* obj12 */ NULL, + /* obj13 */ NULL, + /* obj14 */ NULL, + /* extension */ NULL + }, + { /* convDisplay fields */ + /* StringWidth */ StringWidth, + /* LineHeight */ LineHeight, + /* DrawString */ DrawString, + /* MaxChar */ MaxChar, + /* DrawCursor */ XtInheritDrawCursor, + /* GetCursorBounds */ XtInheritGetCursorBounds, + /* SetFonts */ SetFonts, + }, + { /* wcharDisplay fields */ + /* charset_specs */ defCharSet, + /* num_specs */ XtNumber(defCharSet), + } +}; + +WidgetClass wcharDisplayObjectClass = (WidgetClass)&wcharDisplayClassRec; + +/* ARGSUSED */ +static void +ClassInitialize() +{ + /* add String -> FontMapping converter */ + XtAddConverter(XtRString, XtRFontMapping, StringToFontMapping, + (XtConvertArgList)NULL, (Cardinal)0); +} + +/* ARGSUSED */ +static void +StringToFontMapping(args, num_args, from, to) +XrmValue *args; +Cardinal *num_args; +XrmValue *from; +XrmValue *to; +{ + char *s = (char *)from->addr; + char buf[128]; + static FontMapping fm; + int c; + int i; + + for (i = 0; i < 4; i++) fm.grmapping[i] = False; + to->size = sizeof(FontMapping); + to->addr = (caddr_t)&fm; + + if (strlen(s) + 1 > sizeof(buf)) return; + + XmuCopyISOLatin1Lowered(buf, s); + s = buf; + for (i = 0; i < 4; i++) { + while ((c = *s) != '\0' && (c == ' ' || c == '\t' || c == '\n')) s++; + if (c == '\0') break; + if (c == '/' || c == ',') { + s++; + continue; + } + if (!strncmp(s, "gl", 2)) { + fm.grmapping[i] = False; + } else if (!strncmp(s, "gr", 2)) { + fm.grmapping[i] = True; + } else { + XtStringConversionWarning(s, XtRFontMapping); + } + s += 2; + while ((c = *s) != '\0' && (c == ' ' || c == '\t' || c == '\n')) s++; + if (c == '\0') break; + if (c == '/' || c == ',') s++; + } +} + +/* ARGSUSED */ +static void +Initialize(req, new, args, num_args) +Widget req; +Widget new; +ArgList args; +Cardinal *num_args; +{ + WcharDisplayObjectClass class = (WcharDisplayObjectClass)XtClass(new); + WcharDisplayObject obj = (WcharDisplayObject)new; + int i; + static char stipple_bits[] = { + 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, + 0xaa, 0xaa, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, + 0x55, 0x55, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00 + }; + + /* create a Stipple Bitmap (for drawing CurrentSubSegment) */ + obj->wcharDisplay.stipple = + XCreateBitmapFromData(XtDisplayOfObject((Widget)obj), + RootWindowOfScreen(XtScreenOfObject((Widget)obj)), + stipple_bits, 16, 16); + + for (i = 0; i < 4; i++) { + obj->wcharDisplay.fonts[i] = obj->wcharDisplay.defaultfonts[i]; + obj->wcharDisplay.grmapping[i] = + obj->wcharDisplay.defaultmapping.grmapping[i]; + } + + obj->wcharDisplay.num_specs = class->wcharDisplay_class.num_specs; + obj->wcharDisplay.charset_specs = class->wcharDisplay_class.charset_specs; + + GetAtoms(obj); + GetGC(obj); +} + +static void +Destroy(w) +Widget w; +{ + WcharDisplayObject obj = (WcharDisplayObject)w; + + XtFree((char *)obj->wcharDisplay.fontspecs); + XtWSReleaseGCSet(w, obj->wcharDisplay.gcset_normal); + XtWSReleaseGCSet(w, obj->wcharDisplay.gcset_rev); + XFreePixmap(XtDisplayOfObject((Widget)obj), obj->wcharDisplay.stipple); +} + +/* ARGSUSED */ +static Boolean +SetValues(cur, req, wid, args, num_args) +Widget cur; +Widget req; +Widget wid; +ArgList args; +Cardinal *num_args; +{ + WcharDisplayObject old = (WcharDisplayObject)cur; + WcharDisplayObject new = (WcharDisplayObject)wid; + Boolean redraw = False; + int i; + +#define wd wcharDisplay + for (i = 0; i < 4; i++) { + if ((new->wd.defaultfonts[i] != old->wd.defaultfonts[i] || + new->wd.defaultmapping.grmapping[i] != + new->wd.defaultmapping.grmapping[i]) && + new->wd.fonts[i] == old->wd.defaultfonts[i]) { + redraw = True; + break; + } + } + if (redraw || + new->convDisplay.foreground != old->convDisplay.foreground || + new->convDisplay.background != old->convDisplay.background) { + XtWSReleaseGCSet(wid, new->wcharDisplay.gcset_normal); + XtWSReleaseGCSet(wid, new->wcharDisplay.gcset_rev); + GetGC(new); + redraw = True; + } +#undef wd + + return redraw; +} + +static void +GetAtoms(obj) +WcharDisplayObject obj; +{ + Display *dpy = XtDisplayOfObject((Widget)obj); + WDCharSet *csp; + FontSpec *fsp; + Cardinal nspecs; + char buf[128]; + char *p, *q; + int i; + String params[1]; + Cardinal num_params; + + if ((nspecs = obj->wcharDisplay.num_specs) == 0) { + params[0] = XtClass((Widget)obj)->core_class.class_name; + num_params = 1; + XtAppErrorMsg(XtWidgetToApplicationContext((Widget)obj), + "noEntry", "charSpec", "WidgetError", + "%s: has no character set spec.", + params, &num_params); + } + + csp = obj->wcharDisplay.charset_specs; + fsp = (FontSpec *)XtMalloc(sizeof(FontSpec) * obj->wcharDisplay.num_specs); + obj->wcharDisplay.fontspecs = fsp; + + for (i = 0; i < nspecs; i++, csp++, fsp++) { + p = csp->charset; + q = buf; + while (*p != '\0' && *p != '-') *q++ = *p++; + if (*p++ == '\0' || *p == '\0') { + params[0] = XtClass((Widget)obj)->core_class.class_name; + num_params = 1; + XtAppErrorMsg(XtWidgetToApplicationContext((Widget)obj), + "invalidSpec", "charSetSpec", "WidgetError", + "%s: has invalid character set spec.", + params, &num_params); + } + *q = '\0'; + fsp->registry = CachedInternAtom(dpy, buf, False); + fsp->encoding = CachedInternAtom(dpy, p, False); + } +} + +static void +GetGC(obj) +WcharDisplayObject obj; +{ + XtGCMask mask = GCFont|GCForeground|GCBackground; + XGCValues values; + int ascent, descent; + Boolean *map = obj->wcharDisplay.grmapping; + + values.function = GXcopy; + values.foreground = obj->convDisplay.foreground; + values.background = obj->convDisplay.background; + mask = GCFunction|GCForeground|GCBackground; + obj->wcharDisplay.gc_normal = XtGetGC((Widget)obj, mask, &values); + + values.foreground = obj->convDisplay.background; + values.fill_style = FillStippled; + values.stipple = obj->wcharDisplay.stipple; + mask = GCFunction|GCForeground|GCFillStyle|GCStipple; + obj->wcharDisplay.gc_stipple = XtGetGC((Widget)obj, mask, &values); + + mask = GCFont|GCFunction|GCForeground|GCBackground; + values.function = GXcopy; + values.foreground = obj->convDisplay.foreground; + values.background = obj->convDisplay.background; + obj->wcharDisplay.gcset_normal = XtWSGetGCSet((Widget)obj, mask, &values, + obj->wcharDisplay.fonts[0], + obj->wcharDisplay.fonts[1], + obj->wcharDisplay.fonts[2], + obj->wcharDisplay.fonts[3]); + values.foreground = obj->convDisplay.background; + values.background = obj->convDisplay.foreground; + obj->wcharDisplay.gcset_rev = XtWSGetGCSet((Widget)obj, mask, &values, + obj->wcharDisplay.fonts[0], + obj->wcharDisplay.fonts[1], + obj->wcharDisplay.fonts[2], + obj->wcharDisplay.fonts[3]); + + /* set font mapping */ + XWSSetMapping(obj->wcharDisplay.gcset_normal, + map[0], map[1], map[2], map[3]); + XWSSetMapping(obj->wcharDisplay.gcset_rev, + map[0], map[1], map[2], map[3]); + + XWSFontHeight(obj->wcharDisplay.gcset_normal, NULL, 0, &ascent, &descent); + obj->wcharDisplay.ascent = ascent; + obj->wcharDisplay.fontheight = ascent + descent; +} + +static void +ChangeFont(obj, fonts, mapping) +WcharDisplayObject obj; +XFontStruct **fonts; +Boolean *mapping; +{ + Boolean newgc = False; + int i; + + for (i = 0; i < 4; i++) { + if (fonts[i] != obj->wcharDisplay.fonts[i] || + mapping[i] != obj->wcharDisplay.grmapping[i]) { + obj->wcharDisplay.fonts[i] = fonts[i]; + obj->wcharDisplay.grmapping[i] = mapping[i]; + newgc = True; + } + } + if (newgc) { + XtWSReleaseGCSet((Widget)obj, obj->wcharDisplay.gcset_normal); + XtWSReleaseGCSet((Widget)obj, obj->wcharDisplay.gcset_rev); + GetGC(obj); + } +} + +static int +StringWidth(w, seg, start, end) +Widget w; +ICString *seg; +int start; +int end; +{ + WcharDisplayObject obj = (WcharDisplayObject)w; + wchar *wstr; + int len = seg->nchars; + int nctl; + int width; + + if (end < 0 || len < end) end = len; + if (start >= end || start >= len) return 0; + + wstr = (wchar *)seg->data + start; + len = end - start; + + /* + * searching for control characters -- if found, convert them + * into '^?' format for readability. + */ + if ((nctl = countControlChars(wstr, len)) == 0) { + /* no control characters */ + width = XWSTextWidth(obj->wcharDisplay.gcset_normal, wstr, len); + } else { + wchar *s = (wchar *)LOCAL_ALLOC(sizeof(wchar) * (len + nctl)); + + expandControlChars(wstr, len, s); + width = XWSTextWidth(obj->wcharDisplay.gcset_normal, s, len + nctl); + LOCAL_FREE(s); + } + return width; +} + +static int +LineHeight(w, ascentp) +Widget w; +Position *ascentp; +{ + WcharDisplayObject obj = (WcharDisplayObject)w; + + if (ascentp != NULL) *ascentp = obj->wcharDisplay.ascent; + return obj->wcharDisplay.fontheight; +} + +static void +DrawString(w, canvas, seg, start, end, x, y) +Widget w; +Widget canvas; +ICString *seg; +int start; +int end; +int x; +int y; +{ + WcharDisplayObject obj = (WcharDisplayObject)w; + wchar *wstr; + XWSGC gcset; + int len = seg->nchars; + int nctl; + Display *dpy = XtDisplay(canvas); + Window win = XtWindow(canvas); + int width; + int attr; + + if (end < 0 || len < end) end = len; + if (start >= end || start >= len) return; + + wstr = (wchar *)seg->data + start; + len = end - start; + +#define STIPPLED 1 +#define UNDERLINED 2 + + if (seg->attr == ICAttrNormalString) { + gcset = obj->wcharDisplay.gcset_normal; + attr = 0; + } else if (seg->attr & ICAttrConverted) { + /* converted segment */ + if (seg->attr & ICAttrCurrentSegment) { + gcset = obj->wcharDisplay.gcset_rev; + attr = 0; + } else if (seg->attr & ICAttrCurrentSubSegment) { + gcset = obj->wcharDisplay.gcset_rev; + attr = STIPPLED; + } else { + gcset = obj->wcharDisplay.gcset_normal; + attr = 0; + } + } else { /* ICAttrNotConverted */ + gcset = obj->wcharDisplay.gcset_normal; + attr = UNDERLINED; + } + + if ((nctl = countControlChars(wstr, len)) == 0) { + width = XWSDrawImageString(dpy, win, gcset, + x, y + obj->wcharDisplay.ascent, + wstr, len); + } else { + wchar *s = (wchar *)LOCAL_ALLOC((len + nctl) * sizeof(wchar)); + expandControlChars(wstr, len, s); + width = XWSDrawImageString(dpy, win, gcset, + x, y + obj->wcharDisplay.ascent, + s, len + nctl); + LOCAL_FREE(s); + } + + if (attr == UNDERLINED) { + int uloffset = 1; + int descent = obj->wcharDisplay.fontheight - obj->wcharDisplay.ascent; + + if (descent <= 1) { + /* font descent is 0 or 1 */ + uloffset = descent - 1; + } + XDrawLine(dpy, win, obj->wcharDisplay.gc_normal, + x, y + obj->wcharDisplay.ascent + uloffset, + x + width - 1, y + obj->wcharDisplay.ascent + uloffset); + } else if (attr == STIPPLED) { + XFillRectangle(dpy, win, obj->wcharDisplay.gc_stipple, x, y, + (unsigned int)width, + (unsigned int)obj->wcharDisplay.fontheight); + } +} + +static int +MaxChar(w, seg, start, width) +Widget w; +ICString *seg; +int start; +int width; +{ + WcharDisplayObject obj = (WcharDisplayObject)w; + XWSGC gcset = obj->wcharDisplay.gcset_normal; + wchar *sp = (wchar *)seg->data + start; + wchar *ep = (wchar *)seg->data + seg->nchars; + int cwidth; + int chars; + + chars = 0; + while (sp < ep) { + cwidth = charWidth(*sp++, gcset); + if (width < cwidth) break; + chars++; + if ((width -= cwidth) == 0) break; + } + return chars; +} + +static void +SetFonts(w, fonts, num_fonts) +Widget w; +XFontStruct **fonts; +Cardinal num_fonts; +{ + WcharDisplayObject obj = (WcharDisplayObject)w; + WDCharSet *csp = obj->wcharDisplay.charset_specs; + FontSpec *fsp = obj->wcharDisplay.fontspecs; + Cardinal nspecs = obj->wcharDisplay.num_specs; + Cardinal i, j; + XFontStruct *pickedfonts[4]; + Boolean mapping[4]; + static int csetmask[4] = { + G0LCharSet|G0RCharSet, + G1LCharSet|G1RCharSet, + G2LCharSet|G2RCharSet, + G3LCharSet|G3RCharSet, + }; + + if (num_fonts == 0) { + ChangeFont(obj, obj->wcharDisplay.defaultfonts, + obj->wcharDisplay.defaultmapping.grmapping); + return; + } + + for (i = 0; i < 4; i++) pickedfonts[i] = NULL; + + (void)_CDPickupFonts(w, fsp, nspecs, fonts, num_fonts); + +#define GRMAP (G0RCharSet|G1RCharSet|G2RCharSet|G3RCharSet) + for (j = 0; j < nspecs; j++, fsp++, csp++) { + if (fsp->font == NULL) continue; + for (i = 0; i < 4; i++) { + if (pickedfonts[i] == NULL && (csp->flag & csetmask[i])) { + pickedfonts[i] = fsp->font; + mapping[i] = (csp->flag & csetmask[i] & GRMAP) ? True : False; + } + } + } +#undef GRMAP + for (i = 0; i < 4; i++) { + if (pickedfonts[i] == NULL) { + pickedfonts[i] = obj->wcharDisplay.defaultfonts[i]; + mapping[i] = obj->wcharDisplay.defaultmapping.grmapping[i]; + } + } + + ChangeFont(obj, pickedfonts, mapping); +} + +/* countControlChars -- count number of control characters in a string */ +static int +countControlChars(wstr, len) +register wchar *wstr; +int len; +{ + register wchar *end = wstr + len; + register int n = 0; + + while (wstr < end) { + if (*wstr < 0x20 || *wstr == 0x7f) n++; + wstr++; + } + return n; +} + +/* expandControlChars -- convert control characters into '^?' format */ +static void +expandControlChars(org, orglen, res) +wchar *org; +int orglen; +wchar *res; +{ + wchar *end; + + for (end = org + orglen; org < end; org++) { + if (*org < 0x20 || *org == 0x7f) { + *res++ = '^'; + *res++ = *org ^ 0x40; + } else { + *res++ = *org; + } + } +} + +#define WITHIN_RANGE_2D(row, col, fs) \ + ((fs)->min_byte1 <= (row) && (row) <= (fs)->max_byte1 && \ + (fs)->min_char_or_byte2 <= (col) && (col) <= (fs)->max_char_or_byte2) + +#define WITHIN_RANGE(c, fs) \ + ((fs)->min_char_or_byte2 <= (c) && (c) <= (fs)->max_char_or_byte2) + +#define CHAR_INFO_2D(row, col, fs) \ + ((fs)->per_char + ((row) - (fs)->min_byte1) * \ + ((fs)->max_char_or_byte2 - (fs)->min_char_or_byte2 + 1) + \ + ((col) - (fs)->min_char_or_byte2)) + +#define CHAR_INFO(c, fs) \ + ((fs)->per_char + ((c) - (fs)->min_char_or_byte2)) + +#define CHAR_EXIST(csp) \ + ((csp)->width != 0 || ((csp)->rbearing != 0) || ((csp)->lbearing != 0)) + +static int +defaultCharWidth(font) +XFontStruct *font; +{ + int defchar = font->default_char; + + if (font->min_byte1 || font->max_byte1) { + int row = defchar >> 8; + int col = defchar & 0xff; + if (WITHIN_RANGE_2D(row, col, font)) { + if (font->per_char == NULL) { + return font->min_bounds.width; + } else { + XCharStruct *csp = CHAR_INFO_2D(row, col, font); + return CHAR_EXIST(csp) ? csp->width : 0; + } + } else { + return 0; + } + } else { + if (WITHIN_RANGE(defchar, font)) { + if (font->per_char == NULL) { + return font->min_bounds.width; + } else { + XCharStruct *csp = CHAR_INFO(defchar, font); + return CHAR_EXIST(csp) ? csp->width : 0; + } + } else { + return 0; + } + } +} + +/* charWidth -- returns width of the specified character */ +static int +charWidth(c, gcset) +register int c; +XWSGC gcset; +{ + register XFontStruct *font; + int width; + int gset; + int nonPrinting = (c < 0x20 || c == 0x7f); + + if (nonPrinting) c ^= 0x40; + + switch (c & 0x8080) { + case 0x0000: gset = 0; break; + case 0x8080: gset = 1; break; + case 0x0080: gset = 2; break; + case 0x8000: gset = 3; break; + } + + if ((font = gcset->fe[gset].font) == NULL) return 0; + + if (gcset->fe[gset].flag & GRMAPPING) { + c |= 0x8080; + } else { + c &= 0x7f7f; + } + + if (gcset->fe[gset].flag & TWOB) { + register int row = (c >> 8) & 0xff; + register int col = c & 0xff; + if (WITHIN_RANGE_2D(row, col, font)) { + if (font->per_char == NULL) { + width = font->min_bounds.width; + } else { + XCharStruct *csp = CHAR_INFO_2D(row, col, font); + + width = CHAR_EXIST(csp) ? csp->width : defaultCharWidth(font); + } + } else { + width = defaultCharWidth(font); + } + } else { + c &= 0xff; + if (WITHIN_RANGE(c, font)) { + if (font->per_char == NULL) { + width = font->min_bounds.width; + } else { + XCharStruct *csp = CHAR_INFO(c, font); + + width = CHAR_EXIST(csp) ? csp->width : defaultCharWidth(font); + } + } else { + width = defaultCharWidth(font); + } + } + if (nonPrinting) width += charWidth('^', gcset); + + return width; +} + + +/* + * jpWcharDisplay definition + * + * character set assignment for Japanese wchar: + * G0: ascii (ISO8859/1 left-half) + * G1: kanji (JISX0208) + * G2: half-width kana (JISX0201 right-half) + * G3: unused + */ + +static FontMapping jpDefaultMapping = { { False, False, True, False } }; + +#define JPFONT_ASCII "-Misc-Fixed-Medium-R-*--14-*-*-*-C-*-ISO8859-1" +#define JPFONT_KANJI "-Misc-Fixed-Medium-R-*--14-*-*-*-C-*-JISX0208.1983-0" +#define JPFONT_KANA "-Misc-Fixed-Medium-R-*--14-*-*-*-C-*-JISX0201.1976-0" + +static XtResource jpresources[] = { + /* only override superclass's default */ +#define offset(field) XtOffset(JpWcharDisplayObject, wcharDisplay.field) + { XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *), + offset(defaultfonts[0]), XtRString, JPFONT_ASCII }, + { XtNkanjiFont, XtCKanjiFont, XtRFontStruct, sizeof (XFontStruct *), + offset(defaultfonts[1]), XtRString, JPFONT_KANJI }, + { XtNkanaFont, XtCKanaFont, XtRFontStruct, sizeof (XFontStruct *), + offset(defaultfonts[2]), XtRString, JPFONT_KANA }, + { XtNfontG3, "Not.used", XtRFontStruct, sizeof (XFontStruct *), + offset(defaultfonts[3]), XtRImmediate, (XtPointer)NULL }, + { XtNfontMapping, XtCFontMapping, XtRFontMapping, sizeof (FontMapping), + offset(defaultmapping), XtRFontMapping, (XtPointer)&jpDefaultMapping }, +#undef offset +}; + +static WDCharSet jpCharSet[] = { + { "ISO8859-1", G0LCharSet }, /* my preference */ + { "JISX0201.1976-0", G0LCharSet | G2RCharSet }, + { "JISX0208.1990-0", G1LCharSet }, + { "JISX0208.1983-0", G1LCharSet }, + { "JISX0208.1978-0", G1LCharSet }, + { "JISX0208.1983-1", G1RCharSet }, + { "JISX0208.1978-1", G1RCharSet }, +#ifdef ALLOW_LOWERCASE_CHARSET_NAME + { "iso8859-1", G0LCharSet }, /* my preference */ + { "jisx0201.1976-0", G0LCharSet | G2RCharSet }, + { "jisx0208.1990-0", G1LCharSet }, + { "jisx0208.1983-0", G1LCharSet }, + { "jisx0208.1978-0", G1LCharSet }, + { "jisx0208.1983-1", G1RCharSet }, + { "jisx0208.1978-1", G1RCharSet }, +#endif +}; + +JpWcharDisplayClassRec jpWcharDisplayClassRec = { + { /* object fields */ + /* superclass */ (WidgetClass)&wcharDisplayClassRec, + /* class_name */ "JpWcharDisplay", + /* widget_size */ sizeof(JpWcharDisplayRec), + /* class_initialize */ NULL, + /* class_part_initialize */ NULL, + /* class_inited */ FALSE, + /* initialize */ NULL, + /* initialize_hook */ NULL, + /* obj1 */ NULL, + /* obj2 */ NULL, + /* obj3 */ 0, + /* resources */ jpresources, + /* num_resources */ XtNumber(jpresources), + /* xrm_class */ NULLQUARK, + /* obj4 */ FALSE, + /* obj5 */ FALSE, + /* obj6 */ FALSE, + /* obj7 */ FALSE, + /* destroy */ NULL, + /* obj8 */ NULL, + /* obj9 */ NULL, + /* set_values */ NULL, + /* set_values_hook */ NULL, + /* obj10 */ NULL, + /* get_values_hook */ NULL, + /* obj11 */ NULL, + /* version */ XtVersion, + /* callback_private */ NULL, + /* obj12 */ NULL, + /* obj13 */ NULL, + /* obj14 */ NULL, + /* extension */ NULL + }, + { /* convDisplay fields */ + /* StringWidth */ XtInheritStringWidth, + /* LineHeight */ XtInheritLineHeight, + /* DrawString */ XtInheritDrawString, + /* MaxChar */ XtInheritMaxChar, + /* DrawCursor */ XtInheritDrawCursor, + /* GetCursorBounds */ XtInheritGetCursorBounds, + /* SetFonts */ XtInheritSetFonts, + }, + { /* wcharDisplay fields */ + /* charset_specs */ jpCharSet, + /* num_specs */ XtNumber(jpCharSet), + }, + { /* jpWcharDisplay fields */ + /* empty */ 0, + }, +}; + +WidgetClass jpWcharDisplayObjectClass = (WidgetClass)&jpWcharDisplayClassRec;