1 /**
2 *
3 * $Header: /cvsroot/lesstif/lesstif/lib/Xm-2.1/RenderTable.c,v 1.6 2005/06/24 11:36:03 dannybackx Exp $
4 *
5 * Copyright (C) 1998 Free Software Foundation, Inc.
6 * Copyright � 1998, 2000, 2001, 2002, 2004, 2005 LessTif Development Team
7 *
8 * This file is part of the GNU LessTif Library.
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the Free
22 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 **/
25
26 static const char rcsid[] = "$Header: /cvsroot/lesstif/lesstif/lib/Xm-2.1/RenderTable.c,v 1.6 2005/06/24 11:36:03 dannybackx Exp $";
27
28 #include <LTconfig.h>
29
30 #include <string.h>
31
32 #include <Xm/XmP.h>
33 #include <XmI/XmI.h>
34
35 #include <XmI/DebugUtil.h>
36
37 #ifdef USE_XFT
38 #include <X11/Xft/Xft.h>
39 #endif
40
_XmRenditionCopy(XmRendition s)41 static XmRendition _XmRenditionCopy(XmRendition s)
42 {
43 s->count++;
44 #if 0
45 DEBUGOUT(_LtDebug(__FILE__, NULL, "_XmRenditionCopy(%p) rc %d\n",
46 s, s->count));
47 #endif
48 return s;
49 }
50
_XmRenditionFree(XmRendition r)51 static void _XmRenditionFree(XmRendition r)
52 {
53 _XmFontListEntryFree(r);
54 }
55
56 extern XmRenderTable
XmRenderTableAddRenditions(XmRenderTable oldtable,XmRendition * renditions,Cardinal rendition_count,XmMergeMode merge_mode)57 XmRenderTableAddRenditions(XmRenderTable oldtable,
58 XmRendition *renditions,
59 Cardinal rendition_count,
60 XmMergeMode merge_mode)
61 {
62 /* FIX ME simplistic */
63 int count, i, off;
64 XmRenderTable r;
65
66 off = oldtable ? oldtable->count : 0;
67 count = off + rendition_count;
68 r = __XmFontListAlloc(count);
69
70 if (oldtable)
71 for (i=0; i<oldtable->count; i++)
72 r->renditions[i] = _XmRenditionCopy(oldtable->renditions[i]);
73 for (i=0; i<rendition_count; i++)
74 r->renditions[i+off] = _XmRenditionCopy(renditions[i]);
75
76 r->dpy = r->renditions[0]->dpy;
77 return r;
78 }
79
_XmRenderTablePushRendition(XmRenderTable old,XmRendition rend)80 XmRenderTable _XmRenderTablePushRendition(XmRenderTable old, XmRendition rend)
81 {
82 int count, i, off;
83 XmRenderTable r;
84
85 off = old ? old->count : 0;
86 count = off + 1;
87 r = __XmFontListAlloc(count);
88
89 r->renditions[0] = _XmRenditionCopy(rend);
90 for (i=0; i<off; i++)
91 r->renditions[i+1] = _XmRenditionCopy(old->renditions[i]);
92
93 r->dpy = r->renditions[0]->dpy;
94 r->count = count;
95 return r;
96 }
97
_XmRenderTablePopRendition(XmRenderTable old,XmRendition rend)98 XmRenderTable _XmRenderTablePopRendition(XmRenderTable old, XmRendition rend)
99 {
100 XmRenderTable r;
101 int i;
102
103 if (!old)
104 return NULL;
105 r = __XmFontListAlloc(old->count - 1);
106 for (i=1; i<old->count; i++)
107 r->renditions[i-1] = _XmRenditionCopy(old->renditions[i]);
108 r->dpy = old->dpy;
109 r->count = old->count - 1;
110 return r;
111 }
112
113 /*
114 * Be sure to maintain the same allocation as XmFontList
115 *
116 * NULL tag means copy all renditions.
117 */
118 extern XmRenderTable
XmRenderTableCopy(XmRenderTable table,XmStringTag * tags,int tag_count)119 XmRenderTableCopy(XmRenderTable table, XmStringTag *tags, int tag_count)
120 {
121 int i, j, k, count;
122 XmRenderTable r;
123
124 if (table == NULL)
125 return NULL;
126
127 if (!tags) {
128 /* Allocate & copy */
129 r = __XmFontListAlloc(table->count);
130 for (i=0; i < table->count; i++)
131 r->renditions[i] = _XmRenditionCopy(table->renditions[i]);
132 r->count = table->count;
133 r->dpy = table->dpy;
134 return r;
135 }
136 for (i=0, count=0; i<table->count; i++) {
137 for (j=0; j<tag_count; j++)
138 if (strcmp(table->renditions[i]->tag, tags[j]) == 0) {
139 count++;
140 j = tag_count; /* end loop */
141 }
142 }
143
144 /* Allocate & copy */
145 r = __XmFontListAlloc(count);
146
147 for (i=0, j=0; i < table->count; i++)
148 for (k=0; k<tag_count; k++) {
149 if (strcmp(table->renditions[i]->tag, tags[k]) == 0) {
150 r->renditions[j] = _XmRenditionCopy(table->renditions[i]);
151 j++;
152 /* force end of internal loop */
153 k = tag_count;
154 }
155 }
156 r->count = count;
157 r->dpy = table->dpy;
158 return r;
159 }
160
161
162 extern XmRenderTable
XmRenderTableCvtFromProp(Widget widget,char * property,unsigned int length)163 XmRenderTableCvtFromProp(Widget widget,
164 char *property,
165 unsigned int length)
166 {
167 return NULL;
168 }
169
170
171 extern unsigned int
XmRenderTableCvtToProp(Widget widget,XmRenderTable table,char ** prop_return)172 XmRenderTableCvtToProp(Widget widget,
173 XmRenderTable table,
174 char **prop_return)
175 {
176 return 0;
177 }
178
179
180 extern void
XmRenderTableFree(XmRenderTable table)181 XmRenderTableFree(XmRenderTable table)
182 {
183 XmFontListFree(table);
184 }
185
186 extern XmRendition
XmRenderTableGetRendition(XmRenderTable table,XmStringTag tag)187 XmRenderTableGetRendition(XmRenderTable table, XmStringTag tag)
188 {
189 int i;
190
191 for (i=0; i<table->count; i++) {
192 if (tag == table->renditions[i]->tag)
193 return _XmRenditionCopy(table->renditions[i]);
194 else if (tag && table->renditions[i]->tag &&
195 strcmp(table->renditions[i]->tag, tag) == 0)
196 return _XmRenditionCopy(table->renditions[i]);
197 }
198 return NULL;
199 }
200
201 #ifdef USE_XFT
202 extern XmRendition
XmeRenderTableGetXftRendition(XmRenderTable table)203 XmeRenderTableGetXftRendition(XmRenderTable table)
204 {
205 if (table == NULL || table->count == 0)
206 return NULL;
207 return _XmRenditionCopy(table->renditions[0]);
208 }
209 #endif
210
211 extern XmRendition *
XmRenderTableGetRenditions(XmRenderTable table,XmStringTag * tags,Cardinal tag_count)212 XmRenderTableGetRenditions(XmRenderTable table,
213 XmStringTag *tags,
214 Cardinal tag_count)
215 {
216 return NULL;
217 }
218
219
XmRenderTableGetTags(XmRenderTable table,XmStringTag ** tag_list)220 extern int XmRenderTableGetTags(XmRenderTable table, XmStringTag **tag_list)
221 {
222 return 0;
223 }
224
225 /*
226 * This function deallocates the original render table and the matching
227 * renditions after extracting the required information.
228 */
229 extern XmRenderTable
XmRenderTableRemoveRenditions(XmRenderTable table,XmStringTag * tags,int tag_count)230 XmRenderTableRemoveRenditions(XmRenderTable table, XmStringTag *tags, int tag_count)
231 {
232 int i, j, k, count, match;
233 XmRenderTable r;
234
235 count = table->count;
236 if (tags) {
237 for (i=0; i<table->count; i++) {
238 for (j=0; j<tag_count; j++)
239 if (strcmp(table->renditions[i]->tag, tags[j]) == 0) {
240 count--;
241 j = tag_count; /* end loop */
242 }
243 }
244 }
245
246 /* Allocate & copy */
247 r = __XmFontListAlloc(count);
248
249 for (i=0, j=0; i < table->count; i++) {
250 for (match=0, k=0; k<tag_count && match == 0; k++)
251 if (strcmp(table->renditions[i]->tag, tags[k]) == 0)
252 match = 1;
253 if (match)
254 continue;
255
256 r->renditions[j] = _XmRenditionCopy(table->renditions[i]);
257 j++;
258 /* force end of internal loop */
259 k = tag_count;
260 }
261 r->count = count;
262
263 return r;
264 }
265
266 extern Boolean
XmeRenderTableGetDefaultFont(XmRenderTable renderTable,XFontStruct ** fontStruct)267 XmeRenderTableGetDefaultFont(XmRenderTable renderTable,
268 XFontStruct **fontStruct)
269 {
270 return False;
271 }
272
273 /*
274 * Note that this uses the same structure as a XmFontListEntry.
275 */
276 extern XmRendition
XmRenditionCreate(Widget widget,XmStringTag tag,ArgList al,Cardinal ac)277 XmRenditionCreate(Widget widget, XmStringTag tag, ArgList al, Cardinal ac)
278 {
279 int i;
280 XmRendition r;
281
282 r = _XmFontListEntryCreate();
283 r->tag = XtNewString(tag);
284 r->dpy = XtDisplay(widget);
285
286 /* Assign defaults */
287 r->font = (XFontSet)XmAS_IS;
288 r->font_name = NULL; /* instead of XmAS_IS */
289 r->type = XmAS_IS;
290 r->rendition_foreground = XmAS_IS;
291 r->rendition_background = XmAS_IS;
292 r->load_model = XmAS_IS;
293 r->strike_thru_type = XmAS_IS;
294 r->tab_list = (XmTabList)XmAS_IS;
295 r->underline_type = XmAS_IS;
296
297 #ifdef USE_XFT
298 r->xft_font = NULL;
299 r->font_average_width = 0;
300 memset(&r->xft_foreground, 0, sizeof(XftColor));
301 memset(&r->xft_background, 0, sizeof(XftColor));
302 r->pattern = NULL;
303 r->font_style = NULL;
304 r->font_foundry = NULL;
305 r->font_encoding = NULL;
306 r->font_size = 0;
307 r->pixel_size = 0;
308 r->font_slant = 0;
309 r->font_spacing = 0;
310 r->font_weight = 0;
311 #endif
312
313
314 #ifdef DEBUG_POINTERS
315 DEBUGOUT(_LtDebug(__FILE__, widget, "XmRenditionCreate() -> %p\n", r));
316 #endif
317 for (i=0; i<ac; i++) {
318 if (strcmp(al[i].name, XmNrenditionBackground) == 0) {
319 r->rendition_background = al[i].value;
320 }
321 if (strcmp(al[i].name, XmNrenditionForeground) == 0) {
322 r->rendition_foreground = al[i].value;
323 }
324 if (strcmp(al[i].name, XmNfontName) == 0) {
325 XtFree(r->font_name);
326 r->font_name = XtNewString((char *)al[i].value);
327 }
328 if (strcmp(al[i].name, XmNfont) == 0) {
329 r->font = (XFontSet)al[i].value;
330 }
331 if (strcmp(al[i].name, XmNfontType) == 0) {
332 r->type = (XmFontType)al[i].value;
333 }
334 if (strcmp(al[i].name, XmNloadModel) == 0) {
335 r->load_model = al[i].value;
336 }
337 if (strcmp(al[i].name, XmNstrikethruType) == 0) {
338 r->strike_thru_type = al[i].value;
339 }
340 if (strcmp(al[i].name, XmNtabList) == 0) {
341 r->tab_list = XmTabListCopy((XmTabList)al[i].value, 0, 0);
342 }
343 if (strcmp(al[i].name, XmNunderlineType) == 0) {
344 r->underline_type = al[i].value;
345 }
346 #ifdef USE_XFT
347 /* Xft specific resources ?? FIX ME */
348 #endif
349 }
350
351 return r;
352 }
353
354
XmRenditionFree(XmRendition rendition)355 extern void XmRenditionFree(XmRendition rendition)
356 {
357 /* XXX FIX ME XXX: Is this right? */
358 _XmRenditionFree(rendition);
359 }
360
361 #ifndef XtRXftColor
362 #define XtRXftColor "XftColor"
363 #endif
364
365 extern void
XmRenditionUpdate(XmRendition r,ArgList al,Cardinal ad)366 XmRenditionUpdate(XmRendition r, ArgList al, Cardinal ad)
367 {
368 int i;
369 Boolean ok;
370 Widget w = NULL; /* Crash !! */
371 XrmValue to, from;
372
373 for (i=0; i<ad; i++) {
374 #ifdef USE_XFT
375 if (strcmp(al[i].name, XmNrenditionForeground) == 0) {
376 /* XftColor */
377 from.addr = &al[i].value;
378 from.size = sizeof(XtPointer);
379 to.addr = &r->xft_foreground;
380 to.size = sizeof(XftColor);
381
382 ok = XtConvertAndStore(w,
383 XmRString, &from,
384 XtRXftColor, &to);
385 } else
386 if (strcmp(al[i].name, XmNrenditionBackground) == 0) {
387 /* XftColor */
388 from.addr = &al[i].value;
389 from.size = sizeof(XtPointer);
390 to.addr = &r->xft_background;
391 to.size = sizeof(XftColor);
392 ok = XtConvertAndStore(w,
393 XmRString, &from,
394 XtRXftColor, &to);
395 } else
396 #endif
397 {
398 ; /* Nothing */
399 }
400 }
401 #if 0
402 _XmWarning(NULL, "XmRenditionUpdate(): not yet implemented!");
403 #endif
404 }
405
406
XmRenditionRetrieve(XmRendition r,ArgList al,Cardinal ac)407 extern void XmRenditionRetrieve(XmRendition r, ArgList al, Cardinal ac)
408 {
409 int i;
410 #if 0
411 _XmWarning(NULL, "XmRenditionRetrieve(): not yet implemented!");
412 #endif
413
414 for (i=0; i<ac; i++) {
415 if (strcmp(al[i].name, XmNrenditionBackground) == 0) {
416 *(Pixel *)al[i].value = r->rendition_background;
417 } else if (strcmp(al[i].name, XmNrenditionForeground) == 0) {
418 *(Pixel *)al[i].value = r->rendition_foreground;
419 } else if (strcmp(al[i].name, XmNfontName) == 0) {
420 *(String *)al[i].value = XtNewString(r->font_name);
421 } else if (strcmp(al[i].name, XmNfont) == 0) {
422 *(XFontSet *)al[i].value = r->font;
423 } else if (strcmp(al[i].name, XmNfontType) == 0) {
424 *(XmFontType *)al[i].value = r->type;
425 } else if (strcmp(al[i].name, XmNloadModel) == 0) {
426 *(unsigned char *)al[i].value = r->load_model;
427 } else if (strcmp(al[i].name, XmNstrikethruType) == 0) {
428 *(unsigned char *)al[i].value = r->strike_thru_type;
429 } else if (strcmp(al[i].name, XmNtabList) == 0) {
430 *(XmTabList *)al[i].value = XmTabListCopy(r->tab_list, 0, 0);
431 } else if (strcmp(al[i].name, XmNunderlineType) == 0) {
432 *(unsigned char *)al[i].value = r->underline_type;
433 }
434 #ifdef USE_XFT
435 /* Xft specific resources ?? FIX ME */
436 #endif
437 }
438 }
439
440 /* If there are unspecified values in the primary rendition,
441 * then the widget must create an "effective" rendition for that
442 * segment. This is formed by using the previous (active) rendition
443 * to fill in the unspecified values of the primary rendition.
444 * ..
445 * Finally if the resulting rendition still has resources with
446 * unspecified values and the segment has a locale or charset tag
447 * (these are optional and mutually exclusive) this tag is matched
448 * with a rendition in the render table, and the missing rendition
449 * values are filled in from that entry.
450 *
451 * If no matching rendition is found for a particular tag, then the
452 * XmNoRenditionCallback of the XmDisplay object is called and the
453 * render table is searched again for that tag.
454 * If the resulting rendition does not specify a font or fontset,
455 * then ...
456 */
_XmRenderTableFinaliseTag(Widget w,XmRenderTable r,char * tag)457 void _XmRenderTableFinaliseTag(Widget w, XmRenderTable r, char *tag)
458 {
459 int i;
460 int found = 0;
461 XmFontListEntry e;
462 char *fn;
463
464 /* FIX ME */
465 DEBUGOUT(_LtDebug(__FILE__, w, "_XmRenderTableFinaliseTag(%s)\n", tag));
466 #if 1
467 /* Experimental start */
468 if (r->dpy == 0)
469 r->dpy = XtDisplay(w);
470 /* Experimental end */
471 #endif
472 for (i=0; i<r->count; i++) {
473 if (strcmp(tag, r->renditions[i]->tag) == 0) {
474 #if USE_XFT
475 if (r->renditions[i]->type == XmAS_IS) {
476 XftResult res;
477 XftPattern *p, *p2;
478
479 p = FcPatternCreate();
480 /* Don't even specify anything XftPatternAddString(p, XFT_FAMILY, "fixed"); */
481 p2 = XftFontMatch(XtDisplay(w), 0, p, &res);
482 r->renditions[i]->xft_font =
483 XftFontOpenPattern(XtDisplay(w), p2);
484 _XmXftFontAverageWidth(w,
485 (XtPointer)r->renditions[i]->xft_font,
486 &r->renditions[i]->font_average_width,
487 &r->renditions[i]->font_average_height);
488 r->renditions[i]->type = XmFONT_IS_XFT;
489 r->renditions[i]->font = NULL; /* HACK */
490
491 DEBUGOUT(_LtDebug(__FILE__, w,
492 "_XmRenderTableFinaliseTag(%s): AS IS\n", tag));
493 }
494 #endif
495 if (r->renditions[i]->font == 0
496 || r->renditions[i]->type == XmAS_IS
497 || r->renditions[i]->font == (XFontSet)XmAS_IS)
498 {
499 found = 1;
500
501 if (r->renditions[i]->font_name
502 && r->renditions[i]->font_name != (char *)XmAS_IS)
503 fn = r->renditions[i]->font_name;
504 else
505 fn = XmDEFAULT_FONT;
506
507 e = XmFontListEntryLoad(r->dpy,
508 fn,
509 XmFONT_IS_FONT,
510 tag);
511 if (e == NULL || e->font == NULL) {
512 if (e)
513 XmFontListEntryFree(&e);
514 continue;
515 }
516 r->renditions[i]->font = e->font;
517 XmFontListEntryFree(&e);
518 return;
519 }
520 }
521 }
522
523 if (r->renditions[0]->font == NULL ||
524 r->renditions[0]->font == (XFontSet)XmAS_IS) {
525 XmFontListEntry e = XmFontListEntryLoad(r->dpy,
526 XmDEFAULT_FONT, XmFONT_IS_FONT, XmFONTLIST_DEFAULT_TAG);
527 r->renditions[0]->font = e->font;
528 XmFontListEntryFree(&e);
529 }
530 }
531
532 /*
533 * This version takes the internal _XmString representation
534 */
__XmRenderTableFinalise(Widget w,XmRenderTable r,_XmString xms)535 void __XmRenderTableFinalise(Widget w, XmRenderTable r, _XmString xms)
536 {
537 int i;
538
539 DEBUGOUT(_LtDebug(__FILE__, w, "__XmRenderTableFinalise(rt %p xms %p)\n", r, xms));
540
541 if (xms == NULL) {
542 _XmRenderTableFinaliseTag(w, r, XmFONTLIST_DEFAULT_TAG);
543 return;
544 }
545
546 for (i=0; i<xms->number_of_components; i++) {
547 /* Run through the string, make sure all tags "work" */
548 switch (xms->components[i]->type) {
549 case XmSTRING_COMPONENT_RENDITION_BEGIN:
550 case XmSTRING_COMPONENT_CHARSET:
551 _XmRenderTableFinaliseTag(w, r, xms->components[i]->data);
552 break;
553 case XmSTRING_COMPONENT_LOCALE_TEXT:
554 _XmRenderTableFinaliseTag(w, r, xms->components[i]->data);
555 break;
556 default:
557 ; /* Nothing to do */
558 }
559 }
560 }
561
562 /*
563 * This one takes external XmString representation
564 */
_XmRenderTableFinalise(Widget w,XmRenderTable r,XmString xms)565 void _XmRenderTableFinalise(Widget w, XmRenderTable r, XmString xms)
566 {
567 XmStringContext ctx;
568 XmStringComponentType t;
569 char *tag = NULL, *txt = NULL;
570
571 DEBUGOUT(_LtDebug(__FILE__, w, "_XmRenderTableFinalise(rt %p xms %p)\n", r, xms));
572
573 if (xms == NULL) {
574 _XmRenderTableFinaliseTag(w, r, XmFONTLIST_DEFAULT_TAG);
575 return;
576 }
577
578 /* Run through the string, make sure all tags "work" */
579 if (! XmStringInitContext(&ctx, xms)) {
580 _XmRenderTableFinaliseTag(w, r, XmFONTLIST_DEFAULT_TAG);
581 return;
582 }
583
584 /* FIX ME XmStringGetNextComponent() is obsolete */
585 while ((t = XmStringGetNextComponent(ctx, &txt,
586 &tag, NULL, NULL, NULL, NULL)) != XmSTRING_COMPONENT_END) {
587 switch (t) {
588 case XmSTRING_COMPONENT_RENDITION_BEGIN:
589 case XmSTRING_COMPONENT_CHARSET:
590 _XmRenderTableFinaliseTag(w, r, tag);
591 default:
592 ; /* Nothing to do */
593 }
594 XtFree(tag);
595 XtFree(txt);
596 tag = NULL;
597 txt = NULL;
598 }
599 #if 0
600 if (r->renditions[0]->font == NULL ||
601 r->renditions[0]->font == (XFontSet)XmAS_IS) {
602 XmFontListEntry e = XmFontListEntryLoad(r->dpy,
603 XmDEFAULT_FONT, XmFONT_IS_FONT, XmFONTLIST_DEFAULT_TAG);
604 r->renditions[0]->font = e->font;
605 XmFontListEntryFree(&e);
606 }
607 #endif
608 }
609
610 Boolean
XmeUseXftFont(XmRenderTable r)611 XmeUseXftFont(XmRenderTable r)
612 {
613 #ifdef USE_XFT
614 if (r == NULL || r->count == 0)
615 return False;
616 if (r->renditions[0]->type == XmFONT_IS_XFT)
617 return True;
618 return False;
619 #else
620 return False;
621 #endif
622 }
623
624 XtPointer
XmeXftFont(XmRendition r)625 XmeXftFont(XmRendition r)
626 {
627 #ifdef USE_XFT
628 if (r == NULL)
629 return NULL;
630 if (r->type == XmFONT_IS_XFT)
631 return r->xft_font;
632 return NULL;
633 #else
634 return NULL;
635 #endif
636 }
637