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 ? 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
init_fontset(XOC oc)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 *
get_prop_name(Display * dpy,XFontStruct * fs)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
check_charset(FontSet font_set,char * font_name)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 = (ssize_t) 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 = (ssize_t) 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 static Bool
load_font(XOC oc)186 load_font(
187     XOC oc)
188 {
189     Display *dpy = oc->core.om->core.display;
190     XOCGenericPart *gen = XOC_GENERIC(oc);
191     FontSet font_set = gen->font_set;
192 
193     if (font_set->font_name == NULL)
194 	return False;
195 
196     if (font_set->font == NULL) {
197 	font_set->font = XLoadQueryFont(dpy, font_set->font_name);
198 	if (font_set->font == NULL)
199 	    return False;
200     }
201     return True;
202 }
203 
204 static void
set_fontset_extents(XOC oc)205 set_fontset_extents(
206     XOC oc)
207 {
208     XRectangle *ink = &oc->core.font_set_extents.max_ink_extent;
209     XRectangle *logical = &oc->core.font_set_extents.max_logical_extent;
210     XFontStruct **font_list, *font;
211     XCharStruct overall;
212     int logical_ascent, logical_descent;
213 
214     font_list = oc->core.font_info.font_struct_list;
215     font = *font_list++;
216     overall = font->max_bounds;
217     overall.lbearing = font->min_bounds.lbearing;
218     logical_ascent = font->ascent;
219     logical_descent = font->descent;
220 
221     ink->x = overall.lbearing;
222     ink->y = -(overall.ascent);
223     ink->width = overall.rbearing - overall.lbearing;
224     ink->height = overall.ascent + overall.descent;
225 
226     logical->x = 0;
227     logical->y = -(logical_ascent);
228     logical->width = overall.width;
229     logical->height = logical_ascent + logical_descent;
230 }
231 
232 static Bool
init_core_part(XOC oc)233 init_core_part(
234     XOC oc)
235 {
236     XOCGenericPart *gen = XOC_GENERIC(oc);
237     FontSet font_set;
238     XFontStruct **font_struct_list;
239     char **font_name_list, *font_name_buf;
240 
241     font_set = gen->font_set;
242 
243     if (font_set->font_name == NULL)
244         return False;
245 
246     font_struct_list = Xmalloc(sizeof(XFontStruct *));
247     if (font_struct_list == NULL)
248 	return False;
249 
250     font_name_list = Xmalloc(sizeof(char *));
251     if (font_name_list == NULL)
252 	goto err;
253 
254     font_name_buf = strdup(font_set->font_name);
255     if (font_name_buf == NULL)
256 	goto err;
257 
258     oc->core.font_info.num_font = 1;
259     oc->core.font_info.font_name_list = font_name_list;
260     oc->core.font_info.font_struct_list = font_struct_list;
261 
262     font_set->id = 1;
263     if (font_set->font)
264         *font_struct_list = font_set->font;
265     else
266         *font_struct_list = font_set->info;
267     Xfree(font_set->font_name);
268     *font_name_list = font_set->font_name = font_name_buf;
269 
270     set_fontset_extents(oc);
271 
272     return True;
273 
274 err:
275 
276     Xfree(font_name_list);
277     Xfree(font_struct_list);
278 
279     return False;
280 }
281 
282 static char *
get_font_name(XOC oc,char * pattern)283 get_font_name(
284     XOC oc,
285     char *pattern)
286 {
287     char **list, *name;
288     int count;
289     XFontStruct *fs;
290     Display *dpy = oc->core.om->core.display;
291 
292     list = XListFonts(dpy, pattern, 1, &count);
293     if (list != NULL) {
294 	name = strdup(*list);
295 
296 	XFreeFontNames(list);
297     } else {
298 	fs = XLoadQueryFont(dpy, pattern);
299 	if (fs == NULL) return NULL;
300 
301 	name = get_prop_name(dpy, fs);
302 	XFreeFont(dpy, fs);
303     }
304     return name;
305 }
306 
307 static int
parse_fontname(XOC oc)308 parse_fontname(
309     XOC oc)
310 {
311     XOCGenericPart *gen = XOC_GENERIC(oc);
312     FontSet font_set;
313     FontData font_data;
314     char *pattern, *last, buf[BUFSIZ];
315     int font_data_count, found_num = 0;
316     ssize_t length;
317     int count, num_fields;
318     char *base_name, *font_name, **name_list, **cur_name_list;
319     char *charset_p = NULL;
320     Bool append_charset;
321     /*
322        append_charset flag should be set to True when the XLFD fontname
323        doesn't contain a chaset part.
324      */
325 
326     name_list = _XParseBaseFontNameList(oc->core.base_name_list, &count);
327     if (name_list == NULL)
328 	return -1;
329     cur_name_list = name_list;
330 
331     while (count-- > 0) {
332         pattern = *cur_name_list++;
333 	if (pattern == NULL || *pattern == '\0')
334 	    continue;
335 
336 	append_charset = False;
337 
338 	if (strchr(pattern, '*') == NULL &&
339 	    (font_name = get_font_name(oc, pattern))) {
340 
341 	    font_set = gen->font_set;
342 
343 	    font_data = check_charset(font_set, font_name);
344 	    if (font_data == NULL) {
345 		Display *dpy = oc->core.om->core.display;
346 		char **fn_list = NULL, *prop_fname = NULL;
347 		int list_num;
348 		XFontStruct *fs_list;
349 		if ((fn_list = XListFontsWithInfo(dpy, font_name,
350 						  MAXFONTS,
351 						  &list_num, &fs_list))
352 		    && (prop_fname = get_prop_name(dpy, fs_list))
353 		    && (font_data = check_charset(font_set, prop_fname))) {
354 		    if (fn_list) {
355 			XFreeFontInfo(fn_list, fs_list, list_num);
356 			fn_list = NULL;
357 		    }
358 		    font_name = prop_fname;
359 		}
360 	    }
361 	    if (font_data == NULL)
362 		continue;
363 
364 	    font_set->font_name = strdup(font_name);
365 	    Xfree(font_name);
366 	    if (font_set->font_name == NULL) {
367 		goto err;
368 	    }
369 	    found_num++;
370 	    goto found;
371 	}
372 
373 	strncpy(buf, pattern, BUFSIZ);
374 	buf[BUFSIZ-1] = '\0';
375 	length = (ssize_t) strlen(buf);
376 	last = buf + length - 1;
377 
378 	for (num_fields = 0, base_name = buf; *base_name != '\0'; base_name++)
379 	    if (*base_name == '-') num_fields++;
380 	if (strchr(pattern, '*') == NULL) {
381 	    if (num_fields == 12) {
382 		append_charset = True;
383 		*++last = '-';
384 		last++;
385 	    } else
386 		continue;
387 	} else {
388 	    if (num_fields == 13 || num_fields == 14) {
389 	    /*
390 	     * There are 14 fields in an XLFD name -- make certain the
391 	     * charset (& encoding) is placed in the correct field.
392 	     */
393 		append_charset = True;
394 		last = strrchr (buf, '-');
395 		if (num_fields == 14) {
396 		    *last = '\0';
397 		    last = strrchr (buf, '-');
398 		}
399 		last++;
400 	    } else if (*last == '*') {
401 		append_charset = True;
402 		if (length > 3 && *(last-3) == '-' && *(last-2) == '*'
403 		    && *(last-1) == '-') {
404 		    last -= 2;
405 		}
406 		*++last = '-';
407 		last++;
408 	    } else {
409 		last = strrchr (buf, '-');
410 		charset_p = last;
411 		charset_p = strrchr (buf, '-');
412 		while (*(--charset_p) != '-');
413 		charset_p++;
414 	    }
415 	}
416 
417 	font_set = gen->font_set;
418 
419 	font_data = font_set->font_data;
420 	font_data_count = font_set->font_data_count;
421 	for ( ; font_data_count-- > 0; font_data++) {
422 	    if (append_charset)
423 		{
424 		strncpy(last, font_data->name, (size_t) (BUFSIZ - length));
425 		buf[BUFSIZ-1] = '\0';
426 		}
427 	    else {
428 		if (_XlcCompareISOLatin1(charset_p,
429 					 font_data->name)) {
430 		    continue;
431 		}
432 	    }
433 	    if ((font_set->font_name = get_font_name(oc, buf)))
434 		break;
435 	}
436 	if (font_set->font_name != NULL) {
437 	    found_num++;
438 	    goto found;
439 	}
440     }
441   found:
442     base_name = strdup(oc->core.base_name_list);
443     if (base_name == NULL)
444 	goto err;
445 
446     oc->core.base_name_list = base_name;
447 
448     XFreeStringList(name_list);
449 
450     return found_num;
451 err:
452     XFreeStringList(name_list);
453 
454     return -1;
455 }
456 
457 static Bool
set_missing_list(XOC oc)458 set_missing_list(
459     XOC oc)
460 {
461     XOCGenericPart *gen = XOC_GENERIC(oc);
462     FontSet font_set;
463     char **charset_list, *charset_buf;
464 
465     font_set = gen->font_set;
466 
467     if (font_set->info == NULL || font_set->font == NULL)
468 	return True;
469 
470     charset_list = Xmalloc(sizeof(char *));
471     if (charset_list == NULL)
472 	return False;
473 
474     charset_buf = strdup(font_set->font_data->name);
475     if (charset_buf == NULL) {
476 	Xfree(charset_list);
477 	return False;
478     }
479 
480     oc->core.missing_list.charset_list = charset_list;
481 
482     *charset_list = charset_buf;
483 
484     return True;
485 }
486 
487 static Bool
create_fontset(XOC oc)488 create_fontset(
489     XOC oc)
490 {
491     int found_num;
492 
493     if (init_fontset(oc) == False)
494         return False;
495 
496     found_num = parse_fontname(oc);
497     if (found_num <= 0) {
498 	if (found_num == 0)
499 	    set_missing_list(oc);
500 	return False;
501     }
502 
503     if (load_font(oc) == False)
504 	return False;
505 
506     if (init_core_part(oc) == False)
507 	return False;
508 
509     if (set_missing_list(oc) == False)
510 	return False;
511 
512     return True;
513 }
514 
515 static void
destroy_oc(XOC oc)516 destroy_oc(
517     XOC oc)
518 {
519     Display *dpy = oc->core.om->core.display;
520     XOCGenericPart *gen = XOC_GENERIC(oc);
521     XFontStruct **font_list, *font;
522 
523 
524     Xfree(gen->font_set);
525     Xfree(oc->core.base_name_list);
526     XFreeStringList(oc->core.font_info.font_name_list);
527 
528     if ((font_list = oc->core.font_info.font_struct_list)) {
529 	if ((font = *font_list)) {
530 	    if (font->fid)
531 		XFreeFont(dpy, font);
532 	    else
533 		XFreeFontInfo(NULL, font, 1);
534 	}
535 	Xfree(oc->core.font_info.font_struct_list);
536     }
537 
538 
539     XFreeStringList(oc->core.missing_list.charset_list);
540 
541 #ifdef notdef
542     Xfree(oc->core.res_name);
543     Xfree(oc->core.res_class);
544 #endif
545 
546     Xfree(oc);
547 }
548 
549 static char *
set_oc_values(XOC oc,XlcArgList args,int num_args)550 set_oc_values(
551     XOC oc,
552     XlcArgList args,
553     int num_args)
554 {
555     if (oc->core.resources == NULL)
556 	return NULL;
557 
558     return _XlcSetValues((XPointer) oc, oc->core.resources,
559 			 oc->core.num_resources, args, num_args, XlcSetMask);
560 }
561 
562 static char *
get_oc_values(XOC oc,XlcArgList args,int num_args)563 get_oc_values(
564     XOC oc,
565     XlcArgList args,
566     int num_args)
567 {
568     if (oc->core.resources == NULL)
569 	return NULL;
570 
571     return _XlcGetValues((XPointer) oc, oc->core.resources,
572 			 oc->core.num_resources, args, num_args, XlcGetMask);
573 }
574 
575 static Bool
wcs_to_mbs(XOC oc,char * to,_Xconst wchar_t * from,int length)576 wcs_to_mbs(
577     XOC oc,
578     char *to,
579     _Xconst wchar_t *from,
580     int length)
581 {
582     XlcConv conv = XOC_GENERIC(oc)->wcs_to_cs;
583     XLCd lcd;
584     int ret, to_left = length;
585 
586     if (conv == NULL) {
587 	lcd = oc->core.om->core.lcd;
588 	conv = _XlcOpenConverter(lcd, XlcNWideChar, lcd, XlcNMultiByte);
589 	if (conv == NULL)
590 	    return False;
591 	XOC_GENERIC(oc)->wcs_to_cs = conv;
592     } else
593 	_XlcResetConverter(conv);
594 
595     ret = _XlcConvert(conv, (XPointer *) &from, &length, (XPointer *) &to,
596 		      &to_left, NULL, 0);
597     if (ret != 0 || length > 0)
598 	return False;
599 
600     return True;
601 }
602 
603 static int
_XmbDefaultTextEscapement(XOC oc,_Xconst char * text,int length)604 _XmbDefaultTextEscapement(XOC oc, _Xconst char *text, int length)
605 {
606     return XTextWidth(*oc->core.font_info.font_struct_list, text, length);
607 }
608 
609 static int
_XwcDefaultTextEscapement(XOC oc,_Xconst wchar_t * text,int length)610 _XwcDefaultTextEscapement(XOC oc, _Xconst wchar_t *text, int length)
611 {
612     DefineLocalBuf;
613     char *buf = AllocLocalBuf(length);
614     int ret = 0;
615 
616     if (buf == NULL)
617 	return 0;
618 
619     if (wcs_to_mbs(oc, buf, text, length) == False)
620 	goto err;
621 
622     ret = _XmbDefaultTextEscapement(oc, buf, length);
623 
624 err:
625     FreeLocalBuf(buf);
626 
627     return ret;
628 }
629 
630 static int
_XmbDefaultTextExtents(XOC oc,_Xconst char * text,int length,XRectangle * overall_ink,XRectangle * overall_logical)631 _XmbDefaultTextExtents(XOC oc, _Xconst char *text, int length,
632 		       XRectangle *overall_ink, XRectangle *overall_logical)
633 {
634     int direction, logical_ascent, logical_descent;
635     XCharStruct overall;
636 
637     XTextExtents(*oc->core.font_info.font_struct_list, text, length, &direction,
638 		 &logical_ascent, &logical_descent, &overall);
639 
640     if (overall_ink) {
641 	overall_ink->x = overall.lbearing;
642 	overall_ink->y = -(overall.ascent);
643 	overall_ink->width = overall.rbearing - overall.lbearing;
644 	overall_ink->height = overall.ascent + overall.descent;
645     }
646 
647     if (overall_logical) {
648 	overall_logical->x = 0;
649         overall_logical->y = -(logical_ascent);
650 	overall_logical->width = overall.width;
651         overall_logical->height = logical_ascent + logical_descent;
652     }
653 
654     return overall.width;
655 }
656 
657 static int
_XwcDefaultTextExtents(XOC oc,_Xconst wchar_t * text,int length,XRectangle * overall_ink,XRectangle * overall_logical)658 _XwcDefaultTextExtents(XOC oc, _Xconst wchar_t *text, int length,
659 		       XRectangle *overall_ink, XRectangle *overall_logical)
660 {
661     DefineLocalBuf;
662     char *buf = AllocLocalBuf(length);
663     int ret = 0;
664 
665     if (buf == NULL)
666 	return 0;
667 
668     if (wcs_to_mbs(oc, buf, text, length) == False)
669 	goto err;
670 
671     ret = _XmbDefaultTextExtents(oc, buf, length, overall_ink, overall_logical);
672 
673 err:
674     FreeLocalBuf(buf);
675 
676     return ret;
677 }
678 
679 static Status
_XmbDefaultTextPerCharExtents(XOC oc,_Xconst char * text,int length,XRectangle * ink_buf,XRectangle * logical_buf,int buf_size,int * num_chars,XRectangle * overall_ink,XRectangle * overall_logical)680 _XmbDefaultTextPerCharExtents(XOC oc, _Xconst char *text, int length,
681 			      XRectangle *ink_buf, XRectangle *logical_buf,
682 			      int buf_size, int *num_chars,
683 			      XRectangle *overall_ink,
684 			      XRectangle *overall_logical)
685 {
686     XFontStruct *font = *oc->core.font_info.font_struct_list;
687     XCharStruct *def, *cs, overall;
688     Bool first = True;
689 
690     if (buf_size < length)
691 	return 0;
692 
693     bzero((char *) &overall, sizeof(XCharStruct));
694     *num_chars = 0;
695 
696     CI_GET_DEFAULT_INFO_1D(font, def)
697 
698     while (length-- > 0) {
699 	CI_GET_CHAR_INFO_1D(font, *text, def, cs)
700 	text++;
701 	if (cs == NULL)
702 	    continue;
703 
704 	ink_buf->x = overall.width + cs->lbearing;
705 	ink_buf->y = -(cs->ascent);
706 	ink_buf->width = cs->rbearing - cs->lbearing;
707 	ink_buf->height = cs->ascent + cs->descent;
708 	ink_buf++;
709 
710 	logical_buf->x = overall.width;
711 	logical_buf->y = -(font->ascent);
712 	logical_buf->width = cs->width;
713 	logical_buf->height = font->ascent + font->descent;
714 	logical_buf++;
715 
716 	if (first) {
717 	    overall = *cs;
718 	    first = False;
719 	} else {
720 	    overall.ascent = max(overall.ascent, cs->ascent);
721 	    overall.descent = max(overall.descent, cs->descent);
722 	    overall.lbearing = min(overall.lbearing, overall.width +
723 				   cs->lbearing);
724 	    overall.rbearing = max(overall.rbearing, overall.width +
725 				   cs->rbearing);
726 	    overall.width += cs->width;
727 	}
728    	(*num_chars)++;
729     }
730 
731     if (overall_ink) {
732 	overall_ink->x = overall.lbearing;
733 	overall_ink->y = -(overall.ascent);
734 	overall_ink->width = overall.rbearing - overall.lbearing;
735 	overall_ink->height = overall.ascent + overall.descent;
736     }
737 
738     if (overall_logical) {
739 	overall_logical->x = 0;
740 	overall_logical->y = -(font->ascent);
741 	overall_logical->width = overall.width;
742 	overall_logical->height = font->ascent + font->descent;
743     }
744 
745     return 1;
746 }
747 
748 static Status
_XwcDefaultTextPerCharExtents(XOC oc,_Xconst wchar_t * text,int length,XRectangle * ink_buf,XRectangle * logical_buf,int buf_size,int * num_chars,XRectangle * overall_ink,XRectangle * overall_logical)749 _XwcDefaultTextPerCharExtents(XOC oc, _Xconst wchar_t *text, int length,
750 			      XRectangle *ink_buf, XRectangle *logical_buf,
751 			      int buf_size, int *num_chars,
752 			      XRectangle *overall_ink,
753 			      XRectangle *overall_logical)
754 {
755     DefineLocalBuf;
756     char *buf = AllocLocalBuf(length);
757     Status ret = 0;
758 
759     if (buf == NULL)
760 	return 0;
761 
762     if (wcs_to_mbs(oc, buf, text, length) == False)
763 	goto err;
764 
765     ret = _XmbDefaultTextPerCharExtents(oc, buf, length, ink_buf, logical_buf,
766 					buf_size, num_chars, overall_ink,
767 					overall_logical);
768 
769 err:
770     FreeLocalBuf(buf);
771 
772     return ret;
773 }
774 
775 static int
_XmbDefaultDrawString(Display * dpy,Drawable d,XOC oc,GC gc,int x,int y,_Xconst char * text,int length)776 _XmbDefaultDrawString(Display *dpy, Drawable d, XOC oc, GC gc, int x, int y,
777 		      _Xconst char *text, int length)
778 {
779     XFontStruct *font = *oc->core.font_info.font_struct_list;
780 
781     XSetFont(dpy, gc, font->fid);
782     XDrawString(dpy, d, gc, x, y, text, length);
783 
784     return XTextWidth(font, text, length);
785 }
786 
787 static int
_XwcDefaultDrawString(Display * dpy,Drawable d,XOC oc,GC gc,int x,int y,_Xconst wchar_t * text,int length)788 _XwcDefaultDrawString(Display *dpy, Drawable d, XOC oc, GC gc, int x, int y,
789 		      _Xconst wchar_t *text, int length)
790 {
791     DefineLocalBuf;
792     char *buf = AllocLocalBuf(length);
793     int ret = 0;
794 
795     if (buf == NULL)
796 	return 0;
797 
798     if (wcs_to_mbs(oc, buf, text, length) == False)
799 	goto err;
800 
801     ret = _XmbDefaultDrawString(dpy, d, oc, gc, x, y, buf, length);
802 
803 err:
804     FreeLocalBuf(buf);
805 
806     return ret;
807 }
808 
809 static void
_XmbDefaultDrawImageString(Display * dpy,Drawable d,XOC oc,GC gc,int x,int y,_Xconst char * text,int length)810 _XmbDefaultDrawImageString(Display *dpy, Drawable d, XOC oc, GC gc, int x,
811 			   int y, _Xconst char *text, int length)
812 {
813     XSetFont(dpy, gc, (*oc->core.font_info.font_struct_list)->fid);
814     XDrawImageString(dpy, d, gc, x, y, text, length);
815 }
816 
817 static void
_XwcDefaultDrawImageString(Display * dpy,Drawable d,XOC oc,GC gc,int x,int y,_Xconst wchar_t * text,int length)818 _XwcDefaultDrawImageString(Display *dpy, Drawable d, XOC oc, GC gc, int x,
819 			   int y, _Xconst wchar_t *text, int length)
820 {
821     DefineLocalBuf;
822     char *buf = AllocLocalBuf(length);
823 
824     if (buf == NULL)
825 	return;
826 
827     if (wcs_to_mbs(oc, buf, text, length) == False)
828 	goto err;
829 
830     _XmbDefaultDrawImageString(dpy, d, oc, gc, x, y, buf, length);
831 
832 err:
833     FreeLocalBuf(buf);
834 }
835 
836 static _Xconst XOCMethodsRec oc_default_methods = {
837     destroy_oc,
838     set_oc_values,
839     get_oc_values,
840     _XmbDefaultTextEscapement,
841     _XmbDefaultTextExtents,
842     _XmbDefaultTextPerCharExtents,
843     _XmbDefaultDrawString,
844     _XmbDefaultDrawImageString,
845     _XwcDefaultTextEscapement,
846     _XwcDefaultTextExtents,
847     _XwcDefaultTextPerCharExtents,
848     _XwcDefaultDrawString,
849     _XwcDefaultDrawImageString
850 };
851 
852 static XlcResource oc_resources[] = {
853     { XNBaseFontName, NULLQUARK, sizeof(char *),
854       XOffsetOf(XOCRec, core.base_name_list), XlcCreateMask | XlcGetMask },
855     { XNOMAutomatic, NULLQUARK, sizeof(Bool),
856       XOffsetOf(XOCRec, core.om_automatic), XlcGetMask },
857     { XNMissingCharSet, NULLQUARK, sizeof(XOMCharSetList),
858       XOffsetOf(XOCRec, core.missing_list), XlcGetMask },
859     { XNDefaultString, NULLQUARK, sizeof(char *),
860       XOffsetOf(XOCRec, core.default_string), XlcGetMask },
861     { XNOrientation, NULLQUARK, sizeof(XOrientation),
862       XOffsetOf(XOCRec, core.orientation), XlcSetMask | XlcGetMask },
863     { XNResourceName, NULLQUARK, sizeof(char *),
864       XOffsetOf(XOCRec, core.res_name), XlcSetMask | XlcGetMask },
865     { XNResourceClass, NULLQUARK, sizeof(char *),
866       XOffsetOf(XOCRec, core.res_class), XlcSetMask | XlcGetMask },
867     { XNFontInfo, NULLQUARK, sizeof(XOMFontInfo),
868       XOffsetOf(XOCRec, core.font_info), XlcGetMask }
869 };
870 
871 static XOC
create_oc(XOM om,XlcArgList args,int num_args)872 create_oc(
873     XOM om,
874     XlcArgList args,
875     int num_args)
876 {
877     XOC oc;
878 
879     oc = Xcalloc(1, sizeof(XOCGenericRec));
880     if (oc == NULL)
881 	return (XOC) NULL;
882 
883     oc->core.om = om;
884 
885     if (oc_resources[0].xrm_name == NULLQUARK)
886 	_XlcCompileResourceList(oc_resources, XlcNumber(oc_resources));
887 
888     if (_XlcSetValues((XPointer) oc, oc_resources, XlcNumber(oc_resources),
889 		      args, num_args, XlcCreateMask | XlcDefaultMask))
890 	goto err;
891 
892     if (oc->core.base_name_list == NULL)
893 	goto err;
894 
895     oc->core.resources = oc_resources;
896     oc->core.num_resources = XlcNumber(oc_resources);
897 
898     if (create_fontset(oc) == False)
899 	goto err;
900 
901     oc->methods = (XOCMethods)&oc_default_methods;
902 
903     return oc;
904 
905 err:
906     destroy_oc(oc);
907 
908     return (XOC) NULL;
909 }
910 
911 static Status
close_om(XOM om)912 close_om(
913     XOM om)
914 {
915     XOMGenericPart *gen = XOM_GENERIC(om);
916     OMData data;
917     FontData font_data;
918     int count;
919 
920     if ((data = gen->data)) {
921 	if (data->font_data) {
922 	  for (font_data = data->font_data, count = data->font_data_count;
923 	       count-- > 0 ; font_data++) {
924 		Xfree(font_data->name);
925 	  }
926 	  Xfree(data->font_data);
927 	}
928 	Xfree(gen->data);
929     }
930 
931 
932     Xfree(om->core.res_name);
933     Xfree(om->core.res_class);
934 
935     if (om->core.required_charset.charset_list)
936 	XFreeStringList(om->core.required_charset.charset_list);
937     else
938 	Xfree((char*)om->core.required_charset.charset_list);
939 
940     Xfree(om->core.orientation_list.orientation);
941     Xfree(om);
942 
943     return 1;
944 }
945 
946 static char *
set_om_values(XOM om,XlcArgList args,int num_args)947 set_om_values(
948     XOM om,
949     XlcArgList args,
950     int num_args)
951 {
952     if (om->core.resources == NULL)
953 	return NULL;
954 
955     return _XlcSetValues((XPointer) om, om->core.resources,
956 			 om->core.num_resources, args, num_args, XlcSetMask);
957 }
958 
959 static char *
get_om_values(XOM om,XlcArgList args,int num_args)960 get_om_values(
961     XOM om,
962     XlcArgList args,
963     int num_args)
964 {
965     if (om->core.resources == NULL)
966 	return NULL;
967 
968     return _XlcGetValues((XPointer) om, om->core.resources,
969 			 om->core.num_resources, args, num_args, XlcGetMask);
970 }
971 
972 static _Xconst XOMMethodsRec methods = {
973     close_om,
974     set_om_values,
975     get_om_values,
976     create_oc
977 };
978 
979 static XlcResource om_resources[] = {
980     { XNRequiredCharSet, NULLQUARK, sizeof(XOMCharSetList),
981       XOffsetOf(XOMRec, core.required_charset), XlcGetMask },
982     { XNQueryOrientation, NULLQUARK, sizeof(XOMOrientation),
983       XOffsetOf(XOMRec, core.orientation_list), XlcGetMask },
984     { XNDirectionalDependentDrawing, NULLQUARK, sizeof(Bool),
985       XOffsetOf(XOMRec, core.directional_dependent), XlcGetMask },
986     { XNContextualDrawing, NULLQUARK, sizeof(Bool),
987       XOffsetOf(XOMRec, core.contextual_drawing), XlcGetMask }
988 };
989 
990 static OMData
add_data(XOM om)991 add_data(
992     XOM om)
993 {
994     XOMGenericPart *gen = XOM_GENERIC(om);
995     OMData new;
996 
997     new = Xcalloc(1, sizeof(OMDataRec));
998 
999     if (new == NULL)
1000         return NULL;
1001 
1002     gen->data = new;
1003 
1004     return new;
1005 }
1006 
1007 static _Xconst char *supported_charset_list[] = {
1008     "ISO8859-1",
1009     "adobe-fontspecific",
1010     "SUNOLCURSOR-1",
1011     "SUNOLGLYPH-1"
1012 };
1013 
1014 static Bool
init_om(XOM om)1015 init_om(
1016     XOM om)
1017 {
1018     XOMGenericPart *gen = XOM_GENERIC(om);
1019     OMData data;
1020     FontData font_data;
1021     char **required_list;
1022     XOrientation *orientation;
1023     char *bufptr;
1024     int i, count;
1025 
1026     count = XlcNumber(supported_charset_list);
1027 
1028     data = add_data(om);
1029     if (data == NULL)
1030 	return False;
1031 
1032     font_data = Xcalloc(count, sizeof(FontDataRec));
1033     if (font_data == NULL)
1034 	return False;
1035     data->font_data = font_data;
1036     data->font_data_count = count;
1037 
1038     for (i = 0; i < count; i++, font_data++) {
1039 	font_data->name = strdup(supported_charset_list[i]);
1040 	if (font_data->name == NULL)
1041 	    return False;
1042     }
1043 
1044     /* required charset list */
1045     required_list = Xmalloc(sizeof(char *));
1046     if (required_list == NULL)
1047 	return False;
1048 
1049     bufptr = strdup(data->font_data->name);
1050     if (bufptr == NULL) {
1051 	Xfree(required_list);
1052 	return False;
1053     }
1054 
1055     om->core.required_charset.charset_list = required_list;
1056     om->core.required_charset.charset_count = 1; /* always 1 */
1057 
1058     data = gen->data;
1059 
1060     *required_list = bufptr;
1061 
1062     /* orientation list */
1063     orientation = Xmalloc(sizeof(XOrientation));
1064     if (orientation == NULL)
1065 	return False;
1066 
1067     *orientation = XOMOrientation_LTR_TTB;
1068     om->core.orientation_list.orientation = orientation;
1069     om->core.orientation_list.num_orientation = 1;
1070 
1071     /* directional dependent drawing */
1072     om->core.directional_dependent = False;
1073 
1074     /* contextual drawing */
1075     om->core.contextual_drawing = False;
1076 
1077     /* context dependent */
1078     om->core.context_dependent = False;
1079 
1080     return True;
1081 }
1082 
1083 XOM
_XDefaultOpenOM(XLCd lcd,Display * dpy,XrmDatabase rdb,_Xconst char * res_name,_Xconst char * res_class)1084 _XDefaultOpenOM(XLCd lcd, Display *dpy, XrmDatabase rdb,
1085 		_Xconst char *res_name, _Xconst char *res_class)
1086 {
1087     XOM om;
1088 
1089     om = Xcalloc(1, sizeof(XOMGenericRec));
1090     if (om == NULL)
1091 	return (XOM) NULL;
1092 
1093     om->methods = (XOMMethods)&methods;
1094     om->core.lcd = lcd;
1095     om->core.display = dpy;
1096     om->core.rdb = rdb;
1097     if (res_name) {
1098 	om->core.res_name = strdup(res_name);
1099 	if (om->core.res_name == NULL)
1100 	    goto err;
1101     }
1102     if (res_class) {
1103 	om->core.res_class = strdup(res_class);
1104 	if (om->core.res_class == NULL)
1105 	    goto err;
1106     }
1107 
1108     if (om_resources[0].xrm_name == NULLQUARK)
1109 	_XlcCompileResourceList(om_resources, XlcNumber(om_resources));
1110 
1111     om->core.resources = om_resources;
1112     om->core.num_resources = XlcNumber(om_resources);
1113 
1114     if (init_om(om) == False)
1115 	goto err;
1116 
1117     return om;
1118 err:
1119     close_om(om);
1120 
1121     return (XOM) NULL;
1122 }
1123