upload tizen2.0 source
[framework/uifw/xorg/lib/libx11.git] / src / xlibi18n / XDefaultOMIF.c
1 /*
2 Copyright 1985, 1986, 1987, 1991, 1998  The Open Group
3
4 Permission is hereby granted, free of charge, to any person obtaining a
5 copy of this software and associated documentation files (the
6 "Software"), to deal in the Software without restriction, including
7 without limitation the rights to use, copy, modify, merge, publish,
8 distribute, sublicense, and/or sell copies of the Software, and to
9 permit persons to whom the Software is furnished to do so, subject to
10 the following conditions: The above copyright notice and this
11 permission notice shall be included in all copies or substantial
12 portions of the Software.
13
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
21 EVEN IF ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.
22
23
24 Except as contained in this notice, the name of The Open Group shall not be
25 used in advertising or otherwise to promote the sale, use or other dealings
26 in this Software without prior written authorization from The Open Group.
27
28
29 X Window System is a trademark of The Open Group
30
31 OSF/1, OSF/Motif and Motif are registered trademarks, and OSF, the OSF
32 logo, LBX, X Window System, and Xinerama are trademarks of the Open
33 Group. All other trademarks and registered trademarks mentioned herein
34 are the property of their respective owners. No right, title or
35 interest in or to any trademark, service mark, logo or trade name of
36 Sun Microsystems, Inc. or its licensors is granted.
37
38 */
39 /*
40  * Copyright 2000 Oracle and/or its affiliates. All rights reserved.
41  *
42  * Permission is hereby granted, free of charge, to any person obtaining a
43  * copy of this software and associated documentation files (the "Software"),
44  * to deal in the Software without restriction, including without limitation
45  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
46  * and/or sell copies of the Software, and to permit persons to whom the
47  * Software is furnished to do so, subject to the following conditions:
48  *
49  * The above copyright notice and this permission notice (including the next
50  * paragraph) shall be included in all copies or substantial portions of the
51  * Software.
52  *
53  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
54  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
55  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
56  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
57  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
58  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
59  * DEALINGS IN THE SOFTWARE.
60  */
61
62
63 #ifdef HAVE_CONFIG_H
64 #include <config.h>
65 #endif
66 #include "Xlibint.h"
67 #include "Xlcint.h"
68 #include "XlcPublic.h"
69 #include <X11/Xos.h>
70 #include <X11/Xatom.h>
71 #include <stdio.h>
72
73 #define MAXFONTS                100
74
75 #define XOM_GENERIC(om)         (&((XOMGeneric) om)->gen)
76 #define XOC_GENERIC(font_set)   (&((XOCGeneric) font_set)->gen)
77
78 #define DefineLocalBuf          char local_buf[BUFSIZ]
79 #define AllocLocalBuf(length)   (length > BUFSIZ ? (char *)Xmalloc(length) : local_buf)
80 #define FreeLocalBuf(ptr)       if (ptr != local_buf) Xfree(ptr)
81
82 typedef struct _FontDataRec {
83     char *name;
84 } FontDataRec, *FontData;
85
86 typedef struct _OMDataRec {
87     int font_data_count;
88     FontData font_data;
89 } OMDataRec, *OMData;
90
91 typedef struct _XOMGenericPart {
92     OMData data;
93 } XOMGenericPart;
94
95 typedef struct _XOMGenericRec {
96     XOMMethods methods;
97     XOMCoreRec core;
98     XOMGenericPart gen;
99 } XOMGenericRec, *XOMGeneric;
100
101 typedef struct _FontSetRec {
102     int id;
103     int font_data_count;
104     FontData font_data;
105     char *font_name;
106     XFontStruct *info;
107     XFontStruct *font;
108 } FontSetRec, *FontSet;
109
110 typedef struct _XOCGenericPart {
111     XlcConv wcs_to_cs;
112     FontSet font_set;
113 } XOCGenericPart;
114
115 typedef struct _XOCGenericRec {
116     XOCMethods methods;
117     XOCCoreRec core;
118     XOCGenericPart gen;
119 } XOCGenericRec, *XOCGeneric;
120
121 static Bool
122 init_fontset(
123     XOC oc)
124 {
125     XOCGenericPart *gen;
126     FontSet font_set;
127     OMData data;
128
129     data = XOM_GENERIC(oc->core.om)->data;
130
131     font_set = Xcalloc(1, sizeof(FontSetRec));
132     if (font_set == NULL)
133         return False;
134
135     gen = XOC_GENERIC(oc);
136     gen->font_set = font_set;
137
138     font_set->font_data_count = data->font_data_count;
139     font_set->font_data = data->font_data;
140
141     return True;
142 }
143
144 static char *
145 get_prop_name(
146     Display *dpy,
147     XFontStruct *fs)
148 {
149     unsigned long fp;
150
151     if (XGetFontProperty(fs, XA_FONT, &fp))
152         return XGetAtomName(dpy, fp);
153
154     return (char *) NULL;
155 }
156
157 static FontData
158 check_charset(
159     FontSet font_set,
160     char *font_name)
161 {
162     FontData font_data;
163     char *last;
164     int count;
165     ssize_t length, name_len;
166
167     name_len = strlen(font_name);
168     last = font_name + name_len;
169
170     count = font_set->font_data_count;
171     font_data = font_set->font_data;
172
173     for ( ; count-- > 0; font_data++) {
174         length = strlen(font_data->name);
175
176         if (length > name_len)
177             return(NULL);
178
179         if (_XlcCompareISOLatin1(last - length, font_data->name) == 0)
180             return font_data;
181     }
182     return (FontData) NULL;
183 }
184
185 #if 0 /* Unused */
186 static int
187 check_fontname(
188     XOC oc,
189     char *name)
190 {
191     Display *dpy = oc->core.om->core.display;
192     XOCGenericPart *gen = XOC_GENERIC(oc);
193     FontData data;
194     FontSet font_set;
195     XFontStruct *fs_list;
196     char **fn_list, *fname, *prop_fname = NULL;
197     int list_num, i;
198     int list2_num;
199     char **fn2_list = NULL;
200     int found_num = 0;
201
202     fn_list = XListFonts(dpy, name, MAXFONTS, &list_num);
203     if (fn_list == NULL)
204         return found_num;
205
206     for (i = 0; i < list_num; i++) {
207         fname = fn_list[i];
208
209         font_set = gen->font_set;
210
211         if ((data = check_charset(font_set, fname)) == NULL) {
212             if ((fn2_list = XListFontsWithInfo(dpy, name, MAXFONTS,
213                                                &list2_num, &fs_list))
214                 && (prop_fname = get_prop_name(dpy, fs_list))
215                 && (data = check_charset(font_set, prop_fname)))
216                 fname = prop_fname;
217         }
218         if (data) {
219             font_set->font_name = strdup(fname);
220             if (font_set->font_name) {
221                 found_num++;
222             }
223         }
224         if (fn2_list) {
225             XFreeFontInfo(fn2_list, fs_list, list2_num);
226             fn2_list = NULL;
227             if (prop_fname) {
228                 Xfree(prop_fname);
229                 prop_fname = NULL;
230             }
231         }
232         if (found_num == 1)
233             break;
234     }
235     XFreeFontNames(fn_list);
236     return found_num;
237 }
238 #endif
239
240 static Bool
241 load_font(
242     XOC oc)
243 {
244     Display *dpy = oc->core.om->core.display;
245     XOCGenericPart *gen = XOC_GENERIC(oc);
246     FontSet font_set = gen->font_set;
247
248     if (font_set->font_name == NULL)
249         return False;
250
251     if (font_set->font == NULL) {
252         font_set->font = XLoadQueryFont(dpy, font_set->font_name);
253         if (font_set->font == NULL)
254             return False;
255     }
256     return True;
257 }
258
259 #if 0
260 static Bool
261 load_font_info(
262     XOC oc)
263 {
264     Display *dpy = oc->core.om->core.display;
265     XOCGenericPart *gen = XOC_GENERIC(oc);
266     FontSet font_set = gen->font_set;
267     char **fn_list;
268     int fn_num;
269
270     if (font_set->font_name == NULL)
271         return False;
272
273     if (font_set->info == NULL) {
274         fn_list = XListFontsWithInfo(dpy, font_set->font_name, 1, &fn_num,
275                                      &font_set->info);
276         if (font_set->info == NULL)
277             return False;
278         if (fn_num > 0)
279             font_set->info->fid = XLoadFont(dpy, font_set->font_name);
280
281         if (fn_list) XFreeFontNames(fn_list);
282     }
283     return True;
284 }
285 #endif
286
287 static void
288 set_fontset_extents(
289     XOC oc)
290 {
291     XRectangle *ink = &oc->core.font_set_extents.max_ink_extent;
292     XRectangle *logical = &oc->core.font_set_extents.max_logical_extent;
293     XFontStruct **font_list, *font;
294     XCharStruct overall;
295     int logical_ascent, logical_descent;
296
297     font_list = oc->core.font_info.font_struct_list;
298     font = *font_list++;
299     overall = font->max_bounds;
300     overall.lbearing = font->min_bounds.lbearing;
301     logical_ascent = font->ascent;
302     logical_descent = font->descent;
303
304     ink->x = overall.lbearing;
305     ink->y = -(overall.ascent);
306     ink->width = overall.rbearing - overall.lbearing;
307     ink->height = overall.ascent + overall.descent;
308
309     logical->x = 0;
310     logical->y = -(logical_ascent);
311     logical->width = overall.width;
312     logical->height = logical_ascent + logical_descent;
313 }
314
315 static Bool
316 init_core_part(
317     XOC oc)
318 {
319     XOCGenericPart *gen = XOC_GENERIC(oc);
320     FontSet font_set;
321     XFontStruct **font_struct_list;
322     char **font_name_list, *font_name_buf;
323     int count, length;
324
325     font_set = gen->font_set;
326     count = length = 0;
327
328     if (font_set->font_name != NULL) {
329         length += strlen(font_set->font_name) + 1;
330         count++;
331     }
332     if (count == 0)
333         return False;
334
335     font_struct_list = (XFontStruct **) Xmalloc(sizeof(XFontStruct *));
336     if (font_struct_list == NULL)
337         return False;
338
339     font_name_list = (char **) Xmalloc(sizeof(char *));
340     if (font_name_list == NULL)
341         goto err;
342
343     font_name_buf = (char *) Xmalloc(length);
344     if (font_name_buf == NULL)
345         goto err;
346
347     oc->core.font_info.num_font = 1;
348     oc->core.font_info.font_name_list = font_name_list;
349     oc->core.font_info.font_struct_list = font_struct_list;
350
351     font_set = gen->font_set;
352
353     if (font_set->font_name != NULL) {
354         font_set->id = 1;
355         if (font_set->font)
356             *font_struct_list++ = font_set->font;
357         else
358             *font_struct_list++ = font_set->info;
359         strcpy(font_name_buf, font_set->font_name);
360         Xfree(font_set->font_name);
361         *font_name_list++ = font_set->font_name = font_name_buf;
362         font_name_buf += strlen(font_name_buf) + 1;
363     }
364
365     set_fontset_extents(oc);
366
367     return True;
368
369 err:
370     if (font_name_list)
371         Xfree(font_name_list);
372     Xfree(font_struct_list);
373
374     return False;
375 }
376
377 static char *
378 get_font_name(
379     XOC oc,
380     char *pattern)
381 {
382     char **list, *name;
383     int count;
384     XFontStruct *fs;
385     Display *dpy = oc->core.om->core.display;
386
387     list = XListFonts(dpy, pattern, 1, &count);
388     if (list != NULL) {
389         name = strdup(*list);
390
391         XFreeFontNames(list);
392     } else {
393         fs = XLoadQueryFont(dpy, pattern);
394         if (fs == NULL) return NULL;
395
396         name = get_prop_name(dpy, fs);
397         XFreeFont(dpy, fs);
398     }
399     return name;
400 }
401
402 static int
403 parse_fontname(
404     XOC oc)
405 {
406     XOCGenericPart *gen = XOC_GENERIC(oc);
407     FontSet font_set;
408     FontData font_data;
409     char *pattern, *last, buf[BUFSIZ];
410     int font_data_count, found_num = 0;
411     ssize_t length;
412     int count, num_fields;
413     char *base_name, *font_name, **name_list, **cur_name_list;
414     char *charset_p = NULL;
415     Bool append_charset;
416     /*
417        append_charset flag should be set to True when the XLFD fontname
418        doesn't contain a chaset part.
419      */
420
421     name_list = _XParseBaseFontNameList(oc->core.base_name_list, &count);
422     if (name_list == NULL)
423         return -1;
424     cur_name_list = name_list;
425
426     while (count-- > 0) {
427         pattern = *cur_name_list++;
428         if (pattern == NULL || *pattern == '\0')
429             continue;
430
431         append_charset = False;
432
433         if (strchr(pattern, '*') == NULL &&
434             (font_name = get_font_name(oc, pattern))) {
435
436             font_set = gen->font_set;
437
438             font_data = check_charset(font_set, font_name);
439             if (font_data == NULL) {
440                 Display *dpy = oc->core.om->core.display;
441                 char **fn_list = NULL, *prop_fname = NULL;
442                 int list_num;
443                 XFontStruct *fs_list;
444                 if ((fn_list = XListFontsWithInfo(dpy, font_name,
445                                                   MAXFONTS,
446                                                   &list_num, &fs_list))
447                     && (prop_fname = get_prop_name(dpy, fs_list))
448                     && (font_data = check_charset(font_set, prop_fname))) {
449                     if (fn_list) {
450                         XFreeFontInfo(fn_list, fs_list, list_num);
451                         fn_list = NULL;
452                     }
453                     font_name = prop_fname;
454                 }
455             }
456             if (font_data == NULL)
457                 continue;
458
459             font_set->font_name = strdup(font_name);
460             Xfree(font_name);
461             if (font_set->font_name == NULL) {
462                 goto err;
463             }
464             found_num++;
465             goto found;
466         }
467 /*
468 1266793
469 Limit the length of the string copy to prevent stack corruption.
470         strcpy(buf, pattern);
471 */
472         strncpy(buf, pattern, BUFSIZ);
473         buf[BUFSIZ-1] = '\0';
474         length = strlen(buf);
475         last = buf + length - 1;
476
477         for (num_fields = 0, base_name = buf; *base_name != '\0'; base_name++)
478             if (*base_name == '-') num_fields++;
479         if (strchr(pattern, '*') == NULL) {
480             if (num_fields == 12) {
481                 append_charset = True;
482                 *++last = '-';
483                 last++;
484             } else
485                 continue;
486         } else {
487             if (num_fields == 13 || num_fields == 14) {
488             /*
489              * There are 14 fields in an XLFD name -- make certain the
490              * charset (& encoding) is placed in the correct field.
491              */
492                 append_charset = True;
493                 last = strrchr (buf, '-');
494                 if (num_fields == 14) {
495                     *last = '\0';
496                     last = strrchr (buf, '-');
497                 }
498                 last++;
499             } else if (*last == '*') {
500                 append_charset = True;
501                 if (length > 3 && *(last-3) == '-' && *(last-2) == '*'
502                     && *(last-1) == '-') {
503                     last -= 2;
504                 }
505                 *++last = '-';
506                 last++;
507             } else {
508                 last = strrchr (buf, '-');
509                 charset_p = last;
510                 charset_p = strrchr (buf, '-');
511                 while (*(--charset_p) != '-');
512                 charset_p++;
513             }
514         }
515
516         font_set = gen->font_set;
517
518         font_data = font_set->font_data;
519         font_data_count = font_set->font_data_count;
520         for ( ; font_data_count-- > 0; font_data++) {
521             if (append_charset)
522                 {
523 /*
524 1266793
525 Limit the length of the string copy to prevent stack corruption.
526                 strcpy(last, font_data->name);
527 */
528                 strncpy(last, font_data->name, BUFSIZ - length);
529                 buf[BUFSIZ-1] = '\0';
530                 }
531             else {
532                 if (_XlcCompareISOLatin1(charset_p,
533                                          font_data->name)) {
534                     continue;
535                 }
536             }
537             if ((font_set->font_name = get_font_name(oc, buf)))
538                 break;
539         }
540         if (font_set->font_name != NULL) {
541             found_num++;
542             goto found;
543         }
544     }
545   found:
546     base_name = strdup(oc->core.base_name_list);
547     if (base_name == NULL)
548         goto err;
549
550     oc->core.base_name_list = base_name;
551
552     XFreeStringList(name_list);
553
554     return found_num;
555 err:
556     XFreeStringList(name_list);
557
558     return -1;
559 }
560
561 static Bool
562 set_missing_list(
563     XOC oc)
564 {
565     XOCGenericPart *gen = XOC_GENERIC(oc);
566     FontSet font_set;
567     char **charset_list, *charset_buf;
568     int count, length;
569
570     font_set = gen->font_set;
571     count = length = 0;
572
573     if (!font_set->info && !font_set->font) {
574         length += strlen(font_set->font_data->name) + 1;
575         count++;
576     }
577
578     if (count == 0)
579         return True;
580
581     charset_list = (char **) Xmalloc(sizeof(char *));
582     if (charset_list == NULL)
583         return False;
584
585     charset_buf = (char *) Xmalloc(length);
586     if (charset_buf == NULL) {
587         Xfree(charset_list);
588         return False;
589     }
590
591     oc->core.missing_list.charset_list = charset_list;
592
593     font_set = gen->font_set;
594
595     if (!font_set->info && !font_set->font) {
596         strcpy(charset_buf, font_set->font_data->name);
597         *charset_list++ = charset_buf;
598         charset_buf += strlen(charset_buf) + 1;
599     }
600     return True;
601 }
602
603 static Bool
604 create_fontset(
605     XOC oc)
606 {
607     int found_num;
608
609     if (init_fontset(oc) == False)
610         return False;
611
612     found_num = parse_fontname(oc);
613     if (found_num <= 0) {
614         if (found_num == 0)
615             set_missing_list(oc);
616         return False;
617     }
618
619     if (load_font(oc) == False)
620         return False;
621
622     if (init_core_part(oc) == False)
623         return False;
624
625     if (set_missing_list(oc) == False)
626         return False;
627
628     return True;
629 }
630
631 static void
632 destroy_oc(
633     XOC oc)
634 {
635     Display *dpy = oc->core.om->core.display;
636     XOCGenericPart *gen = XOC_GENERIC(oc);
637     XFontStruct **font_list, *font;
638
639     if (gen->font_set)
640         Xfree(gen->font_set);
641
642     if (oc->core.base_name_list)
643         Xfree(oc->core.base_name_list);
644
645     if (oc->core.font_info.font_name_list)
646         XFreeStringList(oc->core.font_info.font_name_list);
647
648     if ((font_list = oc->core.font_info.font_struct_list)) {
649         if ((font = *font_list)) {
650             if (font->fid)
651                 XFreeFont(dpy, font);
652             else
653                 XFreeFontInfo(NULL, font, 1);
654         }
655         Xfree(oc->core.font_info.font_struct_list);
656     }
657
658     if (oc->core.missing_list.charset_list)
659         XFreeStringList(oc->core.missing_list.charset_list);
660
661 #ifdef notdef
662     if (oc->core.res_name)
663         Xfree(oc->core.res_name);
664     if (oc->core.res_class)
665         Xfree(oc->core.res_class);
666 #endif
667
668     Xfree(oc);
669 }
670
671 static char *
672 set_oc_values(
673     XOC oc,
674     XlcArgList args,
675     int num_args)
676 {
677     if (oc->core.resources == NULL)
678         return NULL;
679
680     return _XlcSetValues((XPointer) oc, oc->core.resources,
681                          oc->core.num_resources, args, num_args, XlcSetMask);
682 }
683
684 static char *
685 get_oc_values(
686     XOC oc,
687     XlcArgList args,
688     int num_args)
689 {
690     if (oc->core.resources == NULL)
691         return NULL;
692
693     return _XlcGetValues((XPointer) oc, oc->core.resources,
694                          oc->core.num_resources, args, num_args, XlcGetMask);
695 }
696
697 static Bool
698 wcs_to_mbs(
699     XOC oc,
700     char *to,
701     _Xconst wchar_t *from,
702     int length)
703 {
704     XlcConv conv = XOC_GENERIC(oc)->wcs_to_cs;
705     XLCd lcd;
706     int ret, to_left = length;
707
708     if (conv == NULL) {
709         lcd = oc->core.om->core.lcd;
710         conv = _XlcOpenConverter(lcd, XlcNWideChar, lcd, XlcNMultiByte);
711         if (conv == NULL)
712             return False;
713         XOC_GENERIC(oc)->wcs_to_cs = conv;
714     } else
715         _XlcResetConverter(conv);
716
717     ret = _XlcConvert(conv, (XPointer *) &from, &length, (XPointer *) &to,
718                       &to_left, NULL, 0);
719     if (ret != 0 || length > 0)
720         return False;
721
722     return True;
723 }
724
725 static int
726 _XmbDefaultTextEscapement(XOC oc, _Xconst char *text, int length)
727 {
728     return XTextWidth(*oc->core.font_info.font_struct_list, text, length);
729 }
730
731 static int
732 _XwcDefaultTextEscapement(XOC oc, _Xconst wchar_t *text, int length)
733 {
734     DefineLocalBuf;
735     char *buf = AllocLocalBuf(length);
736     int ret = 0;
737
738     if (buf == NULL)
739         return 0;
740
741     if (wcs_to_mbs(oc, buf, text, length) == False)
742         goto err;
743
744     ret = _XmbDefaultTextEscapement(oc, buf, length);
745
746 err:
747     FreeLocalBuf(buf);
748
749     return ret;
750 }
751
752 static int
753 _XmbDefaultTextExtents(XOC oc, _Xconst char *text, int length,
754                        XRectangle *overall_ink, XRectangle *overall_logical)
755 {
756     int direction, logical_ascent, logical_descent;
757     XCharStruct overall;
758
759     XTextExtents(*oc->core.font_info.font_struct_list, text, length, &direction,
760                  &logical_ascent, &logical_descent, &overall);
761
762     if (overall_ink) {
763         overall_ink->x = overall.lbearing;
764         overall_ink->y = -(overall.ascent);
765         overall_ink->width = overall.rbearing - overall.lbearing;
766         overall_ink->height = overall.ascent + overall.descent;
767     }
768
769     if (overall_logical) {
770         overall_logical->x = 0;
771         overall_logical->y = -(logical_ascent);
772         overall_logical->width = overall.width;
773         overall_logical->height = logical_ascent + logical_descent;
774     }
775
776     return overall.width;
777 }
778
779 static int
780 _XwcDefaultTextExtents(XOC oc, _Xconst wchar_t *text, int length,
781                        XRectangle *overall_ink, XRectangle *overall_logical)
782 {
783     DefineLocalBuf;
784     char *buf = AllocLocalBuf(length);
785     int ret = 0;
786
787     if (buf == NULL)
788         return 0;
789
790     if (wcs_to_mbs(oc, buf, text, length) == False)
791         goto err;
792
793     ret = _XmbDefaultTextExtents(oc, buf, length, overall_ink, overall_logical);
794
795 err:
796     FreeLocalBuf(buf);
797
798     return ret;
799 }
800
801 static Status
802 _XmbDefaultTextPerCharExtents(XOC oc, _Xconst char *text, int length,
803                               XRectangle *ink_buf, XRectangle *logical_buf,
804                               int buf_size, int *num_chars,
805                               XRectangle *overall_ink,
806                               XRectangle *overall_logical)
807 {
808     XFontStruct *font = *oc->core.font_info.font_struct_list;
809     XCharStruct *def, *cs, overall;
810     Bool first = True;
811
812     if (buf_size < length)
813         return 0;
814
815     bzero((char *) &overall, sizeof(XCharStruct));
816     *num_chars = 0;
817
818     CI_GET_DEFAULT_INFO_1D(font, def)
819
820     while (length-- > 0) {
821         CI_GET_CHAR_INFO_1D(font, *text, def, cs)
822         text++;
823         if (cs == NULL)
824             continue;
825
826         ink_buf->x = overall.width + cs->lbearing;
827         ink_buf->y = -(cs->ascent);
828         ink_buf->width = cs->rbearing - cs->lbearing;
829         ink_buf->height = cs->ascent + cs->descent;
830         ink_buf++;
831
832         logical_buf->x = overall.width;
833         logical_buf->y = -(font->ascent);
834         logical_buf->width = cs->width;
835         logical_buf->height = font->ascent + font->descent;
836         logical_buf++;
837
838         if (first) {
839             overall = *cs;
840             first = False;
841         } else {
842             overall.ascent = max(overall.ascent, cs->ascent);
843             overall.descent = max(overall.descent, cs->descent);
844             overall.lbearing = min(overall.lbearing, overall.width +
845                                    cs->lbearing);
846             overall.rbearing = max(overall.rbearing, overall.width +
847                                    cs->rbearing);
848             overall.width += cs->width;
849         }
850         (*num_chars)++;
851     }
852
853     if (overall_ink) {
854         overall_ink->x = overall.lbearing;
855         overall_ink->y = -(overall.ascent);
856         overall_ink->width = overall.rbearing - overall.lbearing;
857         overall_ink->height = overall.ascent + overall.descent;
858     }
859
860     if (overall_logical) {
861         overall_logical->x = 0;
862         overall_logical->y = -(font->ascent);
863         overall_logical->width = overall.width;
864         overall_logical->height = font->ascent + font->descent;
865     }
866
867     return 1;
868 }
869
870 static Status
871 _XwcDefaultTextPerCharExtents(XOC oc, _Xconst wchar_t *text, int length,
872                               XRectangle *ink_buf, XRectangle *logical_buf,
873                               int buf_size, int *num_chars,
874                               XRectangle *overall_ink,
875                               XRectangle *overall_logical)
876 {
877     DefineLocalBuf;
878     char *buf = AllocLocalBuf(length);
879     Status ret = 0;
880
881     if (buf == NULL)
882         return 0;
883
884     if (wcs_to_mbs(oc, buf, text, length) == False)
885         goto err;
886
887     ret = _XmbDefaultTextPerCharExtents(oc, buf, length, ink_buf, logical_buf,
888                                         buf_size, num_chars, overall_ink,
889                                         overall_logical);
890
891 err:
892     FreeLocalBuf(buf);
893
894     return ret;
895 }
896
897 static int
898 _XmbDefaultDrawString(Display *dpy, Drawable d, XOC oc, GC gc, int x, int y,
899                       _Xconst char *text, int length)
900 {
901     XFontStruct *font = *oc->core.font_info.font_struct_list;
902
903     XSetFont(dpy, gc, font->fid);
904     XDrawString(dpy, d, gc, x, y, text, length);
905
906     return XTextWidth(font, text, length);
907 }
908
909 static int
910 _XwcDefaultDrawString(Display *dpy, Drawable d, XOC oc, GC gc, int x, int y,
911                       _Xconst wchar_t *text, int length)
912 {
913     DefineLocalBuf;
914     char *buf = AllocLocalBuf(length);
915     int ret = 0;
916
917     if (buf == NULL)
918         return 0;
919
920     if (wcs_to_mbs(oc, buf, text, length) == False)
921         goto err;
922
923     ret = _XmbDefaultDrawString(dpy, d, oc, gc, x, y, buf, length);
924
925 err:
926     FreeLocalBuf(buf);
927
928     return ret;
929 }
930
931 static void
932 _XmbDefaultDrawImageString(Display *dpy, Drawable d, XOC oc, GC gc, int x,
933                            int y, _Xconst char *text, int length)
934 {
935     XSetFont(dpy, gc, (*oc->core.font_info.font_struct_list)->fid);
936     XDrawImageString(dpy, d, gc, x, y, text, length);
937 }
938
939 static void
940 _XwcDefaultDrawImageString(Display *dpy, Drawable d, XOC oc, GC gc, int x,
941                            int y, _Xconst wchar_t *text, int length)
942 {
943     DefineLocalBuf;
944     char *buf = AllocLocalBuf(length);
945
946     if (buf == NULL)
947         return;
948
949     if (wcs_to_mbs(oc, buf, text, length) == False)
950         goto err;
951
952     _XmbDefaultDrawImageString(dpy, d, oc, gc, x, y, buf, length);
953
954 err:
955     FreeLocalBuf(buf);
956 }
957
958 static _Xconst XOCMethodsRec oc_default_methods = {
959     destroy_oc,
960     set_oc_values,
961     get_oc_values,
962     _XmbDefaultTextEscapement,
963     _XmbDefaultTextExtents,
964     _XmbDefaultTextPerCharExtents,
965     _XmbDefaultDrawString,
966     _XmbDefaultDrawImageString,
967     _XwcDefaultTextEscapement,
968     _XwcDefaultTextExtents,
969     _XwcDefaultTextPerCharExtents,
970     _XwcDefaultDrawString,
971     _XwcDefaultDrawImageString
972 };
973
974 static XlcResource oc_resources[] = {
975     { XNBaseFontName, NULLQUARK, sizeof(char *),
976       XOffsetOf(XOCRec, core.base_name_list), XlcCreateMask | XlcGetMask },
977     { XNOMAutomatic, NULLQUARK, sizeof(Bool),
978       XOffsetOf(XOCRec, core.om_automatic), XlcGetMask },
979     { XNMissingCharSet, NULLQUARK, sizeof(XOMCharSetList),
980       XOffsetOf(XOCRec, core.missing_list), XlcGetMask },
981     { XNDefaultString, NULLQUARK, sizeof(char *),
982       XOffsetOf(XOCRec, core.default_string), XlcGetMask },
983     { XNOrientation, NULLQUARK, sizeof(XOrientation),
984       XOffsetOf(XOCRec, core.orientation), XlcSetMask | XlcGetMask },
985     { XNResourceName, NULLQUARK, sizeof(char *),
986       XOffsetOf(XOCRec, core.res_name), XlcSetMask | XlcGetMask },
987     { XNResourceClass, NULLQUARK, sizeof(char *),
988       XOffsetOf(XOCRec, core.res_class), XlcSetMask | XlcGetMask },
989     { XNFontInfo, NULLQUARK, sizeof(XOMFontInfo),
990       XOffsetOf(XOCRec, core.font_info), XlcGetMask }
991 };
992
993 static XOC
994 create_oc(
995     XOM om,
996     XlcArgList args,
997     int num_args)
998 {
999     XOC oc;
1000
1001     oc = Xcalloc(1, sizeof(XOCGenericRec));
1002     if (oc == NULL)
1003         return (XOC) NULL;
1004
1005     oc->core.om = om;
1006
1007     if (oc_resources[0].xrm_name == NULLQUARK)
1008         _XlcCompileResourceList(oc_resources, XlcNumber(oc_resources));
1009
1010     if (_XlcSetValues((XPointer) oc, oc_resources, XlcNumber(oc_resources),
1011                       args, num_args, XlcCreateMask | XlcDefaultMask))
1012         goto err;
1013
1014     if (oc->core.base_name_list == NULL)
1015         goto err;
1016
1017     oc->core.resources = oc_resources;
1018     oc->core.num_resources = XlcNumber(oc_resources);
1019
1020     if (create_fontset(oc) == False)
1021         goto err;
1022
1023     oc->methods = (XOCMethods)&oc_default_methods;
1024
1025     return oc;
1026
1027 err:
1028     destroy_oc(oc);
1029
1030     return (XOC) NULL;
1031 }
1032
1033 static Status
1034 close_om(
1035     XOM om)
1036 {
1037     XOMGenericPart *gen = XOM_GENERIC(om);
1038     OMData data;
1039     FontData font_data;
1040     int count;
1041
1042     if ((data = gen->data)) {
1043         if (data->font_data) {
1044           for (font_data = data->font_data, count = data->font_data_count;
1045                count-- > 0 ; font_data++) {
1046             if (font_data->name)
1047                 Xfree(font_data->name);
1048           }
1049           Xfree(data->font_data);
1050         }
1051         Xfree(gen->data);
1052     }
1053
1054     if (om->core.res_name)
1055         Xfree(om->core.res_name);
1056     if (om->core.res_class)
1057         Xfree(om->core.res_class);
1058     if (om->core.required_charset.charset_list)
1059         XFreeStringList(om->core.required_charset.charset_list);
1060     else
1061         Xfree((char*)om->core.required_charset.charset_list);
1062     if (om->core.orientation_list.orientation)
1063         Xfree(om->core.orientation_list.orientation);
1064
1065     Xfree(om);
1066
1067     return 1;
1068 }
1069
1070 static char *
1071 set_om_values(
1072     XOM om,
1073     XlcArgList args,
1074     int num_args)
1075 {
1076     if (om->core.resources == NULL)
1077         return NULL;
1078
1079     return _XlcSetValues((XPointer) om, om->core.resources,
1080                          om->core.num_resources, args, num_args, XlcSetMask);
1081 }
1082
1083 static char *
1084 get_om_values(
1085     XOM om,
1086     XlcArgList args,
1087     int num_args)
1088 {
1089     if (om->core.resources == NULL)
1090         return NULL;
1091
1092     return _XlcGetValues((XPointer) om, om->core.resources,
1093                          om->core.num_resources, args, num_args, XlcGetMask);
1094 }
1095
1096 static _Xconst XOMMethodsRec methods = {
1097     close_om,
1098     set_om_values,
1099     get_om_values,
1100     create_oc
1101 };
1102
1103 static XlcResource om_resources[] = {
1104     { XNRequiredCharSet, NULLQUARK, sizeof(XOMCharSetList),
1105       XOffsetOf(XOMRec, core.required_charset), XlcGetMask },
1106     { XNQueryOrientation, NULLQUARK, sizeof(XOMOrientation),
1107       XOffsetOf(XOMRec, core.orientation_list), XlcGetMask },
1108     { XNDirectionalDependentDrawing, NULLQUARK, sizeof(Bool),
1109       XOffsetOf(XOMRec, core.directional_dependent), XlcGetMask },
1110     { XNContextualDrawing, NULLQUARK, sizeof(Bool),
1111       XOffsetOf(XOMRec, core.contextual_drawing), XlcGetMask }
1112 };
1113
1114 static OMData
1115 add_data(
1116     XOM om)
1117 {
1118     XOMGenericPart *gen = XOM_GENERIC(om);
1119     OMData new;
1120
1121     new = Xcalloc(1, sizeof(OMDataRec));
1122
1123     if (new == NULL)
1124         return NULL;
1125
1126     gen->data = new;
1127
1128     return new;
1129 }
1130
1131 static _Xconst char *supported_charset_list[] = {
1132     "ISO8859-1",
1133 /* fix for bug4332979 */
1134     "adobe-fontspecific",
1135 /* fix for bug4237353: "JISX0201.1976-0" entry should be removed from
1136    supported_charset_list because it is not a supported_charset for C locale
1137     "JISX0201.1976-0", */
1138     "SUNOLCURSOR-1",
1139     "SUNOLGLYPH-1"
1140 };
1141
1142 static Bool
1143 init_om(
1144     XOM om)
1145 {
1146     XOMGenericPart *gen = XOM_GENERIC(om);
1147     OMData data;
1148     FontData font_data;
1149     char **required_list;
1150     XOrientation *orientation;
1151     char **value, buf[BUFSIZ], *bufptr;
1152     int count, length = 0;
1153
1154     value = (char**)supported_charset_list;
1155     count = XlcNumber(supported_charset_list);
1156
1157     data = add_data(om);
1158     if (data == NULL)
1159         return False;
1160
1161     font_data = Xcalloc(count, sizeof(FontDataRec));
1162     if (font_data == NULL)
1163         return False;
1164     data->font_data = font_data;
1165     data->font_data_count = count;
1166
1167     for ( ; count-- > 0; font_data++) {
1168 /*
1169 1266793
1170 This one is fine.  *value points to one of the local strings in
1171 supported_charset_list[].
1172 */
1173         strcpy(buf, *value++);
1174         font_data->name = strdup(buf);
1175         if (font_data->name == NULL)
1176             return False;
1177     }
1178
1179     length += strlen(data->font_data->name) + 1;
1180
1181     /* required charset list */
1182     required_list = (char **) Xmalloc(sizeof(char *));
1183     if (required_list == NULL)
1184         return False;
1185
1186     bufptr = (char *) Xmalloc(length);
1187     if (bufptr == NULL) {
1188         Xfree(required_list);
1189         return False;
1190     }
1191
1192     om->core.required_charset.charset_list = required_list;
1193     om->core.required_charset.charset_count = 1; /* always 1 */
1194
1195     data = gen->data;
1196
1197     strcpy(bufptr, data->font_data->name);
1198     *required_list++ = bufptr;
1199     bufptr += strlen(bufptr) + 1;
1200
1201     /* orientation list */
1202     orientation = (XOrientation *) Xmalloc(sizeof(XOrientation));
1203     if (orientation == NULL)
1204         return False;
1205
1206     *orientation = XOMOrientation_LTR_TTB;
1207     om->core.orientation_list.orientation = orientation;
1208     om->core.orientation_list.num_orientation = 1;
1209
1210     /* directional dependent drawing */
1211     om->core.directional_dependent = False;
1212
1213     /* contexual drawing */
1214     om->core.contextual_drawing = False;
1215
1216     /* context dependent */
1217     om->core.context_dependent = False;
1218
1219     return True;
1220 }
1221
1222 XOM
1223 _XDefaultOpenOM(XLCd lcd, Display *dpy, XrmDatabase rdb,
1224                 _Xconst char *res_name, _Xconst char *res_class)
1225 {
1226     XOM om;
1227
1228     om = Xcalloc(1, sizeof(XOMGenericRec));
1229     if (om == NULL)
1230         return (XOM) NULL;
1231
1232     om->methods = (XOMMethods)&methods;
1233     om->core.lcd = lcd;
1234     om->core.display = dpy;
1235     om->core.rdb = rdb;
1236     if (res_name) {
1237         om->core.res_name = strdup(res_name);
1238         if (om->core.res_name == NULL)
1239             goto err;
1240     }
1241     if (res_class) {
1242         om->core.res_class = strdup(res_class);
1243         if (om->core.res_class == NULL)
1244             goto err;
1245     }
1246
1247     if (om_resources[0].xrm_name == NULLQUARK)
1248         _XlcCompileResourceList(om_resources, XlcNumber(om_resources));
1249
1250     om->core.resources = om_resources;
1251     om->core.num_resources = XlcNumber(om_resources);
1252
1253     if (init_om(om) == False)
1254         goto err;
1255
1256     return om;
1257 err:
1258     close_om(om);
1259
1260     return (XOM) NULL;
1261 }