1 /*
2  * Motif
3  *
4  * Copyright (c) 1987-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*
24  * HISTORY
25  */
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29 
30 #define FIX_1152
31 
32 #ifdef REV_INFO
33 #ifndef lint
34 static char rcsid[] = "$TOG: XmRenderT.c /main/14 1998/10/26 20:14:42 samborn $"
35 #endif
36 #endif
37 
38 #ifndef X_NOT_STDC_ENV
39 #include <stdlib.h>
40 #endif
41 #include <string.h>
42 #include <ctype.h>
43 #include <math.h>
44 
45 #ifdef __cplusplus
46 extern "C" { /* some 'locale.h' do not have prototypes (sun) */
47 #endif
48 #include <X11/Xlocale.h>
49 #ifdef __cplusplus
50 } /* Close scope of 'extern "C"' declaration */
51 #endif /* __cplusplus */
52 
53 #include <Xm/XmosP.h>		/* For ALLOCATE/DEALLOCATE_LOCAL */
54 #include <X11/IntrinsicP.h>
55 #include <X11/ShellP.h>
56 #include <X11/Xresource.h>
57 #include <Xm/Display.h>		/* For XmGetXmDisplay */
58 #include <Xm/DisplayP.h>	/* For direct access to callback fields */
59 #include "MessagesI.h"
60 #include "XmI.h"
61 #include "XmRenderTI.h"
62 #include "XmStringI.h"
63 #include "XmTabListI.h"
64 #ifdef USE_XFT
65 #include <X11/Xft/Xft.h>
66 #endif
67 
68 /* Warning Messages */
69 #define NO_NULL_TAG_MSG			_XmMMsgXmRenderT_0000
70 #define NULL_DISPLAY_MSG      		_XmMMsgXmRenderT_0001
71 #define INVALID_TYPE_MSG      		_XmMMsgXmRenderT_0002
72 #define CONVERSION_FAILED_MSG 		_XmMMsgXmRenderT_0003
73 #define NULL_FONT_TYPE_MSG    		_XmMMsgXmRenderT_0004
74 #define NULL_LOAD_IMMEDIATE_MSG		_XmMMsgXmRenderT_0005
75 
76 /* local macros */
77 #define GetHandle(type)		(type *)XtMalloc(sizeof(type))
78 #define FreeHandle(handle)	XtFree((char *)handle)
79 #define SetPtr(handle, ptr)	*(handle) = ptr
80 #define GetPtr(handle)		*(handle)
81 #define NameIsString(fontname) \
82   (((fontname) != NULL) && ((fontname) != (String)XmAS_IS))
83 #define ListIsList(tablist) \
84   (((tablist) != NULL) && \
85    ((unsigned int)(unsigned long)(tablist) != XmAS_IS))
86 
87 #define  FIX_1414
88 #define  FIX_1449
89 #define  FIX_1444
90 #define FIX_1451
91 #define FIX_1536
92 /**********************************************************************
93  *	      IMPORTANT NOTE: IMPLEMENTATION OF SHARING
94  *
95  *	Instances of XmRenderTable and XmRendition are shared via a
96  *	reference counting mechanism. This comment provides a general
97  *	overview of how this is done.
98  *
99  *	First, both rendertable and renditions are indirectly
100  *	referenced via a handle mechanism.  See the GetHandle,
101  *	FreeHandle, SetPtr and GetPtr macros above.  This allows
102  *	either the handle to change without the underlying data
103  * 	structure changing, or the underlying data structure to change
104  *	without the handle changing. I will indicate below where this
105  *	happens.
106  *
107  *	Second, the real data structure for rendertable and rendition
108  *	contain a reference count.  This count is incremented on copy
109  *	and decremented on free.  If a decrement produces a zero
110  *	refcount, the actual memory is freed.  If an increment
111  *	produces a zero refcount, then the refcount has overflowed.  The
112  *	refcount is decremented, and new memory is allocated for a new
113  *	copy.
114  *
115  *	Finally, I have defined a terminology for the different types
116  *	of "copying" that can done based on allocating a new handle or
117  *	not and allocating a new data structure or not.  This probably
118  *	conflicts with some other existing terminology, probably in
119  *	object oriented programming.  Sorry about that.
120  *
121  *	Function:	Clone	Copy	Renew	Duplicate
122  *			(Mutate)	(Update)
123  *
124  *	handle		new	new	old	old
125  *	structure	new	inc	new	inc
126  *			(changed)	(changed)
127  *
128  *	(changed) indicates that the data in the new structure has
129  *	been changed from the data in the old structure.
130  *
131  *	I will use these terms as a short hand in describing the
132  *	functions below.
133  **********************************************************************/
134 
135 
136 /********    Static Function Declarations    ********/
137 
138 static void CopyInto(XmRendition toRend,
139 		     XmRendition fromRend);
140 static void MergeInto(XmRendition toRend,
141 		     XmRendition fromRend);
142 static XmRendition CloneRendition(XmRendition rend);
143 static XmRendition CopyRendition(XmRendition rend);
144 static XmRendition RenewRendition(XmRendition rend);
145 static XmRendition DuplicateRendition(XmRendition rend);
146 static Boolean FreeRendition(XmRendition rend);
147 static void RenditionWarning(char *tag, char *type,
148 			     char *message, Display *dpy);
149 static void CleanupResources(XmRendition rend, Boolean copy);
150 static void ValidateTag(XmRendition rend,
151 			XmStringTag dflt);
152 static void ValidateAndLoadFont(XmRendition rend, Display *display);
153 static void SetRend(XmRendition to,
154 		    XmRendition from);
155 static Boolean RendComplete(XmRendition rend);
156 static void CopyFromArg(XtArgVal src,
157 			char *dst,
158 			unsigned int size);
159 static void CopyToArg(char *src,
160 		      XtArgVal *dst,
161 		      unsigned int size);
162 static Cardinal GetNamesAndClasses(Widget w,
163 				   XrmNameList names,
164 				   XrmClassList classes);
165 static XrmResourceList CompileResourceTable(XtResourceList resources,
166 					    Cardinal num_resources);
167 static Boolean GetResources(XmRendition rend,
168 			    Display *dsp,
169 			    Widget wid,
170 			    String resname,
171 			    String resclass,
172 			    XmStringTag tag,
173 			    ArgList arglist,
174 			    Cardinal argcount);
175 static void SetDefault(XmRendition rend);
176 #ifdef USE_XFT
177 #ifdef FIX_1536
178 static XftColor GetCachedXftColor(Display *display, Pixel color);
179 #endif
180 #endif
181 
182 /********    End Static Function Declarations    ********/
183 
184 /* Resource List. */
185 
186 /************************************************************************/
187 /* N.B.:  The SetDefault procedure has a hardcoded list of all the	*/
188 /*	common resources.  Be sure to update it when adding resources.	*/
189 /************************************************************************/
190 
191 #define DEFAULT_loadModel		XmAS_IS
192 #define DEFAULT_tag			XmS
193 #define DEFAULT_fontName		(String)XmAS_IS
194 #define DEFAULT_fontType		(XmFontType)XmAS_IS
195 #define DEFAULT_font			(XtPointer)XmAS_IS
196 #define DEFAULT_tabs			(XmTabList)XmAS_IS
197 #define DEFAULT_background		XmUNSPECIFIED_PIXEL
198 #define DEFAULT_foreground		XmUNSPECIFIED_PIXEL
199 #define DEFAULT_underlineType		XmAS_IS
200 #define DEFAULT_strikethruType		XmAS_IS
201 #define DEFAULT_backgroundState		XmAS_IS
202 #define DEFAULT_foregroundState		XmAS_IS
203 #ifdef USE_XFT
204 #define DEFAULT_xftFont			(XtPointer)XmAS_IS
205 #define DEFAULT_fontStyle		(String)NULL
206 #define DEFAULT_fontFoundry		(String)NULL
207 #define DEFAULT_fontEncoding		(String)NULL
208 #define DEFAULT_fontSize		0
209 #endif
210 
211 static XtResource _XmRenditionResources[] = {
212   {
213     XmNtag, XmCTag, XmRString,
214     sizeof(XmStringTag), XtOffsetOf(_XmRenditionRec, tag),
215     XmRImmediate, (XtPointer) DEFAULT_tag
216   },
217   {
218     XmNfontName, XmCFontName, XmRString,
219     sizeof(String), XtOffsetOf(_XmRenditionRec, fontName),
220     XmRImmediate, (XtPointer) DEFAULT_fontName
221   },
222   {
223     XmNfontType, XmCFontType, XmRFontType,
224     sizeof(XmFontType), XtOffsetOf(_XmRenditionRec, fontType),
225     XmRImmediate, (XtPointer) DEFAULT_fontType
226   },
227   {
228     XmNfont, XmCFont, XmRFontStruct,
229     sizeof(XtPointer), XtOffsetOf(_XmRenditionRec, font),
230     XmRImmediate, (XtPointer) DEFAULT_font
231   },
232   {
233     XmNloadModel, XmCLoadModel, XmRLoadModel,
234     sizeof(unsigned char), XtOffsetOf(_XmRenditionRec, loadModel),
235     XmRImmediate, (XtPointer) DEFAULT_loadModel
236   },
237   {
238     XmNtabList, XmCTabList, XmRTabList,
239     sizeof(XmTabList), XtOffsetOf(_XmRenditionRec, tabs),
240     XmRImmediate, (XtPointer) DEFAULT_tabs
241   },
242 #if USE_XFT
243   {
244     XmNxftFont, XmCXftFont, XmRPointer,
245     sizeof (XtPointer), XtOffsetOf (_XmRenditionRec, xftFont),
246     XmRImmediate, (XtPointer) DEFAULT_xftFont
247   },
248   {
249     XmNrenditionBackground, XmCRenditionBackground, XmRRenditionPixel,
250     sizeof (Pixel), XtOffsetOf (_XmRenditionRec, xftBackground.pixel),
251     XmRImmediate, (XtPointer) DEFAULT_background
252   },
253   {
254     XmNrenditionForeground, XmCRenditionForeground, XmRRenditionPixel,
255     sizeof (Pixel), XtOffsetOf (_XmRenditionRec, xftForeground.pixel),
256     XmRImmediate, (XtPointer) DEFAULT_foreground
257   },
258   {
259     XmNfontStyle, XmCFontStyle, XmRString,
260     sizeof(String), XtOffsetOf (_XmRenditionRec, fontStyle),
261     XmRImmediate, (XtPointer) DEFAULT_fontStyle
262   },
263   {
264     XmNfontFoundry, XmCFontFoundry, XmRString,
265     sizeof(String), XtOffsetOf (_XmRenditionRec, fontFoundry),
266     XmRImmediate, (XtPointer) DEFAULT_fontFoundry
267   },
268   {
269     XmNfontEncoding, XmCFontEncoding, XmRString,
270     sizeof(String), XtOffsetOf (_XmRenditionRec, fontEncoding),
271     XmRImmediate, (XtPointer) DEFAULT_fontEncoding
272   },
273   {
274     XmNfontSize, XmCFontSize, XmRInt,
275     sizeof(int), XtOffsetOf (_XmRenditionRec, fontSize),
276     XmRImmediate, (XtPointer) DEFAULT_fontSize
277   },
278 #else
279   {
280     XmNrenditionBackground, XmCRenditionBackground, XmRRenditionPixel,
281     sizeof (Pixel), XtOffsetOf (_XmRenditionRec, background),
282     XmRImmediate, (XtPointer) DEFAULT_background
283   },
284   {
285     XmNrenditionForeground, XmCRenditionForeground, XmRRenditionPixel,
286     sizeof (Pixel), XtOffsetOf (_XmRenditionRec, foreground),
287     XmRImmediate, (XtPointer) DEFAULT_foreground
288   },
289 #endif
290   {
291     XmNunderlineType, XmCUnderlineType, XmRLineType,
292     sizeof(unsigned char), XtOffsetOf(_XmRenditionRec, underlineType),
293     XmRImmediate, (XtPointer) DEFAULT_underlineType
294   },
295   {
296     XmNstrikethruType, XmCStrikethruType, XmRLineType,
297     sizeof(unsigned char), XtOffsetOf(_XmRenditionRec, strikethruType),
298     XmRImmediate, (XtPointer) DEFAULT_strikethruType
299   },
300   {
301     XmNforegroundState, XmCGroundState, XmRGroundState,
302     sizeof(unsigned char), XtOffsetOf(_XmRenditionRec, foregroundState),
303     XmRImmediate, (XtPointer) DEFAULT_foregroundState
304   },
305   {
306     XmNbackgroundState, XmCGroundState, XmRGroundState,
307     sizeof(unsigned char), XtOffsetOf(_XmRenditionRec, backgroundState),
308     XmRImmediate, (XtPointer) DEFAULT_backgroundState
309   },
310 };
311 
312 static XmConst Cardinal _XmNumRenditionResources =
313 	XtNumber(_XmRenditionResources);
314 
315 /* Searches up widget hierarchy, quarkifying ancestor names and */
316 /* classes. */
317 static Cardinal
GetNamesAndClasses(Widget w,XrmNameList names,XrmClassList classes)318 GetNamesAndClasses(Widget w, XrmNameList names, XrmClassList classes)
319 {
320   Cardinal length, j;
321   XrmQuark t;
322   WidgetClass wc;
323 
324   /* Return null-terminated quark arrays, with length the number of
325      quarks (not including NULL) */
326 
327   for (length = 0; w != NULL; w = (Widget)w->core.parent)
328     {
329       names[length] = w->core.xrm_name;
330       wc = XtClass(w);
331       /* KLUDGE KLUDGE KLUDGE KLUDGE */
332       if (w->core.parent == NULL && XtIsApplicationShell(w)) {
333 	classes[length] =
334 	  ((ApplicationShellWidget) w)->application.xrm_class;
335       } else classes[length] = wc->core_class.xrm_class;
336       length++;
337     }
338   /* They're in backwards order, flop them around */
339   for (j = 0; j < length/2; j++)
340     {
341       t = names[j];
342       names[j] = names[length-j-1];
343       names[length-j-1] = t;
344       t = classes[j];
345       classes[j] = classes[length-j-1];
346       classes[length-j-1] = t;
347     }
348   names[length] = NULLQUARK;
349   classes[length] = NULLQUARK;
350   return length;
351 }						  /* GetNamesAndClasses */
352 
353 /* Converts resource list to quarkified list. */
354 static XrmResourceList
CompileResourceTable(XtResourceList resources,Cardinal num_resources)355 CompileResourceTable(XtResourceList resources,
356 		     Cardinal num_resources)
357 {
358   Cardinal		count;
359   XrmResourceList	table, tPtr;
360   XtResourceList	rPtr;
361 
362   tPtr = table = (XrmResourceList)XtMalloc(num_resources * sizeof(XrmResource));
363   rPtr = resources;
364 
365   for (count = 0; count < num_resources; count++, tPtr++, rPtr++)
366     {
367       tPtr->xrm_name 		= XrmPermStringToQuark(rPtr->resource_name);
368       tPtr->xrm_class 		= XrmPermStringToQuark(rPtr->resource_class);
369       tPtr->xrm_type 		= XrmPermStringToQuark(rPtr->resource_type);
370       tPtr->xrm_size		= rPtr->resource_size;
371       tPtr->xrm_offset		= rPtr->resource_offset;
372       tPtr->xrm_default_type 	= XrmPermStringToQuark(rPtr->default_type);
373       tPtr->xrm_default_addr	= rPtr->default_addr;
374     }
375   return(table);
376 }
377 
378 /* Does resource database lookup for arglist, filling in defaults from */
379 /* resource list as necessary. */
380 static Boolean
GetResources(XmRendition rend,Display * dsp,Widget wid,String resname,String resclass,XmStringTag tag,ArgList arglist,Cardinal argcount)381 GetResources(XmRendition rend,
382 	     Display *dsp,
383 	     Widget wid,
384 	     String resname,
385 	     String resclass,
386 	     XmStringTag tag,
387 	     ArgList arglist,
388 	     Cardinal argcount)
389 {
390   XrmName		names[100];
391   XrmClass		classes[100];
392   Cardinal		length = 0;
393   static XrmQuarkList	quarks = NULL;
394   static Cardinal	num_quarks = 0;
395   static Boolean	*found = NULL;
396   int			i, j;
397   static XrmResourceList	table = NULL;
398   static XrmQuark	QString;
399   static XrmQuark	Qfont;
400   Arg			*arg;
401   XrmName		argName;
402   XrmResource		*res;
403   XrmDatabase		db = NULL;
404   XrmHashTable   	stackSearchList[100];
405   XrmHashTable    	*searchList = stackSearchList;
406   unsigned int    	searchListSize = 100;
407   Boolean		got_one = False;
408   XrmValue		value;
409   XrmQuark		rawType;
410   XrmValue		convValue;
411   Boolean		have_value, copied;
412 #ifdef XTHREADS
413   XtAppContext		app=NULL;
414 
415   if (wid)
416 	app = XtWidgetToApplicationContext(wid);
417   else if (dsp)
418 	app = XtDisplayToApplicationContext(dsp);
419   if (app) {
420       _XmAppLock(app);
421   }
422   _XmProcessLock();
423 #endif
424   /* Initialize quark cache */
425   if (quarks == NULL)
426     {
427       quarks = (XrmQuark *)XtMalloc(_XmNumRenditionResources *
428 				    sizeof(XrmQuark));
429       num_quarks = _XmNumRenditionResources;
430     }
431 
432   /* Initialize found */
433   if (found == NULL)
434     found = (Boolean *)XtMalloc(_XmNumRenditionResources * sizeof(Boolean));
435   bzero(found, _XmNumRenditionResources * sizeof(Boolean));
436 
437   /* Compile names and classes. */
438   if (wid != NULL)
439     length = GetNamesAndClasses(wid, names, classes);
440 
441   names[length] = XrmStringToQuark(resname);
442   classes[length] = XrmStringToQuark(resclass);
443   length++;
444 
445   if (tag != NULL)
446     {
447       names[length] = XrmStringToQuark(tag);
448       classes[length] = XrmPermStringToQuark(XmCRendition);
449       length++;
450     }
451 
452   names[length] = NULLQUARK;
453   classes[length] = NULLQUARK;
454 
455   /* Cache arglist */
456   if (num_quarks < argcount)
457     {
458       quarks = (XrmQuark *)XtRealloc((char *)quarks,
459 				     argcount * sizeof(XrmQuark));
460       num_quarks = argcount;
461     }
462   for (i = 0; i < argcount; i++)
463     quarks[i] = XrmStringToQuark(arglist[i].name);
464 
465   /* Compile resource description into XrmResourceList if not already done. */
466   if (table == NULL)
467     {
468       table = CompileResourceTable(_XmRenditionResources,
469 				   _XmNumRenditionResources);
470       QString = XrmPermStringToQuark(XtCString);
471       Qfont = XrmPermStringToQuark(XmNfont);
472     }
473 
474   /* Set resources from arglist. */
475   for (arg = arglist, i = 0; i < argcount; arg++, i++)
476     {
477       argName = quarks[i];
478 
479       for (j = 0, res = table; j < _XmNumRenditionResources; j++, res++)
480 	{
481 	  if (res->xrm_name == argName)
482 	    {
483 	      CopyFromArg((arg->value),
484 			  ((char *)GetPtr(rend) + res->xrm_offset),
485 			  res->xrm_size);
486 	      found[j] = TRUE;
487 	      break;
488 	    }
489 	}
490     }
491 
492   /* DB query */
493   /* Get database */
494   if ((wid != NULL) || (dsp != NULL))
495     {
496       if (wid != NULL)
497 	db = XtScreenDatabase(XtScreenOfObject(wid));
498       else db = XtScreenDatabase(DefaultScreenOfDisplay(dsp));
499 
500       /* Get searchlist */
501       while (!XrmQGetSearchList(db, names, classes,
502 				searchList, searchListSize))
503 	{
504 	  if (searchList == stackSearchList)
505 	    searchList = NULL;
506 	  searchList = (XrmHashTable *)XtRealloc((char*)searchList,
507 						 sizeof(XrmHashTable) *
508 						 (searchListSize *= 2));
509 	}
510     }
511 
512   /* Loop over table */
513   for (j = 0, res = table; j < _XmNumRenditionResources; j++, res++)
514     {
515       if (!found[j])
516 	{
517 	  copied = False;
518 	  have_value = False;
519 
520 	  if ((db != NULL) &&
521 	      (XrmQGetSearchResource(searchList, res->xrm_name,
522 				     res->xrm_class, &rawType, &value)))
523 	    {
524 	      /* convert if necessary */
525 	      if (rawType != res->xrm_type)
526 		{
527 		  if (wid != NULL)
528 		    {
529 		      convValue.size = res->xrm_size;
530 		      convValue.addr = (char *)GetPtr(rend) + res->xrm_offset;
531 		      /*
532 		       * Check for special font case.
533 		       * Depending upon the fontType resource, try to convert
534 		       * to a FontSet, else to a FontStruct.
535 		       */
536 		      if ((res->xrm_name == Qfont) &&
537 			  (_XmRendFontType(rend) == XmFONT_IS_FONTSET))
538 			  copied = have_value =
539 			     XtConvertAndStore(wid,
540 					       XrmQuarkToString(rawType),
541 					       &value,
542 					       "FontSet",
543 					       &convValue);
544 		      else
545 			  copied = have_value =
546 			     XtConvertAndStore(wid,
547 					       XrmQuarkToString(rawType),
548 					       &value,
549 					       XrmQuarkToString(res->xrm_type),
550 					       &convValue);
551 		    }
552 		  else have_value = False;
553 		}
554 	      else have_value = True;
555 
556 	      /* Check for special font case */
557 	      if (have_value)
558 		{
559 		  if (res->xrm_name == Qfont)
560 		    {
561 		      _XmRendFontName(rend) = value.addr;
562 		      copied = True;
563 		    }
564 		}
565 	    }
566 
567 	  if (!got_one && have_value) got_one = True;
568 
569 	  /* Set defaults */
570 	  if (!have_value)
571 	    {
572 	      CopyFromArg((XtArgVal)(res->xrm_default_addr),
573 			  ((char *)GetPtr(rend) + res->xrm_offset),
574 			  res->xrm_size);
575 	      copied = True;
576 	    }
577 
578 	  /* Copy if needed */
579 	  if (!copied)
580 	    {
581 	      if (res->xrm_type == QString)
582 		*((String *)((char *)GetPtr(rend) + res->xrm_offset)) =
583 		  value.addr;
584 	      else if (value.addr != NULL)
585 		memcpy(((char *)GetPtr(rend) + res->xrm_offset),
586 		       value.addr, res->xrm_size);
587 	      else
588 		bzero(((char *)GetPtr(rend) + res->xrm_offset), res->xrm_size);
589 	    }
590 
591 	}
592     }
593   if (searchList != stackSearchList) XtFree((char *)searchList);
594 
595 #ifdef XTHREADS
596   _XmProcessUnlock();
597   if (app) {
598       _XmAppUnlock(app);
599   }
600 #endif
601   return(got_one);
602 }
603 
604 /* Sets all resources to defaults from resource list. */
605 static void
SetDefault(XmRendition rend)606 SetDefault(XmRendition rend)
607 {
608   /* A more robust implementation of this routine would to to loop
609    * over _XmRenditionResources and use CopyFromArg to reset values
610    * in rend, but to improve performance we use direct assignments.
611    */
612 
613   if (rend == NULL) return;
614 
615 #ifdef	USE_XFT
616   memset (&(_XmRendXftFG(rend)), 0, sizeof (XftColor));
617   memset (&(_XmRendXftBG(rend)), 0, sizeof (XftColor));
618 #endif
619 
620   /* Leave _XmRendFontOnly unchanged.	 */
621   /* Leave _XmRendRefcount unchanged.	 */
622   _XmRendLoadModel(rend)      = DEFAULT_loadModel;
623   _XmRendTag(rend)	      = DEFAULT_tag;
624   _XmRendFontName(rend)	      = DEFAULT_fontName;
625   _XmRendFontType(rend)	      = DEFAULT_fontType;
626   _XmRendFont(rend)	      = DEFAULT_font;
627   /* Leave _XmRendDisplay unchanged.	 */
628   /* Leave _XmRendGC unchanged.		 */
629   /* Leave _XmRendTags unchanged.	 */
630   /* Leave _XmRendCount unchanged.	 */
631   /* Leave _XmRendHadEnds unchanged.	 */
632   _XmRendTabs(rend)	      = DEFAULT_tabs;
633   _XmRendBG(rend)	      = DEFAULT_background;
634   _XmRendFG(rend)	      = DEFAULT_foreground;
635   _XmRendUnderlineType(rend)  = DEFAULT_underlineType;
636   _XmRendStrikethruType(rend) = DEFAULT_strikethruType;
637   _XmRendBGState(rend)	      = DEFAULT_backgroundState;
638   _XmRendFGState(rend)	      = DEFAULT_foregroundState;
639 
640 #ifdef	USE_XFT
641   _XmRendXftFG (rend).color.alpha = 0xFFFF; /*TODO: it is really needed? (yura)*/
642   _XmRendXftBG (rend).color.alpha = 0xFFFF; /*TODO: it is really needed? (yura)*/
643   _XmRendXftFont(rend) = DEFAULT_xftFont;
644   _XmRendPattern(rend) = NULL;
645   _XmRendFontStyle(rend) = DEFAULT_fontStyle;
646   _XmRendFontFoundry(rend) = DEFAULT_fontFoundry;
647   _XmRendFontEncoding(rend) = DEFAULT_fontEncoding;
648   _XmRendFontSize(rend) = DEFAULT_fontSize;
649   _XmRendPixelSize(rend) = 0;
650   _XmRendFontSlant(rend) = 0;
651   _XmRendFontSpacing(rend) = 0;
652   _XmRendFontWeight(rend) = 0;
653 #endif
654 }
655 
656 /* Extern function to pick out display from rendertable. */
657 Display *
_XmRenderTableDisplay(XmRenderTable table)658 _XmRenderTableDisplay(XmRenderTable table)
659 {
660   return(_XmRTDisplay(table));
661 }
662 
663 /* Find a rendition in table with matching tag.  Call callback if not */
664 /* found and callback available.  Fail if need_font is true and */
665 /* rendition found does not provide font. */
666 XmRendition
_XmRenderTableFindRendition(XmRenderTable table,XmStringTag tag,int cached_tag,int need_font,int call,short * index)667 _XmRenderTableFindRendition(XmRenderTable table,
668 			    XmStringTag tag,
669 #if NeedWidePrototypes
670 			    int cached_tag,
671 			    int need_font,
672 			    int call,
673 #else
674 			    Boolean cached_tag,
675 			    Boolean need_font,
676 			    Boolean call,
677 #endif /* NeedWidePrototypes */
678 			    short *index)
679 {
680   int				i, j;
681   XmRendition			rend;
682   Boolean			hit = FALSE;
683   XmDisplayCallbackStruct	cb;
684   XmDisplay			dsp;
685   XmRenderTable			copy;
686 
687   if ((table == NULL) || (tag == NULL)) return(NULL);
688 
689 
690   for (;;) /* May have to try twice */
691     {
692       for (i = 0; i < _XmRTCount(table); i++)
693 	{
694 	  rend = _XmRTRenditions(table)[i];
695 
696 	  if ((cached_tag) ?
697 	      (_XmRendTag(rend) == tag) :
698 	      (strcmp(_XmRendTag(rend), tag) == 0))
699 	    {
700 	      hit = TRUE;
701 
702 	      if ((_XmRendFont(rend) == NULL) && (_XmRendXftFont (rend) == NULL) &&
703 		  NameIsString(_XmRendFontName(rend)))
704 		{
705 		  if (_XmRendLoadModel(rend) == XmLOAD_DEFERRED)
706 		    _XmRendLoadModel(rend) = XmLOAD_IMMEDIATE;
707 
708 		  ValidateAndLoadFont(rend, _XmRendDisplay(rend));
709 
710 		  if (need_font && (_XmRendFont(rend) == NULL &&
711                       _XmRendXftFont(rend) == NULL))
712 		    break;
713 		}
714 
715 	      if (index != NULL) *index = i;
716 	      return(rend);
717 	    }
718 	}
719 
720       /* Are we done? */
721       if (hit || !call) break;
722 
723       call = FALSE;
724 
725       /* Call callback */
726       if (_XmRTDisplay(table) != NULL)
727 	{
728 	  dsp = (XmDisplay) XmGetXmDisplay(_XmRTDisplay(table));
729 
730 	  /* CR 7964: XtHasCallbacks is surprisingly expensive, */
731 	  /*	so we use a conservative approximation here. */
732 	  if (dsp && dsp->display.noRenditionCallback)
733 	    {
734 	      copy = XmRenderTableCopy(table, NULL, 0);
735 
736 	      cb.reason = XmCR_NO_RENDITION;
737 	      cb.event = NULL;
738 	      cb.render_table = copy;
739 	      cb.tag = tag;
740 
741 	      XtCallCallbackList((Widget)dsp,
742 				 dsp->display.noRenditionCallback,
743 				 &cb);
744 
745 	      if (cb.render_table != copy)
746 		{
747 		  /* Callback mutated table.  Update table with */
748 		  /* substitution and search again. */
749 
750 		  for (j = 0; j < _XmRTCount(table); j++)
751 		    if (FreeRendition(_XmRTRenditions(table)[j]))
752 		      FreeHandle(_XmRTRenditions(table)[j]);
753 
754 		  if (_XmRTRefcountDec(table) == 0)
755 		    XtFree((char *)GetPtr(table));
756 
757 		  SetPtr(table, GetPtr(cb.render_table));
758 		  FreeHandle(cb.render_table);
759 		}
760 	      else break;
761 	    }
762 	  else break;
763 	}
764       else break;
765     }
766 
767   /* Didn't find it. */
768   if (index != NULL) *index = -1;
769   return(NULL);
770 }
771 
772 /* If to has resource unset and from has it set, set in to. */
773 static void
SetRend(XmRendition to,XmRendition from)774 SetRend(XmRendition to,
775 	XmRendition from)
776 {
777   if (NameIsString(_XmRendFontName(from)) &&
778       !NameIsString(_XmRendFontName(to)))
779     _XmRendFontName(to) = _XmRendFontName(from);
780   if ((_XmRendFontType(from) != XmAS_IS) &&
781       (_XmRendFontType(to) == XmAS_IS))
782     _XmRendFontType(to) = _XmRendFontType(from);
783   if ((_XmRendLoadModel(from) != XmAS_IS) &&
784       (_XmRendLoadModel(to) == XmAS_IS))
785     _XmRendLoadModel(to) = _XmRendLoadModel(from);
786   if ((_XmRendFont(from) != NULL) &&
787       ((unsigned int)(unsigned long)_XmRendFont(to) == XmAS_IS))
788     _XmRendFont(to) = _XmRendFont(from);
789   if (ListIsList(_XmRendTabs(from)) &&
790       !ListIsList(_XmRendTabs(to)))
791     _XmRendTabs(to) = _XmRendTabs(from);
792 #if USE_XFT
793   if ((_XmRendFG(from) != XmUNSPECIFIED_PIXEL) &&
794       (_XmRendFG(to) == XmUNSPECIFIED_PIXEL))
795     {
796 #ifdef FIX_1536
797       _XmRendFG(to) = _XmRendFG(from);
798       _XmRendXftFG(to) = GetCachedXftColor(_XmRendDisplay(to), _XmRendFG(to));
799 #else
800       XColor xcolor;
801       _XmRendFG(to) = _XmRendFG(from);
802       xcolor.pixel = _XmRendFG(to);
803       XQueryColor(_XmRendDisplay(to), DefaultColormapOfScreen(
804                   DefaultScreenOfDisplay(_XmRendDisplay(to))), &xcolor);
805       /* doesn't needed  (_XmRendXftFG (to)).pixel = xcolor.pixel; */
806       (_XmRendXftFG(to)).color.red = xcolor.red;
807       (_XmRendXftFG(to)).color.green = xcolor.green;
808       (_XmRendXftFG(to)).color.blue = xcolor.blue;
809       (_XmRendXftFG(to)).color.alpha = 0xFFFF;
810 #endif
811     }
812   if ((_XmRendBG(from) != XmUNSPECIFIED_PIXEL) &&
813       (_XmRendBG(to) == XmUNSPECIFIED_PIXEL))
814     {
815 #ifdef FIX_1536
816       _XmRendBG(to) = _XmRendBG (from);
817       _XmRendXftBG(to) = GetCachedXftColor(_XmRendDisplay(to), _XmRendBG(to));
818 #else
819       XColor xcolor;
820       _XmRendBG(to) = _XmRendBG (from);
821       xcolor.pixel = _XmRendBG (to);
822       XQueryColor(_XmRendDisplay(to), DefaultColormapOfScreen(
823                   DefaultScreenOfDisplay(_XmRendDisplay(to))), &xcolor);
824       /* doesn't needed  (_XmRendXftBG (to)).pixel = xcolor.pixel; */
825       (_XmRendXftBG(to)).color.red = xcolor.red;
826       (_XmRendXftBG(to)).color.green = xcolor.green;
827       (_XmRendXftBG(to)).color.blue = xcolor.blue;
828       (_XmRendXftBG(to)).color.alpha = 0xFFFF;
829 #endif
830     }
831   if ((_XmRendXftFont (from) != NULL) &&
832       ((unsigned int) (unsigned long) _XmRendXftFont (to) == XmAS_IS))
833     _XmRendXftFont (to) = _XmRendXftFont (from);
834   if ((_XmRendFontStyle (from) != NULL) && _XmRendFontStyle (to) == NULL)
835     _XmRendFontStyle (to) = _XmRendFontStyle (from);
836   if ((_XmRendFontFoundry (from) != NULL) && _XmRendFontFoundry (to) == NULL)
837     _XmRendFontFoundry (to) = _XmRendFontFoundry (from);
838   if ((_XmRendFontEncoding (from) != NULL) && _XmRendFontEncoding (to) == NULL)
839     _XmRendFontEncoding (to) = _XmRendFontEncoding (from);
840   if (_XmRendFontSize (to) == 0)
841     _XmRendFontSize (to) = _XmRendFontSize (from);
842 #else
843   if ((_XmRendFG(from) != XmUNSPECIFIED_PIXEL) &&
844       (_XmRendFG(to) == XmUNSPECIFIED_PIXEL))
845     _XmRendFG(to) = _XmRendFG (from);
846   if ((_XmRendBG(from) != XmUNSPECIFIED_PIXEL) &&
847       (_XmRendBG(to) == XmUNSPECIFIED_PIXEL))
848     _XmRendBG(to) = _XmRendBG (from);
849 #endif
850   if ((_XmRendUnderlineType(from) != XmAS_IS) &&
851       (_XmRendUnderlineType(to) == XmAS_IS))
852     _XmRendUnderlineType(to) = _XmRendUnderlineType(from);
853   if ((_XmRendStrikethruType(from) != XmAS_IS) &&
854       (_XmRendStrikethruType(to) == XmAS_IS))
855     _XmRendStrikethruType(to) = _XmRendStrikethruType(from);
856 }
857 
858 /* Check that all resources are not default values. */
859 static Boolean
RendComplete(XmRendition rend)860 RendComplete(XmRendition rend)
861 {
862   return(((unsigned int)(unsigned long)_XmRendFontName(rend) != XmAS_IS) &&
863 	 (_XmRendFontType(rend) != XmAS_IS) &&
864 	 (_XmRendLoadModel(rend) != XmAS_IS) &&
865 	 (
866 	  ((unsigned int) (unsigned long) _XmRendFont (rend) != XmAS_IS)
867 #ifdef USE_XFT
868             || ((unsigned int) (unsigned long) _XmRendXftFont (rend) != XmAS_IS)
869 #endif
870          ) &&
871 	 ((unsigned int)(unsigned long)_XmRendTabs(rend) != XmAS_IS) &&
872 	 (_XmRendFG(rend) != XmUNSPECIFIED_PIXEL) &&
873 	 (_XmRendBG(rend) != XmUNSPECIFIED_PIXEL) &&
874 	 (_XmRendUnderlineType(rend) != XmAS_IS) &&
875 	 (_XmRendStrikethruType(rend) != XmAS_IS));
876 }
877 
878 /* Search rt for all renditions matching tags, successively merging */
879 /* resource values in scr rendition. */
880 /*ARGSUSED*/
881 XmRendition
_XmRenditionMerge(Display * d,XmRendition * scr,XmRendition base_rend,XmRenderTable rt,XmStringTag base_tag,XmStringTag * tags,unsigned int tag_count,unsigned int copy)882 _XmRenditionMerge(Display *d,	/* unused */
883 		  XmRendition *scr,
884 		  XmRendition base_rend,
885 		  XmRenderTable rt,
886 		  XmStringTag base_tag,
887 		  XmStringTag *tags,
888 #if NeedWidePrototypes
889 		  unsigned int tag_count,
890 		  unsigned int copy
891 #else
892 		  unsigned short tag_count,
893 		  Boolean copy
894 #endif /* NeedWidePrototypes */
895 		  )
896 {
897   XmRendition 	rend, tmp;
898   int 		i;
899 
900   if (scr == NULL)
901     {
902       rend = XmRenditionCreate(NULL, XmS, NULL, 0); /* Create new */
903     }
904   else
905     {
906       rend = *scr;
907       if (copy)
908 	{
909 	  if (NameIsString(_XmRendFontName(rend)))
910 	    XtFree(_XmRendFontName(rend));
911 	  if (ListIsList(_XmRendTabs(rend)))
912 	    XmTabListFree(_XmRendTabs(rend));
913 	}
914       SetDefault(rend);			  /* Reset state */
915     }
916 
917   for (i = (tag_count - 1); i >= 0; i--)
918     {
919       tmp = _XmRenderTableFindRendition(rt, tags[i], TRUE, FALSE, TRUE, NULL);
920       if (tmp == NULL) continue;
921 
922       SetRend(rend, tmp);
923       if (RendComplete(rend)) break;
924     }
925 
926   if (!RendComplete(rend))
927     {
928       short index;
929 
930       _XmRenderTableFindFallback(rt, base_tag, TRUE, &index, &tmp);
931       if (tmp != NULL) SetRend(rend, tmp);
932     }
933 
934   if (base_rend != NULL)
935     {
936       SetRend(rend, base_rend);
937 
938       if (_XmRendFGState(base_rend) == XmFORCE_COLOR)
939 #if USE_XFT
940 	_XmRendXftFG(rend) = _XmRendXftFG(base_rend);
941 #else
942 	_XmRendFG(rend) = _XmRendFG(base_rend);
943 #endif
944 
945       if (_XmRendBGState(base_rend) == XmFORCE_COLOR)
946 	_XmRendBG(rend) = _XmRendBG(base_rend);
947     }
948 
949   CleanupResources(rend, copy);
950 
951   return(rend);
952 }
953 
954 
955 /****************
956  * If the cached_tag flag is true, _XmRenderTableFindFallback assumes that the
957  *   tag pointer is a pointer out of the (local) tag cache.
958  *   Since XmRenditionCreate also uses tag pointers out of this cache,
959  *   a string compare is avoided by simply comparing pointer values.
960  ****************/
961 extern Boolean
_XmRenderTableFindFallback(XmRenderTable rendertable,XmStringTag tag,int cached_tag,short * indx,XmRendition * rend_ptr)962 _XmRenderTableFindFallback(
963         XmRenderTable rendertable,
964         XmStringTag tag,
965 #if NeedWidePrototypes
966         int cached_tag,
967 #else
968         Boolean cached_tag,
969 #endif /* NeedWidePrototypes */
970         short *indx,
971 	XmRendition *rend_ptr )
972 {
973   XmStringTag     search_cset = NULL;
974 
975   *indx = -1 ;
976 
977   if ((rendertable != NULL) && (_XmRTCount(rendertable) == 0))
978     {
979       *rend_ptr = NULL;
980       return(FALSE);
981     }
982 
983   if (rendertable != NULL)
984     {
985       if (tag != NULL)
986 	{
987 	  if (cached_tag)			  /* No XmSTRING_DEFAULT_CHARSET */
988 	    {
989 	      *rend_ptr = (XmRendition)
990 		_XmRenderTableFindRendition(rendertable, tag, TRUE, TRUE, FALSE,
991 					    indx);
992 	      if (*rend_ptr != NULL) return(TRUE);
993 	    }
994 	  else
995 	    {
996 	      XmStringTag       curtag;
997 
998 	      if ((strcmp(tag, XmSTRING_DEFAULT_CHARSET) == 0))
999 		curtag = _XmStringGetCurrentCharset();
1000 	      else curtag = tag;
1001 
1002 	      *rend_ptr = (XmRendition)
1003 		_XmRenderTableFindRendition(rendertable, curtag, FALSE, TRUE, FALSE,
1004 					    indx);
1005 
1006 	      if (*rend_ptr != NULL) return(TRUE);
1007 	    }
1008 
1009 	  /* Didn't find a match.  See if tag is one of the defaults
1010 	     and search for the other. */
1011 	  if (_XmStringIsCurrentCharset(tag))
1012 	    {
1013 	      search_cset = XmFONTLIST_DEFAULT_TAG;
1014 
1015 	      *rend_ptr = (XmRendition)
1016 		_XmRenderTableFindRendition(rendertable, search_cset, TRUE,
1017 					    TRUE, FALSE, indx);
1018 
1019 	      if (*rend_ptr != NULL) return(TRUE);
1020 	    }
1021 	  else if ((tag == XmFONTLIST_DEFAULT_TAG) ||
1022 		   (strcmp(tag, XmFONTLIST_DEFAULT_TAG) == 0))
1023 	    {
1024 	      search_cset = _XmStringGetCurrentCharset();
1025 
1026 	      *rend_ptr = (XmRendition)
1027 		_XmRenderTableFindRendition(rendertable, search_cset, FALSE,
1028 					    TRUE, FALSE, indx);
1029 
1030 	      if (*rend_ptr != NULL) return(TRUE);
1031 	    }
1032 	}
1033 
1034       /* Otherwise pick up first font(set) if tag a default value. */
1035       if ((tag == NULL) ||
1036 	  (tag == XmFONTLIST_DEFAULT_TAG) ||
1037 	  (strcmp(tag, XmFONTLIST_DEFAULT_TAG) == 0) ||
1038 	  _XmStringIsCurrentCharset(tag))
1039 	return(_XmRenderTableFindFirstFont(rendertable, indx, rend_ptr));
1040     }
1041   *rend_ptr = NULL;
1042   *indx = -1;
1043   return(FALSE);
1044 }
1045 
1046 extern Boolean
_XmRenderTableFindFirstFont(XmRenderTable rendertable,short * indx,XmRendition * rend_ptr)1047 _XmRenderTableFindFirstFont(XmRenderTable rendertable,
1048 			    short *indx,
1049 			    XmRendition *rend_ptr)
1050 {
1051   int i, f_idx = -1, fs_idx = -1;
1052 #ifdef USE_XFT
1053   int xft_idx = -1;
1054 #endif
1055 
1056   for (i = _XmRTCount(rendertable) - 1; i >= 0; i--)
1057     {
1058       *rend_ptr = _XmRTRenditions(rendertable)[i];
1059 
1060       if (_XmRendFont(*rend_ptr) != NULL)
1061       {
1062 	if (_XmRendFontType(*rend_ptr) == XmFONT_IS_FONT) f_idx = i;
1063 	else if (_XmRendFontType(*rend_ptr) == XmFONT_IS_FONTSET) fs_idx = i;
1064 #ifdef USE_XFT
1065       } else if (_XmRendXftFont(*rend_ptr) != NULL) {
1066         if (_XmRendFontType(*rend_ptr) == XmFONT_IS_XFT) xft_idx = i;
1067 #endif
1068       }
1069   }
1070 #ifdef USE_XFT
1071   if (xft_idx >= 0)
1072     {
1073       *rend_ptr = _XmRTRenditions (rendertable)[xft_idx];
1074       *indx = xft_idx;
1075     }
1076   else
1077 #endif
1078   if (fs_idx >= 0)
1079     {
1080       *rend_ptr = _XmRTRenditions(rendertable)[fs_idx];
1081       *indx = fs_idx;
1082     }
1083   else if (f_idx >= 0)
1084     {
1085       *rend_ptr = _XmRTRenditions(rendertable)[f_idx];
1086       *indx = f_idx;
1087     }
1088   else
1089     {
1090       *rend_ptr = NULL;
1091       *indx = -1;
1092       return(FALSE);
1093     }
1094 
1095   return(TRUE);
1096 }
1097 
1098 /* Put value of every resource in fromRend into toRend, copying where */
1099 /* necessary. */
1100 static void
CopyInto(XmRendition toRend,XmRendition fromRend)1101 CopyInto(XmRendition toRend,
1102 	 XmRendition fromRend)
1103 {
1104   _XmRendTag(toRend) = _XmStringCacheTag(_XmRendTag(fromRend),
1105 					 XmSTRING_TAG_STRLEN);
1106   /* CR 7890 - the fontName might be XmAS_IS here - if so, we
1107    ** obviously don't want to do an XtNewString (implicit strcpy)
1108    */
1109   if (!NameIsString(_XmRendFontName(fromRend)))
1110     _XmRendFontName(toRend) = NULL;
1111   else
1112     _XmRendFontName(toRend) = XtNewString(_XmRendFontName(fromRend));
1113   _XmRendFontType(toRend) = _XmRendFontType(fromRend);
1114   _XmRendLoadModel(toRend) = _XmRendLoadModel(fromRend);
1115   _XmRendFont(toRend) = _XmRendFont(fromRend);
1116   _XmRendDisplay(toRend) = _XmRendDisplay(fromRend);
1117 
1118   if (!ListIsList(_XmRendTabs(fromRend)))
1119     _XmRendTabs(toRend) = NULL;
1120   else
1121     _XmRendTabs(toRend) = XmTabListCopy(_XmRendTabs(fromRend), 0, 0);
1122 #if USE_XFT
1123   _XmRendXftFont (toRend) = _XmRendXftFont (fromRend);
1124   _XmRendXftBG (toRend) = _XmRendXftBG (fromRend);
1125   _XmRendXftFG (toRend) = _XmRendXftFG (fromRend);
1126   _XmRendFontStyle (toRend) = _XmRendFontStyle (fromRend);
1127   _XmRendFontFoundry (toRend) = _XmRendFontFoundry (fromRend);
1128   _XmRendFontEncoding (toRend) = _XmRendFontEncoding (fromRend);
1129   _XmRendFontSize (toRend) = _XmRendFontSize (fromRend);
1130 #else
1131   _XmRendBG (toRend) = _XmRendBG (fromRend);
1132   _XmRendFG (toRend) = _XmRendFG (fromRend);
1133 #endif
1134   _XmRendUnderlineType(toRend) = _XmRendUnderlineType(fromRend);
1135   _XmRendStrikethruType(toRend) = _XmRendStrikethruType(fromRend);
1136 }
1137 
1138 /* As above, except only change resources in toRend that are default. */
1139 static void
MergeInto(XmRendition toRend,XmRendition fromRend)1140 MergeInto(XmRendition toRend,
1141 	 XmRendition fromRend)
1142 {
1143   _XmRendTag(toRend) = _XmStringCacheTag(_XmRendTag(fromRend),
1144 					 XmSTRING_TAG_STRLEN);
1145   if ((_XmRendFontName(toRend) == NULL) &&
1146       NameIsString(_XmRendFontName(fromRend)))
1147     _XmRendFontName(toRend) = XtNewString(_XmRendFontName(fromRend));
1148   if (_XmRendFontType(toRend) == XmAS_IS)
1149     _XmRendFontType(toRend) = _XmRendFontType(fromRend);
1150   if (_XmRendLoadModel(toRend) == XmAS_IS)
1151     _XmRendLoadModel(toRend) = _XmRendLoadModel(fromRend);
1152   if (_XmRendFont(toRend) == NULL)
1153     _XmRendFont(toRend) = _XmRendFont(fromRend);
1154 
1155   if (!ListIsList(_XmRendTabs(toRend)) &&
1156       ListIsList(_XmRendTabs(fromRend)))
1157     _XmRendTabs(toRend) = XmTabListCopy(_XmRendTabs(fromRend), 0, 0);
1158 #if USE_XFT
1159   if (_XmRendXftFont(toRend) == NULL)
1160     _XmRendXftFont(toRend) = _XmRendXftFont(fromRend);
1161   if (_XmRendBG(toRend) == XmUNSPECIFIED_PIXEL)
1162     _XmRendXftBG(toRend) = _XmRendXftBG(fromRend);
1163   if (_XmRendFG(toRend) == XmUNSPECIFIED_PIXEL)
1164     _XmRendXftFG(toRend) = _XmRendXftFG(fromRend);
1165   if (_XmRendFontStyle(toRend) == NULL)
1166     _XmRendFontStyle(toRend) = _XmRendFontStyle(fromRend);
1167   if (_XmRendFontFoundry(toRend) == NULL)
1168     _XmRendFontFoundry(toRend) = _XmRendFontFoundry(fromRend);
1169   if (_XmRendFontEncoding(toRend) == NULL)
1170     _XmRendFontEncoding(toRend) = _XmRendFontEncoding(fromRend);
1171   if (_XmRendFontSize(toRend) == 0)
1172     _XmRendFontSize(toRend) = _XmRendFontSize(fromRend);
1173 #else
1174   if (_XmRendBG(toRend) == XmUNSPECIFIED_PIXEL)
1175     _XmRendBG(toRend) = _XmRendBG (fromRend);
1176   if (_XmRendFG(toRend) == XmUNSPECIFIED_PIXEL)
1177     _XmRendFG(toRend) = _XmRendFG (fromRend);
1178 #endif
1179   if (_XmRendUnderlineType(toRend) == XmAS_IS)
1180     _XmRendUnderlineType(toRend) = _XmRendUnderlineType(fromRend);
1181   if (_XmRendUnderlineType(toRend) == XmAS_IS)
1182     _XmRendStrikethruType(toRend) = _XmRendStrikethruType(fromRend);
1183 }
1184 
1185 /* Make a Clone--new handle and new data structure--of a rendition. */
1186 static XmRendition
CloneRendition(XmRendition rend)1187 CloneRendition(XmRendition rend)
1188 {
1189   _XmRendition 	copy;
1190   XmRendition	copy_handle;
1191 
1192   if (rend == NULL) return(NULL);
1193 
1194   copy = (_XmRendition)XtMalloc(sizeof(_XmRenditionRec));
1195   bzero((char*)copy, sizeof(_XmRenditionRec));
1196   copy_handle = GetHandle(_XmRendition);
1197   SetPtr(copy_handle, copy);
1198 
1199   _XmRendFontOnly(copy_handle) = FALSE;
1200   _XmRendRefcount(copy_handle) = 1;
1201 
1202   CopyInto(copy_handle, rend);
1203   return(copy_handle);
1204 }
1205 
1206 /* Set the old handle to point to a new data structure. */
1207 static XmRendition
RenewRendition(XmRendition rend)1208 RenewRendition(XmRendition rend)
1209 {
1210   _XmRendition copy;
1211 
1212   if (rend == NULL) return(NULL);
1213 
1214   copy = (_XmRendition)XtMalloc(sizeof(_XmRenditionRec));
1215   memcpy((char *)copy, (char *)GetPtr(rend), sizeof(_XmRenditionRec));
1216   SetPtr(rend, copy);
1217 
1218   _XmRendFontOnly(rend) = FALSE;
1219   _XmRendRefcount(rend) = 1;
1220 
1221   return(rend);
1222 }
1223 
1224 /* Allocate a new handle which points to the old data structure with */
1225 /* an incremented refcount. */
1226 static XmRendition
CopyRendition(XmRendition rend)1227 CopyRendition(XmRendition rend)
1228 {
1229   XmRendition	copy;
1230 
1231   if (rend == NULL) return(NULL);
1232 
1233   if (_XmRendRefcountInc(rend) == 0)
1234     {
1235       _XmRendRefcountDec(rend);
1236       return(CloneRendition(rend));
1237     }
1238   else
1239     {
1240       copy = GetHandle(_XmRendition);
1241       SetPtr(copy, GetPtr(rend));
1242       return(copy);
1243     }
1244 }
1245 
1246 /* Increment the refcount.  Clone if overflow. */
1247 static XmRendition
DuplicateRendition(XmRendition rend)1248 DuplicateRendition(XmRendition rend)
1249 {
1250   if (rend == NULL) return(NULL);
1251 
1252   if (_XmRendRefcountInc(rend) == 0)
1253     {
1254       _XmRendRefcountDec(rend);
1255       return(CloneRendition(rend));
1256     }
1257   else
1258     {
1259       return(rend);
1260     }
1261 }
1262 
1263 /* Make a copy of a rendition, *including* the "scratch" info (tags,
1264  * GC, hadEnds).
1265  * Shared indicates whether or not this is a shared copy.
1266  */
1267 XmRendition
_XmRenditionCopy(XmRendition rend,Boolean shared)1268 _XmRenditionCopy(XmRendition rend,
1269 		 Boolean shared)
1270 {
1271   XmRendition toRend;
1272   int i;
1273 
1274   if (rend == NULL) return(NULL);
1275 
1276   if (shared) toRend = CopyRendition(rend);
1277   else toRend = CloneRendition(rend);
1278 
1279   /* If we had to clone, copy the 'scratch' info. */
1280   if (*toRend != *rend)
1281     {
1282       _XmRendGC(toRend) = _XmRendGC(rend);
1283       _XmRendTagCount(toRend) = _XmRendTagCount(rend);
1284       _XmRendHadEnds(toRend) = _XmRendHadEnds(rend);
1285       _XmRendTags(toRend) =
1286 	(XmStringTag *)XtMalloc(sizeof(XmStringTag) * _XmRendTagCount(rend));
1287       for (i = 0; i < _XmRendTagCount(rend); i++)
1288 	_XmRendTags(toRend)[i] = _XmRendTags(rend)[i];
1289     }
1290 
1291   return(toRend);
1292 }
1293 
1294 /* Creates new rendertable, adding any new renditions. */
1295 /* Mutate rendertable.  Copy renditions. */
1296 XmRenderTable
XmRenderTableAddRenditions(XmRenderTable oldtable,XmRendition * renditions,Cardinal rendition_count,XmMergeMode merge_mode)1297 XmRenderTableAddRenditions(XmRenderTable oldtable,
1298 			   XmRendition *renditions,
1299 			   Cardinal rendition_count,
1300 			   XmMergeMode merge_mode)
1301 {
1302   int			i, next;
1303   int			count = rendition_count;
1304   XmRendition		rend, match;
1305   _XmRenderTable	table;
1306   XmRenderTable		newtable, tmptable = NULL;
1307   Boolean		*matches;
1308   short			idx;
1309   XtAppContext		app=NULL;
1310 
1311   if ((renditions == NULL) || (rendition_count == 0))
1312     return(oldtable);
1313 
1314 #ifdef XTHREADS
1315   if (_XmRendDisplay(renditions[0]))
1316 	app = XtDisplayToApplicationContext(_XmRendDisplay(renditions[0]));
1317   if (app) {
1318      _XmAppLock(app);
1319   }
1320   else {
1321      _XmProcessLock();
1322   }
1323 #endif
1324   if (oldtable == NULL)
1325     {
1326       /* Malloc new table */
1327       table =
1328 	(_XmRenderTable)XtMalloc(sizeof(_XmRenderTableRec) +
1329 				(sizeof(XmRendition) *
1330 				 (rendition_count -
1331 				  RENDITIONS_IN_STRUCT)));
1332       oldtable = GetHandle(_XmRenderTable);
1333       SetPtr(oldtable, table);
1334 
1335       _XmRTCount(oldtable) = rendition_count;
1336       _XmRTDisplay(oldtable) = NULL;
1337       _XmRTRefcount(oldtable) = 1;
1338 
1339       /* Copy renditions */
1340       for (i = 0; i < rendition_count; i++)
1341 	{
1342 	  _XmRTRenditions(oldtable)[i] = CopyRendition(renditions[i]);
1343 	  if (_XmRTDisplay(oldtable) == NULL)
1344 	    _XmRTDisplay(oldtable) = _XmRendDisplay(renditions[i]);
1345 	}
1346     }
1347   else
1348     {
1349       matches =
1350 	(Boolean *)ALLOCATE_LOCAL(rendition_count * sizeof(Boolean));
1351       bzero(matches, rendition_count * sizeof(Boolean));
1352 
1353       /* May have to copy table if shared. */
1354       if (_XmRTRefcount(oldtable) > 1)
1355 	{
1356 	  /* Allocate new table */
1357 	  table = (_XmRenderTable)
1358 	    XtMalloc(sizeof(_XmRenderTableRec) +
1359 		     (sizeof(XmRendition) *
1360 		      (_XmRTCount(oldtable) - RENDITIONS_IN_STRUCT)));
1361 
1362 	  newtable = GetHandle(_XmRenderTable);
1363 	  SetPtr(newtable, table);
1364 
1365 	  _XmRTDisplay(newtable) = _XmRTDisplay(oldtable);
1366 	  _XmRTRefcount(newtable) = 1;
1367 
1368 	  /* Move old Renditions. */
1369 	  for (i = 0; i < _XmRTCount(oldtable); i++)
1370 	    _XmRTRenditions(newtable)[i] = _XmRTRenditions(oldtable)[i];
1371 
1372 	  _XmRTCount(newtable) = _XmRTCount(oldtable);
1373 	  _XmRTRefcountDec(oldtable);
1374 
1375 	  /* Free at end so we don't get same memory from malloc. */
1376 	  tmptable = oldtable;
1377 	  oldtable = newtable;
1378 	}
1379 
1380       /* Merge matching renditions */
1381       for (i = 0; i < rendition_count; i++)
1382 	{
1383 	  rend = renditions[i];
1384 
1385 	  match =
1386 	    _XmRenderTableFindRendition(oldtable, _XmRendTag(rend),
1387 					TRUE, FALSE, FALSE, &idx);
1388 	  if ((match != NULL) && (merge_mode != XmDUPLICATE))
1389 	    {
1390 	      /* Merge renditions. */
1391 	      switch (merge_mode)
1392 		{
1393 		case XmMERGE_REPLACE:
1394 		  if (FreeRendition(match)) FreeHandle(match);
1395 		  _XmRTRenditions(oldtable)[idx] =
1396 		    CopyRendition(rend);
1397 		  break;
1398 
1399 		case XmSKIP:
1400 		  break;
1401 
1402 		case XmMERGE_OLD:
1403 		  if (_XmRendRefcount(match) > 1)
1404 		    {
1405 		      match = CloneRendition(match);
1406 		      _XmRTRenditions(oldtable)[idx] = match;
1407 		    }
1408 		  MergeInto(match, rend);
1409 		  break;
1410 
1411 		case XmMERGE_NEW:
1412 		  rend = CloneRendition(rend);
1413 		  MergeInto(rend, match);
1414 		  _XmRTRenditions(oldtable)[idx] = rend;
1415 		  if (FreeRendition(match)) FreeHandle(match);
1416 		  break;
1417 
1418 		default:
1419 		  printf("NYI");
1420 		  break;
1421 		}
1422 
1423 	      matches[i] = TRUE;
1424 	      --count;
1425 	    }
1426 	}
1427 
1428       if (count > 0)				  /* Allocate new table */
1429 	{
1430 	  table = (_XmRenderTable)
1431 	    XtMalloc(sizeof(_XmRenderTableRec) +
1432 		     (sizeof(XmRendition) *
1433 		      (_XmRTCount(oldtable) + count - RENDITIONS_IN_STRUCT)));
1434 	  newtable = GetHandle(_XmRenderTable);
1435 	  SetPtr(newtable, table);
1436 
1437 	  _XmRTDisplay(newtable) = _XmRTDisplay(oldtable);
1438 	  _XmRTRefcount(newtable) = 1;
1439 
1440 	  /* Move old Renditions. */
1441 	  for (i = 0; i < _XmRTCount(oldtable); i++)
1442 	    _XmRTRenditions(newtable)[i] = _XmRTRenditions(oldtable)[i];
1443 
1444 	  /* Copy new renditions. */
1445 	  next = _XmRTCount(oldtable);
1446 
1447 	  for (i = 0; i < rendition_count; i++)
1448 	    {
1449 	      if (!matches[i])
1450 		{
1451 		  _XmRTRenditions(newtable)[next] =
1452 		    CopyRendition(renditions[i]);
1453 		  if (_XmRTDisplay(newtable) == NULL)
1454 		    _XmRTDisplay(newtable) = _XmRTDisplay(oldtable);
1455 		  ++next;
1456 		}
1457 	    }
1458 
1459 	  _XmRTCount(newtable) = _XmRTCount(oldtable) + count;
1460 
1461 	  /* Deallocate oldtable */
1462 	  XtFree((char *)GetPtr(oldtable));
1463 	  FreeHandle(oldtable);
1464 	}
1465       /* Otherwise just return newhandle to oldtable */
1466       else
1467 	{
1468 	  table = GetPtr(oldtable);
1469 	  newtable = GetHandle(_XmRenderTable);
1470 	  SetPtr(newtable, table);
1471 	  FreeHandle(oldtable);
1472 	}
1473 
1474       DEALLOCATE_LOCAL((char *)matches);
1475 
1476       oldtable = newtable;
1477     }
1478 
1479   if (tmptable != NULL) FreeHandle(tmptable);
1480 #ifdef XTHREADS
1481   if (app) {
1482       _XmAppUnlock(app);
1483   }
1484   else {
1485       _XmProcessUnlock();
1486   }
1487 #endif
1488   return(oldtable);
1489 }
1490 
1491 /* Remove matching renditions. */
1492 /* Mutates oldtable, decrements removed renditions. */
1493 XmRenderTable
XmRenderTableRemoveRenditions(XmRenderTable oldtable,XmStringTag * tags,int tag_count)1494 XmRenderTableRemoveRenditions(XmRenderTable oldtable,
1495 			      XmStringTag *tags,
1496 			      int tag_count)
1497 {
1498   XmRenderTable ret_val;
1499 #ifdef XTHREADS
1500   XtAppContext  app=NULL;
1501 
1502   if (_XmRTDisplay(oldtable))
1503 	app = XtDisplayToApplicationContext(_XmRTDisplay(oldtable));
1504   if (app) {
1505     _XmAppLock(app);
1506   }
1507   else {
1508     _XmProcessLock();
1509   }
1510 #endif
1511   ret_val = _XmRenderTableRemoveRenditions(oldtable, tags,tag_count,
1512 				FALSE, XmFONT_IS_FONT, NULL);
1513 #ifdef XTHREADS
1514   if (app) {
1515      _XmAppUnlock(app);
1516   }
1517   else {
1518      _XmProcessUnlock();
1519   }
1520 #endif
1521   return ret_val;
1522 }
1523 
1524 /* Remove matching renditions. */
1525 /* Mutates oldtable, decrements removed renditions. */
1526 /* If chk_font TRUE, checks that font and type also match. */
1527 XmRenderTable
_XmRenderTableRemoveRenditions(XmRenderTable oldtable,XmStringTag * tags,int tag_count,int chk_font,XmFontType type,XtPointer font)1528 _XmRenderTableRemoveRenditions(XmRenderTable oldtable,
1529 			       XmStringTag *tags,
1530 			       int tag_count,
1531 #if NeedWidePrototypes
1532 			       int chk_font,
1533 #else
1534 			       Boolean chk_font,
1535 #endif /* NeedWidePrototypes */
1536 			       XmFontType type,
1537 			       XtPointer font)
1538 {
1539   int			i, j;
1540   int			count;
1541   _XmRenderTable	table;
1542   XmRenderTable		newtable = NULL;
1543 
1544   if ((oldtable == NULL) || (tags == NULL) || (tag_count == 0))
1545     return(oldtable);
1546 
1547   count = 0;
1548 
1549   if (_XmRTRefcount(oldtable) > 1)
1550     {
1551       /* Allocate new table */
1552       table = (_XmRenderTable)
1553 	XtMalloc(sizeof(_XmRenderTableRec) +
1554 		 (sizeof(XmRendition) *
1555 		  (_XmRTCount(oldtable) - RENDITIONS_IN_STRUCT)));
1556 
1557       newtable = GetHandle(_XmRenderTable);
1558       SetPtr(newtable, table);
1559 
1560       _XmRTDisplay(newtable) = _XmRTDisplay(oldtable);
1561       _XmRTRefcount(newtable) = 1;
1562 
1563       /* Move old Renditions. */
1564       for (i = 0; i < _XmRTCount(oldtable); i++)
1565 	_XmRTRenditions(newtable)[i] = _XmRTRenditions(oldtable)[i];
1566       _XmRTCount(newtable) = _XmRTCount(oldtable);
1567 
1568       if (_XmRTRefcountDec(oldtable) == 0)
1569 	XtFree((char *)GetPtr(oldtable));
1570       FreeHandle(oldtable);
1571 
1572       oldtable = newtable;
1573     }
1574   /* Iterate over renditions */
1575   for (i = 0; i < _XmRTCount(oldtable); i++)
1576     {
1577       /* Match against tags */
1578       for (j = 0; j < tag_count; j++)
1579 	{
1580 	  if ((strcmp(_XmRendTag(_XmRTRenditions(oldtable)[i]),
1581 		      tags[j]) == 0) &&
1582 	      (!chk_font ||
1583 	       ((font == _XmRendFont(_XmRTRenditions(oldtable)[i])) &&
1584 		(type == _XmRendFontType(_XmRTRenditions(oldtable)[i])))))
1585 	    {
1586 	      if (FreeRendition(_XmRTRenditions(oldtable)[i]))
1587 		FreeHandle(_XmRTRenditions(oldtable)[i]);
1588 	      _XmRTRenditions(oldtable)[i] = NULL;
1589 	      break;
1590 	    }
1591 	}
1592       if (_XmRTRenditions(oldtable)[i] != NULL)
1593 	{
1594 	  if (count != i)
1595 	    _XmRTRenditions(oldtable)[count] = _XmRTRenditions(oldtable)[i];
1596 
1597 	  count++;
1598 	}
1599     }
1600   if (count == 0)
1601     /* No renditions left. Return NULL. */
1602     {
1603       XmRenderTableFree(oldtable);
1604       return(NULL);
1605     }
1606   else if (count < _XmRTCount(oldtable))
1607     {
1608       /* Realloc table */
1609       table = (_XmRenderTable)XtRealloc((char *)*oldtable,
1610 					sizeof(_XmRenderTableRec) +
1611 					(sizeof(XmRendition) *
1612 					 (count - RENDITIONS_IN_STRUCT)));
1613       if (newtable == NULL)
1614 	{
1615 	  newtable = GetHandle(_XmRenderTable);
1616 	  FreeHandle(oldtable);
1617 	}
1618       SetPtr(newtable, table);
1619 
1620       _XmRTCount(newtable) = count;
1621 
1622       return(newtable);
1623     }
1624   return(oldtable);
1625 }
1626 
1627 static void
CopyFromArg(XtArgVal src,char * dst,unsigned int size)1628 CopyFromArg(XtArgVal src, char *dst, unsigned int size)
1629 {
1630   if (size > sizeof(XtArgVal))
1631     memcpy((char *)dst, (char *)src, (size_t)size);
1632   else {
1633     union {
1634       long	longval;
1635 #ifdef FIX_1152
1636       int	intval;
1637 #endif
1638       short	shortval;
1639       char	charval;
1640       char*	charptr;
1641       XtPointer	ptr;
1642     } u;
1643     char *p = (char*)&u;
1644     if      (size == sizeof(long))	    u.longval = (long)src;
1645 #ifdef FIX_1152
1646     else if (size == sizeof(int))	    u.intval = (int) src;
1647 #endif
1648     else if (size == sizeof(short))	    u.shortval = (short)src;
1649     else if (size == sizeof(char))	    u.charval = (char)src;
1650     else if (size == sizeof(XtPointer))	    u.ptr = (XtPointer)src;
1651     else if (size == sizeof(char*))	    u.charptr = (char*)src;
1652     else				    p = (char*)&src;
1653 
1654     memcpy((char *)dst, p, (size_t)size);
1655   }
1656 } /* CopyFromArg */
1657 
1658 static void
CopyToArg(char * src,XtArgVal * dst,unsigned int size)1659 CopyToArg(char *src, XtArgVal *dst, unsigned int size)
1660 {
1661   if ((void *)(*dst) == NULL) {
1662     /* old GetValues semantics (storing directly into arglists) are bad,
1663      * but preserve for compatibility as long as arglist contains NULL.
1664      */
1665     if	    (size == sizeof(long))	   *dst = (XtArgVal)*(long*)src;
1666 #ifdef FIX_1152
1667     else if (size == sizeof(int))	   *dst = (XtArgVal)*(int*)src;
1668 #endif
1669     else if (size == sizeof(short))    *dst = (XtArgVal)*(short*)src;
1670     else if (size == sizeof(char))	   *dst = (XtArgVal)*(char*)src;
1671     else if (size == sizeof(XtPointer)) *dst = (XtArgVal)*(XtPointer*)src;
1672     else if (size == sizeof(char*))    *dst = (XtArgVal)*(char**)src;
1673     else if (size == sizeof(XtArgVal)) *dst = *(XtArgVal*)src;
1674     else memcpy((char*)dst, (char*)src, (size_t)size);
1675   }
1676   else {
1677     /* proper GetValues semantics: argval is pointer to destination */
1678     if	(size == sizeof(long))	   *((long*)*dst) = *(long*)src;
1679 #ifdef FIX_1152
1680     else if (size == sizeof(int))	*((int*)*dst) = *(int*)src;
1681 #endif
1682     else if (size == sizeof(short))    *((short*)*dst) = *(short*)src;
1683     else if (size == sizeof(char))	   *((char*)*dst) = *(char*)src;
1684     else if (size == sizeof(XtPointer)) *((XtPointer*)*dst) = *(XtPointer*)src;
1685     else if (size == sizeof(char*))    *((char**)*dst) = *(char**)src;
1686     else if (size == sizeof(XtArgVal)) *((XtArgVal*)*dst)= *(XtArgVal*)src;
1687     else memcpy((char *)*dst, (char *)src, (size_t)size);
1688   }
1689 } /* CopyToArg */
1690 
1691 /* Copies renditions matching tags to a new table. */
1692 /* If all renditions copied then duplicate rendertable, duplicate */
1693 /* renditions.  Otherwise, mutate rendertable, duplicate renditions. */
1694 XmRenderTable
XmRenderTableCopy(XmRenderTable table,XmStringTag * tags,int tag_count)1695 XmRenderTableCopy(XmRenderTable table,
1696 		  XmStringTag *tags,
1697 		  int tag_count)
1698 {
1699   XmRenderTable		rt = NULL;
1700   _XmRenderTable	t = NULL;
1701   int			i, j, count;
1702   int			size;
1703   XmRendition		rend = NULL;
1704   XtAppContext		app = NULL;
1705 
1706   if (table == NULL) return((XmRenderTable)NULL);
1707 
1708 #ifdef XTHREADS
1709   if (_XmRTDisplay(table))
1710      app = XtDisplayToApplicationContext(_XmRTDisplay(table));
1711   if (app) {
1712      _XmAppLock(app);
1713   }
1714   else {
1715      _XmProcessLock();
1716   }
1717 #endif
1718   count = 0;
1719 
1720   if ((_XmRTRefcountInc(table) == 0) || (tags != NULL))
1721     {
1722       /* Malloc new table */
1723       _XmRTRefcountDec(table);
1724 
1725       if (tag_count > 0)
1726 	size = (sizeof(_XmRendition) * (tag_count - RENDITIONS_IN_STRUCT));
1727       else
1728 	size = (sizeof(_XmRendition) *
1729 		(_XmRTCount(table) - RENDITIONS_IN_STRUCT));
1730 
1731       size = (size < 0) ? 0 : size;
1732 
1733       t = (_XmRenderTable)XtMalloc(sizeof(_XmRenderTableRec) + size);
1734       rt = GetHandle(_XmRenderTable);
1735       SetPtr(rt, t);
1736       _XmRTRefcount(rt) = 1;
1737     }
1738 
1739   if (tags == NULL)
1740     {
1741       /* Increment renditions. */
1742       for (i = 0; i < _XmRTCount(table); i++)
1743 	{
1744 	  rend = DuplicateRendition(_XmRTRenditions(table)[i]);
1745 	  /* Check for overflow. */
1746 	  if (rend != _XmRTRenditions(table)[i]) break;
1747 	}
1748 
1749       if (i < _XmRTCount(table))		  /* Overflow! */
1750 	{
1751 	  /* Malloc new table. */
1752 	  t = (_XmRenderTable)XtMalloc(sizeof(_XmRenderTableRec) +
1753 				       (sizeof(_XmRendition) *
1754 					(_XmRTCount(table) - RENDITIONS_IN_STRUCT)));
1755 	  rt = GetHandle(_XmRenderTable);
1756 	  SetPtr(rt, t);
1757 	  _XmRTRefcount(rt) = 1;
1758 
1759 	  _XmRTCount(rt) = _XmRTCount(table);
1760 
1761 	  /* Move renditions done already. */
1762 	  for (j = 0; j < i; j++)
1763 	    _XmRTRenditions(rt)[j] = _XmRTRenditions(table)[j];
1764 	  _XmRTRenditions(rt)[i] = rend;
1765 	  /* Copy rest */
1766 	  for (j = i + 1; j < _XmRTCount(rt); j++)
1767 	    _XmRTRenditions(rt)[j] = DuplicateRendition(_XmRTRenditions(table)[j]);
1768 	}
1769       else
1770 	{
1771 	  rt = GetHandle(_XmRenderTable);
1772 	  SetPtr(rt, GetPtr(table));
1773 	}
1774     }
1775   else
1776     {
1777       /* Copy matching renditions. */
1778       for (i = 0; i < tag_count; i++)
1779 	{
1780 	  XmRendition match;
1781 
1782 	  match = XmRenderTableGetRendition(table, tags[i]);
1783 
1784 	  if (match != NULL)
1785 	    {
1786 	      _XmRTRenditions(rt)[i] = match;
1787 	      ++count;
1788 	    }
1789 	}
1790 
1791       /* Realloc table */
1792       t = (_XmRenderTable)XtRealloc((char *)t,
1793 				     sizeof(_XmRenderTableRec) +
1794 				     (sizeof(XmRendition) *
1795 				      (count - RENDITIONS_IN_STRUCT)));
1796       SetPtr(rt, t);
1797       _XmRTCount(rt) = count;
1798     }
1799 
1800   _XmRTDisplay(rt) = _XmRTDisplay(table);
1801 
1802 #ifdef XTHREADS
1803   if (app) {
1804 	_XmAppUnlock(app);
1805   }
1806   else {
1807 	_XmProcessUnlock();
1808   }
1809 #endif
1810   return(rt);
1811 }
1812 
1813 /* Decrement rendertable, free if refcount is zero.  XmRenditionFree */
1814 /* renditions. */
1815 void
XmRenderTableFree(XmRenderTable table)1816 XmRenderTableFree(XmRenderTable table)
1817 {
1818   int 		i;
1819 
1820   _XmProcessLock();
1821   for (i = 0; i < _XmRTCount(table); i++)
1822     if (FreeRendition(_XmRTRenditions(table)[i]))
1823       FreeHandle(_XmRTRenditions(table)[i]);
1824 
1825   if (_XmRTRefcountDec(table) == 0)
1826     XtFree((char *)GetPtr(table));
1827 
1828   FreeHandle(table);
1829   _XmProcessUnlock();
1830 }
1831 
1832 /* Get list of tags of all renditions in table. */
1833 int
XmRenderTableGetTags(XmRenderTable table,XmStringTag ** tag_list)1834 XmRenderTableGetTags(XmRenderTable table,
1835 		     XmStringTag **tag_list)
1836 {
1837   int i, ret_val;
1838   XtAppContext          app = NULL;
1839 
1840   if (table == NULL)
1841     {
1842       *tag_list = NULL;
1843       return(0);
1844     }
1845 
1846   app = XtDisplayToApplicationContext(_XmRTDisplay(table));
1847   _XmAppLock(app);
1848   *tag_list =
1849     (XmStringTag *)XtMalloc(sizeof(XmStringTag) * _XmRTCount(table));
1850 
1851   for (i = 0; i < _XmRTCount(table); i++)
1852       (*tag_list)[i] =
1853 	XtNewString(_XmRendTag(_XmRTRenditions(table)[i]));
1854 
1855   ret_val = _XmRTCount(table);
1856   _XmAppUnlock(app);
1857   return ret_val;
1858 }
1859 
1860 /* Returns copy of matching rendition. */
1861 XmRendition
XmRenderTableGetRendition(XmRenderTable table,XmStringTag tag)1862 XmRenderTableGetRendition(XmRenderTable table,
1863 			  XmStringTag tag)
1864 {
1865   XmRendition ret_val;
1866   _XmDisplayToAppContext(_XmRTDisplay(table));
1867 
1868   _XmAppLock(app);
1869   ret_val = CopyRendition(_XmRenderTableFindRendition(table, tag,
1870 			FALSE, FALSE, FALSE, NULL));
1871   _XmAppUnlock(app);
1872   return ret_val;
1873 }
1874 
1875 /* Returns array of copies of matching renditions. */
1876 XmRendition *
XmRenderTableGetRenditions(XmRenderTable table,char ** tags,Cardinal tag_count)1877 XmRenderTableGetRenditions(XmRenderTable table,
1878 			   char **tags,
1879 			   Cardinal tag_count)
1880 {
1881   XmRendition	rend, *rends;
1882   int		i, count;
1883   XtAppContext  app = NULL;
1884 
1885   if ((table == NULL) || (tags == NULL) || (tag_count == 0))
1886       return(NULL);
1887 
1888 #ifdef XTHREADS
1889   if (_XmRTDisplay(table))
1890   {
1891      app = XtDisplayToApplicationContext(_XmRTDisplay(table));
1892      _XmAppLock(app);
1893   }
1894 #endif
1895   rends = (XmRendition *)XtMalloc(tag_count * sizeof(XmRendition));
1896 
1897   count = 0;
1898   for (i = 0; i < tag_count; i++)
1899     {
1900       rend = _XmRenderTableFindRendition(table, tags[i],
1901 					 FALSE, FALSE, FALSE, NULL);
1902       if (rend != NULL)
1903 	{
1904 	  rends[count] = CopyRendition(rend);
1905 	  count++;
1906 	}
1907     }
1908 
1909   if (count < tag_count)
1910     rends = (XmRendition *)XtRealloc((char *)rends, count * sizeof(XmRendition));
1911 
1912 #ifdef XTHREADS
1913   if (app) {
1914      _XmAppUnlock(app);
1915   }
1916 #endif
1917   return(rends);
1918 }
1919 
1920 /* Wrapper for calling XtWarning functions. */
1921 static void
RenditionWarning(char * tag,char * type,char * message,Display * dpy)1922 RenditionWarning(char *tag,
1923 		 char *type,
1924 		 char *message,
1925      		 Display *dpy)
1926 {
1927   char *params[1];
1928   Cardinal num_params = 1 ;
1929   Display *d;
1930 
1931   /* the MotifWarningHandler installed in VendorS.c knows about
1932      this convention */
1933   params[0] = XME_WARNING;
1934 
1935   if (dpy)
1936      d = dpy;
1937   else
1938      d = _XmGetDefaultDisplay();
1939   if (d)
1940     XtAppWarningMsg (XtDisplayToApplicationContext(d),
1941 		     tag, type, "XmRendition",
1942 		     message, params, &num_params);
1943   else XtWarning(message);
1944 }
1945 
1946 /* Replace XmAS_IS and copy as necessary. */
1947 static void
CleanupResources(XmRendition rend,Boolean copy)1948 CleanupResources(XmRendition rend,
1949 		 Boolean copy)
1950 {
1951   if ((unsigned int)(unsigned long)_XmRendFont(rend) == XmAS_IS)
1952     _XmRendFont(rend) = NULL;
1953   else if (_XmRendFontType(rend) == XmAS_IS)
1954     _XmRendFontType(rend) = XmFONT_IS_FONT;
1955 
1956 #ifdef USE_XFT
1957   if ((unsigned int)(unsigned long)_XmRendXftFont (rend) == XmAS_IS)
1958     _XmRendXftFont (rend) = NULL;
1959 #endif
1960 
1961   if (((unsigned int)(unsigned long)_XmRendFontName(rend) == XmAS_IS) ||
1962       (strcmp(_XmRendFontName(rend), XmSXmAS_IS) == 0))
1963     _XmRendFontName(rend) = NULL;
1964   else if (copy)
1965     _XmRendFontName(rend) = XtNewString(_XmRendFontName(rend));
1966 
1967   if ((unsigned int)(unsigned long)_XmRendTabs(rend) == XmAS_IS)
1968     _XmRendTabs(rend) = NULL;
1969   else if (copy)
1970     _XmRendTabs(rend) = XmTabListCopy(_XmRendTabs(rend), 0, 0);
1971 }
1972 
1973 
1974 /* Emit warning and set default if tag is NULL. */
1975 static void
ValidateTag(XmRendition rend,XmStringTag dflt)1976 ValidateTag(XmRendition rend,
1977 	    XmStringTag dflt)
1978 {
1979   if (_XmRendTag(rend) == NULL)
1980     {
1981       RenditionWarning(_XmRendTag(rend), "NO_NULL_TAG",
1982 	NO_NULL_TAG_MSG, _XmRendDisplay(rend));
1983       _XmRendTag(rend) = _XmStringCacheTag(dflt, XmSTRING_TAG_STRLEN);
1984     }
1985 }
1986 
1987 #ifdef FIX_1414
1988 #ifdef USE_XFT
1989 static int
GetSameRenditions(XmRendition * rend_cache,XmRendition rend,int count_rend)1990 GetSameRenditions(XmRendition *rend_cache, XmRendition rend, int count_rend)
1991 {
1992 	int i;
1993 	for (i=0; i<count_rend; i++){
1994 
1995 		if ( rend_cache && (rend_cache[i])
1996 				&& ((((_XmRendFontName(rend) 	&& _XmRendFontName(rend_cache[i]) ) && !strcmp(_XmRendFontName(rend_cache[i]), _XmRendFontName(rend)))
1997 					|| 	(!_XmRendFontName(rend) && !_XmRendFontName(rend_cache[i])))
1998 				&& (((_XmRendFontFoundry(rend) && _XmRendFontFoundry(rend_cache[i])) && !strcmp(_XmRendFontFoundry(rend_cache[i]), _XmRendFontFoundry(rend)))
1999 					|| 	(!_XmRendFontFoundry(rend) && !_XmRendFontFoundry(rend_cache[i])))
2000 				&& (((_XmRendFontEncoding(rend) && _XmRendFontEncoding(rend_cache[i])) && !strcmp(_XmRendFontEncoding(rend_cache[i]), _XmRendFontEncoding(rend)))
2001 					|| 	(!_XmRendFontEncoding(rend) && !_XmRendFontEncoding(rend_cache[i])))
2002 				&& (((_XmRendFontStyle(rend) && _XmRendFontStyle(rend_cache[i])) && !strcmp(_XmRendFontStyle(rend_cache[i]), _XmRendFontStyle(rend)))
2003 					|| 	(!_XmRendFontStyle(rend) && !_XmRendFontStyle(rend_cache[i])) )
2004 				&& _XmRendFontSize(rend) == _XmRendFontSize(rend_cache[i])
2005 				&& _XmRendPixelSize(rend) == _XmRendPixelSize(rend_cache[i])
2006 				&& _XmRendFontSlant(rend) == _XmRendFontSlant(rend_cache[i])
2007 				&& _XmRendFontWeight(rend) == _XmRendFontWeight(rend_cache[i])
2008 				&& _XmRendFontSpacing(rend) == _XmRendFontSpacing(rend_cache[i]))
2009 	   	   )
2010 		{
2011 			return i;
2012 		}
2013 
2014 	}
2015 	return -1;
2016 
2017 }
2018 #endif
2019 #endif
2020 
2021 /* Make sure all the font related resources make sense together and */
2022 /* then load the font specified by fontName if necessary. */
2023 static void
ValidateAndLoadFont(XmRendition rend,Display * display)2024 ValidateAndLoadFont(XmRendition rend, Display *display)
2025 {
2026   XrmString 		locale;
2027   XtPointer 		font;
2028   XrmValue         	args[2];
2029   Cardinal         	num_args = 0;
2030   XrmValue         	fromVal;
2031   XrmValue         	toVal;
2032   Boolean		result = False;
2033 
2034   _XmRendDisplay(rend) = display;
2035 
2036   if (_XmRendLoadModel(rend) != XmLOAD_DEFERRED)
2037     {
2038       XmDisplay			dsp = NULL;
2039       XmDisplayCallbackStruct	cb;
2040 
2041       if ((_XmRendFont(rend) == NULL) &&
2042 #ifdef USE_XFT
2043           (_XmRendXftFont (rend) == NULL) &&
2044 #endif
2045 	  (_XmRendFontName(rend) != NULL))
2046 	{
2047 	  if (_XmRendFontType(rend) != XmAS_IS)
2048 	    {
2049 	      if (display == NULL)
2050 		{
2051 		  RenditionWarning(_XmRendTag(rend), "NULL_DISPLAY",
2052 				   NULL_DISPLAY_MSG, NULL);
2053 		  return;
2054 		}
2055 
2056 	      args[0].addr = (XPointer) &display;
2057 	      args[0].size = sizeof(Display*);
2058 	      num_args++;
2059 
2060 	      fromVal.addr = _XmRendFontName(rend);
2061 	      fromVal.size = strlen(_XmRendFontName(rend));
2062 
2063 	      toVal.addr = (XPointer) &font;
2064 	      toVal.size = sizeof (XtPointer);
2065 
2066 	      switch (_XmRendFontType(rend))
2067 		{
2068 		case XmFONT_IS_FONT:
2069 		  result =
2070 		    XtCallConverter(display, XtCvtStringToFontStruct,
2071 				    args, num_args, &fromVal, &toVal, NULL);
2072 		  break;
2073 		case XmFONT_IS_FONTSET:
2074 		  locale =
2075 		    XrmQuarkToString(XrmStringToQuark(setlocale(LC_ALL, NULL)));
2076 		  args[1].addr = (XPointer) &locale;
2077 		  args[1].size = sizeof(XrmString);
2078 		  num_args++;
2079 
2080 		  result = XtCallConverter (display, XtCvtStringToFontSet, args,
2081 					    num_args, &fromVal, &toVal, NULL);
2082 		  break;
2083 #ifdef USE_XFT
2084 		case XmFONT_IS_XFT:
2085 		  {
2086 		    FcResult res;
2087 		    FcPattern *p;
2088 
2089 #ifdef FIX_1414
2090 						  static XmRendition *rend_cache;
2091 						  static int count_rend=0, num_rend;
2092 						  num_rend = GetSameRenditions(rend_cache, rend, count_rend);
2093 
2094 						  if (num_rend>=0)
2095 							  _XmRendXftFont(rend) = _XmRendXftFont(rend_cache[num_rend]);
2096 						  else
2097 						  {
2098 #endif
2099 		    _XmRendPattern(rend) = FcPatternCreate();
2100 		    if (_XmRendFontName(rend))
2101 		      FcPatternAddString(_XmRendPattern(rend), FC_FAMILY,
2102 		                         (XftChar8 *)_XmRendFontName(rend));
2103 		    if (_XmRendFontFoundry(rend))
2104 		      FcPatternAddString(_XmRendPattern(rend), FC_FOUNDRY,
2105 		                         (XftChar8 *)_XmRendFontFoundry(rend));
2106 		    if (_XmRendFontEncoding(rend))
2107 		      FcPatternAddString(_XmRendPattern(rend), XFT_ENCODING,
2108 		                         (XftChar8 *)_XmRendFontEncoding(rend));
2109 		    if (_XmRendFontStyle(rend))
2110 		      FcPatternAddString(_XmRendPattern(rend), FC_STYLE,
2111 		                         (XftChar8 *)_XmRendFontStyle(rend));
2112 		    if (_XmRendFontSize(rend))
2113 		      FcPatternAddInteger(_XmRendPattern(rend), FC_SIZE,
2114 		                         _XmRendFontSize(rend));
2115 		    if (_XmRendPixelSize(rend))
2116 		      FcPatternAddInteger(_XmRendPattern(rend), FC_PIXEL_SIZE,
2117 		                         _XmRendPixelSize(rend));
2118 		    if (_XmRendFontSlant(rend))
2119 		      FcPatternAddInteger(_XmRendPattern(rend), FC_SLANT,
2120 		                         _XmRendFontSlant(rend));
2121 		    if (_XmRendFontWeight(rend))
2122 		      FcPatternAddInteger(_XmRendPattern(rend), FC_WEIGHT,
2123 		                         _XmRendFontWeight(rend));
2124 		    if (_XmRendFontSpacing(rend))
2125 		      FcPatternAddInteger(_XmRendPattern(rend), FC_SPACING,
2126 		                         _XmRendFontSpacing(rend));
2127                     p = XftFontMatch(display, 0, _XmRendPattern(rend), &res);
2128 #ifdef FIX_1414
2129                     _XmRendXftFont(rend) = XftFontOpenPattern(display, p);
2130 					    		  rend_cache = (XmRendition *) XtRealloc((char *)rend_cache,
2131 					    		    (Cardinal)(sizeof(XmRendition) * (count_rend + 1)));
2132 							  rend_cache[count_rend] =_XmRenditionCopy(rend, TRUE);
2133 							  count_rend++;
2134 						  }
2135 
2136 #else
2137 						  _XmRendXftFont(rend) = XftFontOpenPattern(display, p);
2138 #endif
2139 		  }
2140 		  result = _XmRendXftFont(rend) != NULL;
2141 		  break;
2142 #endif
2143 		default:
2144 		  RenditionWarning(_XmRendTag(rend), "INVALID_TYPE",
2145 				   INVALID_TYPE_MSG,
2146 				   _XmRendDisplay(rend));
2147 		  break;
2148 		}
2149 
2150 	      /* NoFontCallback. */
2151 	      if (!result)
2152 		{
2153 		  if (display != NULL)
2154 		    {
2155 		      dsp = (XmDisplay) XmGetXmDisplay(display);
2156 		      cb.reason = XmCR_NO_FONT;
2157 		      cb.event = NULL;
2158 		      cb.rendition = rend;
2159 		      cb.font_name = _XmRendFontName(rend);
2160 
2161 		      /* We must know for sure whether there are any */
2162 		      /* callbacks, so we have to use XtHasCallbacks. */
2163 		      if (XtHasCallbacks((Widget)dsp, XmNnoFontCallback) ==
2164 			  XtCallbackHasSome)
2165 			{
2166 			  XtCallCallbackList((Widget)dsp,
2167 					     dsp->display.noFontCallback,
2168 					     &cb);
2169 			  return;
2170 			}
2171 		    }
2172 
2173 		  RenditionWarning(_XmRendTag(rend), "CONVERSION_FAILED",
2174 				   CONVERSION_FAILED_MSG,
2175 				   _XmRendDisplay(rend));
2176 		}
2177 	      else
2178 		{
2179 #ifdef USE_XFT
2180 		  if (_XmRendFontType(rend) != XmFONT_IS_XFT)
2181 #endif
2182 		    _XmRendFont(rend) = font;
2183 		}
2184 	    }
2185 	  else
2186 	    {
2187 	      RenditionWarning(_XmRendTag(rend), "NULL_FONT_TYPE",
2188 			       NULL_FONT_TYPE_MSG,
2189 				_XmRendDisplay(rend));
2190 	    }
2191 	}
2192       else if ((_XmRendLoadModel(rend) == XmLOAD_IMMEDIATE) &&
2193 	       (_XmRendFont(rend) == NULL) &&
2194 #ifdef USE_XFT
2195 	       (_XmRendXftFont (rend) == NULL) &&
2196 #endif
2197 	       (_XmRendFontName(rend) == NULL))
2198 	{
2199 	  RenditionWarning(_XmRendTag(rend), "NULL_LOAD_IMMEDIATE",
2200 			   NULL_LOAD_IMMEDIATE_MSG,
2201 			   _XmRendDisplay(rend));
2202 	}
2203     }
2204 }
2205 
2206 /* Create new rendition. */
2207 XmRendition
XmRenditionCreate(Widget widget,XmStringTag tag,ArgList arglist,Cardinal argcount)2208 XmRenditionCreate(Widget widget,
2209 		  XmStringTag tag,
2210 		  ArgList arglist,
2211 		  Cardinal argcount)
2212 {
2213   XmRendition  ret_val;
2214   XtAppContext app=NULL;
2215 
2216   /* If cannot applock, assume its an internal call (from
2217    *	fontlist code, etc.) and already process locked.
2218    */
2219   if (widget)
2220 	app = XtWidgetToApplicationContext(widget);
2221   if (app) {
2222 	_XmAppLock(app);
2223   }
2224   else {
2225 	_XmProcessLock();
2226   }
2227   ret_val = _XmRenditionCreate(NULL, widget, XmS, XmCRenderTable,
2228 			    tag, arglist, argcount, NULL);
2229   if (app) {
2230 	_XmAppUnlock(app);
2231   }
2232   else {
2233 	_XmProcessUnlock();
2234   }
2235 
2236   return ret_val;
2237 }
2238 
2239 /* Internal function.  Called from XmRenditionCreate, resource */
2240 /* converter, and Mrm create function. */
2241 XmRendition
_XmRenditionCreate(Display * display,Widget widget,String resname,String resclass,XmStringTag tag,ArgList arglist,Cardinal argcount,Boolean * in_db)2242 _XmRenditionCreate(Display *display,
2243 		   Widget widget,
2244 		   String resname,
2245 		   String resclass,
2246 		   XmStringTag tag,
2247 		   ArgList arglist,
2248 		   Cardinal argcount,
2249 		   Boolean *in_db)
2250 {
2251   XmRendition	rend;
2252   _XmRendition	rend_int;
2253   Boolean 	result;
2254 
2255   if ((display == NULL) && (widget != NULL))
2256     display = XtDisplayOfObject(widget);
2257 
2258  if ((tag != NULL) &&
2259      (tag != XmFONTLIST_DEFAULT_TAG) &&
2260      (strcmp(tag, XmSTRING_DEFAULT_CHARSET) == 0))
2261    tag = _XmStringGetCurrentCharset();
2262 
2263   /* Allocate rendition. */
2264   rend_int = (_XmRendition)XtMalloc(sizeof(_XmRenditionRec));
2265   bzero((char*)rend_int, sizeof(_XmRenditionRec));
2266   rend = GetHandle(_XmRendition);
2267   SetPtr(rend, rend_int);
2268 
2269   _XmRendRefcount(rend) = 1;
2270 
2271   /* For now, FontOnly renditions aren't implemented. */
2272   _XmRendFontOnly(rend) = FALSE;
2273 
2274   /* X resource DB query */
2275   result =
2276     GetResources(rend, display, widget, resname, resclass, tag,
2277 		 arglist, argcount);
2278 
2279   if (in_db != NULL) *in_db = result;
2280 
2281   if (tag == NULL)
2282     {
2283       if (result == FALSE)
2284 	{
2285 	  XtFree((char *)rend_int);
2286 	  FreeHandle(rend);
2287 	  return(NULL);
2288 	}
2289       else tag = _MOTIF_DEFAULT_LOCALE;
2290     }
2291 
2292   _XmRendTag(rend) = _XmStringCacheTag(tag, XmSTRING_TAG_STRLEN);
2293 
2294   /* Cleanup and validate resources. */
2295 
2296   CleanupResources(rend, TRUE);
2297 
2298   ValidateTag(rend, XmS);
2299 
2300   ValidateAndLoadFont(rend, display);
2301 
2302   return(rend);
2303 }
2304 
2305 /* Mrm create function for rendertables. */
2306 /*ARGSUSED*/
2307 Widget
_XmCreateRenderTable(Widget parent,String name,ArgList arglist,Cardinal argcount)2308 _XmCreateRenderTable(Widget parent,
2309 		     String name, /* unused */
2310 		     ArgList arglist, /* unused */
2311 		     Cardinal argcount)	/* unused */
2312 {
2313   XmRenderTable 	newtable;
2314   _XmRenderTable	table;
2315 
2316   /* Malloc new table */
2317   table = (_XmRenderTable)XtMalloc(sizeof(_XmRenderTableRec));
2318   newtable = GetHandle(_XmRenderTable);
2319   SetPtr(newtable, table);
2320   _XmRTCount(newtable) = 0;
2321   _XmRTRefcount(newtable) = 1;
2322   _XmRTDisplay(newtable) = XtDisplay(parent);
2323 
2324   return((Widget)newtable);
2325 }
2326 
2327 /* Mrm create function for renditions. */
2328 Widget
_XmCreateRendition(Widget parent,String name,ArgList arglist,Cardinal argcount)2329 _XmCreateRendition(Widget parent,
2330 		   String name,
2331 		   ArgList arglist,
2332 		   Cardinal argcount)
2333 {
2334   XmRenderTable		rt = (XmRenderTable)parent;
2335   _XmRenderTable	table;
2336   XmRendition		rend;
2337 
2338   table = GetPtr(rt);
2339 
2340   rend = _XmRenditionCreate(_XmRTDisplay(rt), NULL, XmS, XmCRenderTable,
2341 			    name, arglist, argcount, NULL);
2342 
2343   /* Ignore repeats */
2344   if (_XmRenderTableFindRendition(rt, _XmRendTag(rend),
2345 				  TRUE, FALSE, FALSE, NULL)
2346       != NULL)
2347     {
2348       if (FreeRendition(rend)) FreeHandle(rend);
2349       return((Widget)NULL);
2350     }
2351 
2352   table = (_XmRenderTable)
2353     XtRealloc((char *)table,
2354 	      sizeof(_XmRenderTableRec) +
2355 	      (sizeof(XmRendition) *
2356 	       ((_XmRTCount(rt) + 1) - RENDITIONS_IN_STRUCT)));
2357   SetPtr(rt, table);
2358 
2359   /* Copy new rendition. */
2360   _XmRTRenditions(rt)[_XmRTCount(rt)] = CopyRendition(rend);
2361   _XmRTCount(rt)++;
2362 
2363   return((Widget)rend);
2364 }
2365 
2366 /* Free data structure and any copied values. */
2367 /* TRUE return -> freed.  FALSE -> just decremented. */
2368 static Boolean
FreeRendition(XmRendition rendition)2369 FreeRendition(XmRendition rendition)
2370 {
2371   if (rendition == NULL) return(FALSE);
2372 
2373   if (_XmRendRefcountDec(rendition) == 0)
2374     {
2375       /* CR 7890 - the fontName might be XmAS_IS here */
2376       if (NameIsString(_XmRendFontName(rendition)))
2377 	XtFree(_XmRendFontName(rendition));
2378       if (ListIsList(_XmRendTabs(rendition)))
2379 	XmTabListFree(_XmRendTabs(rendition));
2380       if (_XmRendTagCount(rendition) != 0)
2381 	XtFree((char *)_XmRendTags(rendition));
2382 #ifdef USE_XFT
2383       if (_XmRendXftFont(rendition))
2384         {
2385           XftFontClose(_XmRendDisplay(rendition),
2386               _XmRendXftFont(rendition));
2387           _XmRendXftFont(rendition) = NULL;
2388         }
2389       if (_XmRendPattern(rendition))
2390         {
2391           FcPatternDestroy(_XmRendPattern(rendition));
2392           _XmRendPattern(rendition) = NULL;
2393         }
2394 #endif
2395 
2396       XtFree((char *)GetPtr(rendition));
2397       return(TRUE);
2398     }
2399   return(FALSE);
2400 }
2401 
2402 void
XmRenditionFree(XmRendition rendition)2403 XmRenditionFree(XmRendition rendition)
2404 {
2405   XtAppContext app;
2406 
2407   if (rendition == NULL) return;
2408 
2409   _XmProcessLock();
2410   FreeRendition(rendition);
2411   FreeHandle(rendition);
2412   _XmProcessUnlock();
2413 }
2414 
2415 /* Get resource values from rendition. */
2416 void
XmRenditionRetrieve(XmRendition rendition,ArgList arglist,Cardinal argcount)2417 XmRenditionRetrieve(XmRendition rendition,
2418 		    ArgList arglist,
2419 		    Cardinal argcount)
2420 {
2421   int			i, j;
2422   Arg			*arg;
2423   XtResource		*res;
2424   char			*as_is = (char *)XmAS_IS;
2425 
2426   if (rendition == NULL) return;
2427 
2428   _XmProcessLock();
2429   /* Get resources */
2430   for (i = 0; i < argcount; i++)
2431     {
2432       arg = &(arglist[i]);
2433 
2434       for (j = 0; j < _XmNumRenditionResources; j++)
2435 	{
2436 	  res = &(_XmRenditionResources[j]);
2437 
2438 	  if (strcmp(res->resource_name, arg->name) == 0)
2439 	    {
2440 	      /* CR 7890: Font hook - if there's a fontName but the
2441 	      ** font hasn't been fetched yet, now's a good time to
2442 	      ** get it - if the caller wants to use the font to, say,
2443 	      ** compute font metrics for layout (as CSText does), it won't
2444 	      ** like to get NULL back
2445 	      */
2446 	      if (strcmp(res->resource_name, XmNfont) == 0)
2447 		{
2448 		  if ((_XmRendFont(rendition) == NULL) &&
2449 #ifdef USE_XFT
2450 		      (_XmRendXftFont (rendition) == NULL) &&
2451 #endif
2452 		      (_XmRendFontName(rendition) != NULL))
2453 		    {
2454 		      if (_XmRendLoadModel(rendition) == XmLOAD_DEFERRED)
2455 			_XmRendLoadModel(rendition) = XmLOAD_IMMEDIATE;
2456 		      ValidateAndLoadFont(rendition, _XmRendDisplay(rendition));
2457 		    }
2458 		  if (_XmRendFont (rendition) == NULL
2459 #ifdef USE_XFT
2460 		      && _XmRendXftFont (rendition) == NULL
2461 #endif
2462 		     )
2463 		    CopyToArg((char*)&as_is, &(arg->value), sizeof(char*));
2464 		  else CopyToArg(((char *)GetPtr(rendition) +
2465 				  res->resource_offset),
2466 				 &(arg->value),
2467 				 res->resource_size);
2468 		}
2469 	      else if (((strcmp(res->resource_name, XmNfontName) == 0) &&
2470 		       (_XmRendFontName(rendition) == NULL)) ||
2471 		       ((strcmp(res->resource_name, XmNtabList) == 0) &&
2472 		       (_XmRendTabs(rendition) == NULL)))
2473 		CopyToArg((char*)&as_is, &(arg->value), sizeof(char*));
2474 	      else CopyToArg(((char *)GetPtr(rendition) + res->resource_offset),
2475 			     &(arg->value),
2476 			     res->resource_size);
2477 	      break;
2478 	    }
2479 	}
2480     }
2481     _XmProcessUnlock();
2482 }
2483 
2484 /* Set resources in rendition. */
2485 /* Renew rendition if necessary, then update resources. */
2486 void
XmRenditionUpdate(XmRendition rendition,ArgList arglist,Cardinal argcount)2487 XmRenditionUpdate(XmRendition rendition,
2488 		  ArgList arglist,
2489 		  Cardinal argcount)
2490 {
2491   XmStringTag	oldtag;
2492   char		*oldname;
2493   XtPointer	oldfont;
2494   XmTabList	oldtabs;
2495   int		i, j;
2496   XtResource	*res;
2497   Arg		*arg;
2498   Display	*display = _XmGetDefaultDisplay();
2499   Boolean	can_free;
2500   XtAppContext	app = NULL;
2501 
2502   if (rendition == NULL) return;
2503 
2504 #ifdef XTHREADS
2505   if (_XmRendDisplay(rendition))
2506   {
2507      app = XtDisplayToApplicationContext(_XmRendDisplay(rendition));
2508      _XmAppLock(app);
2509   }
2510   if (_XmRendDisplay(rendition) && (_XmRendDisplay(rendition) !=
2511 			display) )
2512  	display = _XmRendDisplay(rendition);
2513 #endif
2514   /* Save old values to check for dependencies and free memory. */
2515   oldtag = _XmRendTag(rendition);
2516   oldname = _XmRendFontName(rendition);
2517   oldfont = _XmRendFont(rendition);
2518   oldtabs = _XmRendTabs(rendition);
2519   can_free = TRUE;
2520 
2521   /* New memory if needed. */
2522   if (_XmRendRefcount(rendition) > 1)
2523     {
2524       _XmRendRefcountDec(rendition);
2525       RenewRendition(rendition);
2526       can_free = FALSE;
2527     }
2528 
2529   for (i = 0; i < argcount; i++)
2530     {
2531       arg = &(arglist[i]);
2532 
2533       for (j = 0; j < _XmNumRenditionResources; j++)
2534 	{
2535 	  res = &(_XmRenditionResources[j]);
2536 
2537 	  if (strcmp(res->resource_name, arg->name) == 0)
2538 	    {
2539 	      CopyFromArg((arg->value),
2540 			  ((char *)GetPtr(rendition) + res->resource_offset),
2541 			  res->resource_size);
2542 	      break;
2543 	    }
2544 	}
2545     }
2546 
2547   CopyInto(rendition, rendition);
2548 
2549   /** Validate resources **/
2550 
2551   /* CR 7890 - handle cases of fontName == NULL and fontName == XmAS_IS */
2552 
2553   /* If fontName changed but not font, NULL font so it's updated.
2554    ** (first make sure we won't crash on the strcmp) */
2555 
2556   if (NameIsString(oldname) && NameIsString(_XmRendFontName(rendition)))    {
2557     if (strcmp(oldname, _XmRendFontName(rendition)) != 0)
2558       {
2559 	if (oldfont == _XmRendFont(rendition))
2560 	  _XmRendFont(rendition) = NULL;
2561       }
2562     if (can_free) XtFree(oldname);
2563   }
2564   /* Also handle the case where we started with a NULL fontName and
2565    ** had a real fontName specified */
2566   else if ((oldname == NULL) && NameIsString(_XmRendFontName(rendition)))
2567     {
2568       if (oldfont == _XmRendFontName(rendition))
2569 	_XmRendFont(rendition) = NULL;
2570     }
2571 
2572   if (_XmRendFont(rendition) == (XtPointer)XmAS_IS)
2573     _XmRendFont(rendition) = NULL;
2574 
2575   if ((oldtabs != _XmRendTabs(rendition)) && can_free) XmTabListFree(oldtabs);
2576 
2577   ValidateTag(rendition, oldtag);
2578 
2579   ValidateAndLoadFont(rendition, display);
2580 #ifdef XTHREADS
2581   if (app) {
2582      _XmAppUnlock(app);
2583   }
2584 #endif
2585 }
2586 
2587 /*****************************************************************************/
2588 /* XmRenderTableCvtToProp takes a rendertable and converts it to             */
2589 /* an ascii string in the following format:				     */
2590 /* tag : char*								     */
2591 /* font : either fontid (integer) or [ fontid, fontid ... fontid ] or -1     */
2592 /* tablist : [ tab1, ... tabn ] or -1					     */
2593 /* background : pixel or -1						     */
2594 /* foreground : pixel or -1						     */
2595 /* underlineType : integer (from enum in Xm.h ) or -1			     */
2596 /* strikethruType : integer (from enum in Xm.h ) or -1			     */
2597 /* 									     */
2598 /* example:								     */
2599 /* "tag, font, tablist, background, foreground, underlineType, 		     */
2600 /*  strikethruType\n							     */
2601 /* bold, 10000031, -1, -1, -1, -1, -1\n					     */
2602 /* underline, 10000029, -1, -1, -1, -1, -1\n				     */
2603 /* default, 10000029, [ 1.234 1 0 0, 2.43 2 0 2], 1, 2, 0, 0\n		     */
2604 /* japanese, [10000029, 10000030], -1, -1, -1, -1, -1"			     */
2605 /* 									     */
2606 /* The first line gives a complete list of the attributes by name.	     */
2607 /* on the destination side,  attributes which are not understood	     */
2608 /* or are outdated can be ignored.  The conversion of each rendition	     */
2609 /* passes a single "line" which contains the fields in order.		     */
2610 /*****************************************************************************/
2611 
2612 /* Note that this MUST be in the same order as the output conversion
2613    below!! */
2614 static XmConst char *CVTproperties[] = {
2615   XmNtag,
2616   XmNfont,
2617   XmNtabList,
2618   XmNbackground,
2619   XmNforeground,
2620   XmNunderlineType,
2621   XmNstrikethruType,
2622   NULL,
2623   };
2624 
2625 /* Must be big enough to take all the above strings concatenated with
2626    commas separating them */
2627 static char CVTtransfervector[256];
2628 static int CVTtvinited = 0;
2629 
2630 /* Use this macro to encapsulate the code that extends the output
2631    buffer as needed */
2632 #define CVTaddString(dest, src, srcsize)\
2633 {\
2634    if ((chars_used + srcsize) > allocated_size) {\
2635      allocated_size *= 2;\
2636      buffer = XtRealloc(buffer, allocated_size);\
2637    }\
2638    strcat(buffer, src);\
2639    chars_used += srcsize;\
2640 }
2641 
2642 /*ARGSUSED*/
2643 unsigned int
XmRenderTableCvtToProp(Widget widget,XmRenderTable table,char ** prop_return)2644 XmRenderTableCvtToProp(Widget widget, /* unused */
2645 		       XmRenderTable table,
2646 		       char **prop_return)
2647 {
2648   int i;
2649   int allocated_size = 256;
2650   int chars_used = 0, size;
2651   char *buffer;
2652   char *str;
2653   XmRendition rendition;
2654   _XmWidgetToAppContext(widget);
2655 
2656   _XmAppLock(app);
2657   buffer = XtMalloc(allocated_size);
2658 
2659   _XmProcessLock();
2660   if (CVTtvinited == 0) {
2661     CVTtvinited = 1;
2662     strcpy(CVTtransfervector, "");
2663     for(i = 0; CVTproperties[i] != NULL; i++) {
2664       strcat(CVTtransfervector, CVTproperties[i]);
2665       strcat(CVTtransfervector, ",");
2666     }
2667     strcat(CVTtransfervector, "\n");
2668   }
2669 
2670   /* Copy the transfer vector into the output buffer. */
2671   strcpy(buffer, CVTtransfervector);
2672   chars_used = strlen(buffer);
2673   _XmProcessUnlock();
2674 
2675   /* Now iterate over the list of renditions */
2676   for(i = 0; i < _XmRTCount(table); i++) {
2677     char temp[2048];
2678 
2679     rendition = _XmRTRenditions(table)[i];
2680     sprintf(temp, "\"%s\", ", _XmRendTag(rendition));
2681     size = strlen(temp);
2682     CVTaddString(buffer, temp, size);
2683 
2684     if (_XmRendFontType(rendition) == XmAS_IS)
2685       str = "-1, ";
2686     else {
2687       sprintf(temp, "%d \"%s\" %d,", _XmRendFontType(rendition),
2688 	      _XmRendFontName(rendition), _XmRendLoadModel(rendition));
2689       str = temp;
2690     }
2691     size = strlen(str);
2692     CVTaddString(buffer, str, size);
2693 
2694     if ((unsigned int)(unsigned long)_XmRendTabs(rendition) == XmAS_IS ||
2695 	_XmRendTabs(rendition) == NULL)
2696       str = "-1, ";
2697     else {
2698       _XmTab tab;
2699       _XmTabList tlist;
2700       int number;
2701       strcpy(temp, "[ ");
2702       tlist = (_XmTabList) _XmRendTabs(rendition);
2703       number = tlist -> count;
2704       tab = (_XmTab) tlist -> start;
2705       while(number > 0) {
2706 	sprintf(temp, "%s %f %d %d %d, ", temp, tab -> value,
2707 		tab -> units, tab -> alignment, tab -> offsetModel);
2708 	tab = (_XmTab) tab -> next;
2709 	number--;
2710       }
2711       strcat(temp, " ], ");
2712       str = temp;
2713     }
2714     size = strlen(str);
2715     CVTaddString(buffer, str, size);
2716 
2717     if (_XmRendBG(rendition) == XmAS_IS)
2718       str = "-1, ";
2719     else {
2720       sprintf(temp, "%ld, ", _XmRendBG(rendition));
2721       str = temp;
2722     }
2723     size = strlen(str);
2724     CVTaddString(buffer, str, size);
2725 
2726     if (_XmRendFG(rendition) == XmAS_IS)
2727       str = "-1, ";
2728     else {
2729       sprintf(temp, "%ld, ", _XmRendFG(rendition));
2730       str = temp;
2731     }
2732     size = strlen(str);
2733     CVTaddString(buffer, str, size);
2734 
2735     if (_XmRendUnderlineType(rendition) == XmAS_IS)
2736       str = "-1, ";
2737     else {
2738       sprintf(temp, "%d, ", _XmRendUnderlineType(rendition));
2739       str = temp;
2740     }
2741     size = strlen(str);
2742     CVTaddString(buffer, str, size);
2743 
2744     if (_XmRendStrikethruType(rendition) == XmAS_IS)
2745       str = "-1, ";
2746     else {
2747       sprintf(temp, "%d, ", _XmRendStrikethruType(rendition));
2748       str = temp;
2749     }
2750     size = strlen(str);
2751     CVTaddString(buffer, str, size);
2752     CVTaddString(buffer, "\n", size);
2753   }
2754 
2755   /* Return the converted rendertable string */
2756   *prop_return = buffer;
2757 
2758   _XmAppUnlock(app);
2759   /* chars_used is always the size - the NULL terminator */
2760   return(chars_used + 1);
2761 }
2762 
2763 typedef enum {   T_NL, T_INT, T_FLOAT, T_SEP,
2764 		 T_OPEN, T_CLOSE, T_STR, T_EOF } TokenType;
2765 
2766 typedef struct _TokenRec {
2767   TokenType	type;
2768   int		integer;
2769   float		real;
2770   char		*string;
2771 } TokenRec, *Token;
2772 
2773 
2774 #ifndef XTHREADS
2775 static TokenRec reusetoken;
2776 #endif
2777 
2778 static Token
ReadToken(char * string,int * position)2779 ReadToken(char *string, int *position)
2780 {
2781 #ifdef XTHREADS
2782   TokenRec reusetoken;
2783   Token new_token = &reusetoken;
2784 #else
2785   Token new_token = &reusetoken;
2786 #endif
2787   int pos = *position;
2788   int count;
2789 
2790   /* Skip whitespace but not newlines */
2791   while (isspace(string[pos]) && ! (string[pos] == '\n'))
2792     pos++;
2793 
2794   /* Select token type */
2795   switch(string[pos]) {
2796   case '\0':
2797     new_token -> type = T_EOF;
2798     break;
2799   case '\n':
2800     new_token -> type = T_NL;
2801     pos++;
2802     break;
2803   case ',':
2804     new_token -> type = T_SEP;
2805     pos++;
2806     break;
2807   case '[':
2808     new_token -> type = T_OPEN;
2809     pos++;
2810     break;
2811   case ']':
2812     new_token -> type = T_CLOSE;
2813     pos++;
2814     break;
2815   case '"': /* String result */
2816     count = 1;
2817     while (string[pos + count] != '"' &&
2818 	   string[pos + count] != '\0')
2819       count++; /* Scan for end of string */
2820     new_token -> type = T_STR;
2821     new_token -> string = NULL;
2822     count -= 1;
2823     if (count > 0) {
2824       new_token -> string = (char*) XtMalloc(count + 1);
2825       strncpy(new_token -> string, &string[pos + 1], count);
2826       pos += count + 2; /* Move past end quote */
2827       new_token -> string[count] = 0; /* Null terminate */
2828     }
2829     break;
2830   default:
2831     if (isalpha(string[pos])) /* String result */
2832       {
2833 	char temp[80];
2834 	int count;
2835 	for(count = 0;
2836 	    isalpha(string[pos + count]) && count < 79;
2837 	    count++) temp[count] = string[pos + count];
2838 	temp[count] = 0;
2839 	pos += count;
2840 	new_token -> type = T_STR;
2841 	new_token -> string = XtNewString(temp);
2842       }
2843     else
2844       {
2845 	/* start converting a float number.  If it is exactly integer
2846 	   then we return an int,  otherwise return a float */
2847 	double result;
2848 	int intresult;
2849 	char *newpos;
2850 	result=strtod(&(string[pos]), &newpos);
2851 	intresult= (int) result;
2852 	pos = newpos - string;
2853 	if (((double) intresult) == result) /* Integer result */
2854 	  {
2855 	    new_token -> type = T_INT;
2856 	    new_token -> integer = intresult;
2857 	  }
2858 	else
2859 	  {
2860 	    new_token -> type = T_FLOAT;
2861 	    new_token -> real = (float) result;
2862 	  }
2863       }
2864   }
2865 
2866   *position = pos;
2867   return(new_token);
2868 }
2869 
2870 #ifdef	USE_XFT
2871 static struct _XmXftDrawCacheStruct {
2872 	Display	*display;
2873 	Window	window;
2874 	XftDraw	*draw;
2875 } *_XmXftDrawCache = NULL;
2876 static int _XmXftDrawCacheSize = 0;
2877 
2878 static XErrorHandler           oldErrorHandler;
2879 static int xft_error;
2880 
2881 static int
_XmXftErrorHandler(Display * display,XErrorEvent * error)2882 _XmXftErrorHandler(
2883         Display *display,
2884         XErrorEvent *error )
2885 {
2886    (void) fprintf(stderr,
2887    "Ignoring Xlib error: error code %d request code %d\n",
2888    error->error_code,
2889    error->request_code) ;
2890    xft_error = BadWindow;
2891 
2892     /* No exit! - but keep lint happy */
2893 
2894     return 0 ;
2895 }
2896 
2897 XftDraw *
_XmXftDrawCreate(Display * display,Window window)2898 _XmXftDrawCreate(Display *display, Window window)
2899 {
2900 	XftDraw			*draw;
2901 	XWindowAttributes	wa;
2902 	int			i;
2903 	Status status;
2904 
2905 	for (i=0; i<_XmXftDrawCacheSize; i++) {
2906 		if (_XmXftDrawCache[i].display == display &&
2907 		    _XmXftDrawCache[i].window == window) {
2908 			return _XmXftDrawCache[i].draw;
2909 		}
2910 	}
2911 
2912 #ifdef FIX_1444
2913 	if (!(draw = XftDrawCreate(display, window,
2914 	    DefaultVisual(display, DefaultScreen(display)),
2915 	    DefaultColormap(display, DefaultScreen(display)))))
2916             	draw = XftDrawCreateBitmap(display, window);
2917 #else
2918 	oldErrorHandler = XSetErrorHandler (_XmXftErrorHandler);
2919 	xft_error = 0;
2920 	XGetWindowAttributes(display, window, &wa);
2921 	XSetErrorHandler(oldErrorHandler);
2922 	if (xft_error != BadWindow) {
2923 	    draw = XftDrawCreate(display, window,
2924 	        DefaultVisual(display, DefaultScreen(display)),
2925 	        DefaultColormap(display, DefaultScreen(display)));
2926 	} else {
2927             draw = XftDrawCreateBitmap(display, window);
2928         }
2929 #endif
2930 	/* Store it in the cache. Look for an empty slot first */
2931 	for (i=0; i<_XmXftDrawCacheSize; i++)
2932 		if (_XmXftDrawCache[i].display == NULL) {
2933 			_XmXftDrawCache[i].display = display;
2934 			_XmXftDrawCache[i].draw = draw;
2935 			_XmXftDrawCache[i].window = window;
2936 			return draw;
2937 		}
2938 	i = _XmXftDrawCacheSize;	/* Next free index */
2939 	_XmXftDrawCacheSize = _XmXftDrawCacheSize * 2 + 8;
2940 	_XmXftDrawCache = (struct _XmXftDrawCacheStruct *)
2941 		XtRealloc((char *)_XmXftDrawCache,
2942 		sizeof(struct _XmXftDrawCacheStruct) * _XmXftDrawCacheSize);
2943 #ifdef FIX_1449
2944 	memset(_XmXftDrawCache + i, 0, (_XmXftDrawCacheSize - i) * sizeof(*_XmXftDrawCache));
2945 #endif
2946 
2947 	_XmXftDrawCache[i].display = display;
2948 	_XmXftDrawCache[i].draw = draw;
2949 	_XmXftDrawCache[i].window = window;
2950 
2951 	return draw;
2952 }
2953 
2954 void
_XmXftDrawDestroy(Display * display,Window window,XftDraw * draw)2955 _XmXftDrawDestroy(Display *display, Window window, XftDraw *draw)
2956 {
2957     int i;
2958 
2959     for (i=0; i<_XmXftDrawCacheSize; i++)
2960 	if (_XmXftDrawCache[i].display == display &&
2961 	    _XmXftDrawCache[i].window == window) {
2962 	        _XmXftDrawCache[i].display = NULL;
2963 	        _XmXftDrawCache[i].draw = NULL;
2964 	        _XmXftDrawCache[i].window = None;
2965 	        XftDrawDestroy(draw);
2966 	        return;
2967         }
2968     XmeWarning(NULL, "_XmXftDrawDestroy() this should not happen\n");
2969 }
2970 
2971 void
_XmXftDrawString2(Display * display,Window window,GC gc,XftFont * font,int bpc,int x,int y,char * s,int len)2972 _XmXftDrawString2(Display *display, Window window, GC gc, XftFont *font, int bpc,
2973 #if NeedWidePrototypes
2974                 int x, int y,
2975 #else
2976                 Position x, Position y,
2977 #endif
2978                 char *s, int len)
2979 {
2980     XftDraw	*draw = _XmXftDrawCreate(display, window);
2981     XGCValues gc_val;
2982     XColor xcol;
2983     XftColor xftcol;
2984 
2985     XGetGCValues(display, gc, GCForeground, &gc_val);
2986 
2987     xcol.pixel = gc_val.foreground;
2988     XQueryColor(display, DefaultColormap(display,
2989         DefaultScreen(display)), &xcol);
2990     xftcol.color.red = xcol.red;
2991     xftcol.color.blue = xcol.blue;
2992     xftcol.color.green = xcol.green;
2993     xftcol.color.alpha = 0xFFFF;
2994 
2995     switch (bpc)
2996     {
2997 	case 1:
2998 		XftDrawStringUtf8(draw, &xftcol, font,
2999 			x, y, (XftChar8 *)s, len);
3000 		break;
3001 	case 2:
3002 		XftDrawString16(draw, &xftcol, font,
3003 			x, y, (XftChar16 *)s, len);
3004 		break;
3005 	case 4:
3006 		XftDrawString32(draw, &xftcol, font,
3007 			x, y, (XftChar32 *)s, len);
3008 		break;
3009 	default:
3010 		XmeWarning(NULL, "_XmXftDrawString(unsupported bpc)\n");
3011     }
3012 }
3013 
3014 void
_XmXftDrawString(Display * display,Window window,XmRendition rend,int bpc,int x,int y,char * s,int len,int image)3015 _XmXftDrawString(Display *display, Window window, XmRendition rend, int bpc,
3016 #if NeedWidePrototypes
3017                 int x, int y,
3018 #else
3019                 Position x, Position y,
3020 #endif
3021                 char *s, int len,
3022 #if NeedWidePrototypes
3023 		int image
3024 #else
3025 		Boolean image
3026 #endif
3027 		)
3028 {
3029     XftDraw	*draw = _XmXftDrawCreate(display, window);
3030     XftColor    fg_color = _XmRendXftFG(rend);
3031 
3032     if (image)
3033     {
3034         XftColor bg_color = _XmRendXftBG(rend);
3035 	XGlyphInfo ext;
3036 	ext.xOff = 0;
3037 
3038 	switch (bpc)
3039 	{
3040 	    case 1:
3041 	        XftTextExtentsUtf8(display, _XmRendXftFont(rend),
3042 		                (FcChar8*)s, len, &ext);
3043 		break;
3044 	    case 2:
3045 	        XftTextExtents16(display, _XmRendXftFont(rend),
3046 		                 (FcChar16*)s, len, &ext);
3047 		break;
3048 	    case 4:
3049 	        XftTextExtents32(display, _XmRendXftFont(rend),
3050 		                 (FcChar32*)s, len, &ext);
3051 		break;
3052 	}
3053 
3054 	if (_XmRendBG(rend) == XmUNSPECIFIED_PIXEL)
3055 	{
3056 	    XGCValues gc_val;
3057 	    XColor xcol;
3058 
3059 	    XGetGCValues(display, _XmRendGC(rend), GCBackground, &gc_val);
3060 	    xcol.pixel = gc_val.background;
3061             XQueryColor(display, DefaultColormapOfScreen(
3062                   DefaultScreenOfDisplay(display)), &xcol);
3063 	    bg_color.pixel = xcol.pixel;
3064 	    bg_color.color.red = xcol.red;
3065 	    bg_color.color.green = xcol.green;
3066 	    bg_color.color.blue = xcol.blue;
3067 	    bg_color.color.alpha = 0xFFFF;
3068 	}
3069 #ifdef FIX_1451
3070         XftDrawRect(draw, &bg_color, x, y - _XmRendXftFont(rend)->ascent,
3071 	            ext.xOff,
3072 		    _XmRendXftFont(rend)->ascent +
3073 		    _XmRendXftFont(rend)->descent);
3074 #else
3075         XftDrawRect(draw, &bg_color, x - 10, y - _XmRendXftFont(rend)->ascent - 10,
3076 	            ext.xOff +20,
3077 		    _XmRendXftFont(rend)->ascent +
3078 		    _XmRendXftFont(rend)->descent + 20);
3079 #endif
3080     }
3081 
3082     if (_XmRendFG(rend) == XmUNSPECIFIED_PIXEL)
3083     {
3084         XGCValues gc_val;
3085 	XColor xcol;
3086 	XGetGCValues(display, _XmRendGC(rend), GCForeground, &gc_val);
3087 	xcol.pixel = gc_val.foreground;
3088         XQueryColor(display, DefaultColormapOfScreen(
3089               DefaultScreenOfDisplay(display)), &xcol);
3090 	fg_color.pixel = xcol.pixel;
3091 	fg_color.color.red = xcol.red;
3092 	fg_color.color.green = xcol.green;
3093 	fg_color.color.blue = xcol.blue;
3094 	fg_color.color.alpha = 0xFFFF;
3095     }
3096 
3097     switch (bpc)
3098     {
3099 	case 1:
3100 		XftDrawStringUtf8(draw, &fg_color, _XmRendXftFont(rend),
3101 			x, y, (XftChar8 *)s, len);
3102 		break;
3103 	case 2:
3104 		XftDrawString16(draw, &fg_color, _XmRendXftFont(rend),
3105 			x, y, (XftChar16 *)s, len);
3106 		break;
3107 	case 4:
3108 		XftDrawString32(draw, &fg_color, _XmRendXftFont(rend),
3109 			x, y, (XftChar32 *)s, len);
3110 		break;
3111 	default:
3112 		XmeWarning(NULL, "_XmXftDrawString(unsupported bpc)\n");
3113     }
3114 }
3115 
3116 void
_XmXftSetClipRectangles(Display * display,Window window,Position x,Position y,XRectangle * rects,int n)3117 _XmXftSetClipRectangles(Display *display, Window window, Position x, Position y, XRectangle *rects, int n)
3118 {
3119 	XftDraw	*d = _XmXftDrawCreate(display, window);
3120 
3121 	XftDrawSetClipRectangles(d, x, y, rects, n);
3122 }
3123 
3124 #ifdef FIX_1536
3125 static XftColor
GetCachedXftColor(Display * display,Pixel color)3126 GetCachedXftColor(Display *display, Pixel color)
3127 {
3128   static XftColor *color_cache = NULL;
3129   static int colors_count = 0;
3130 
3131   XftColor xftcol = {0, {0,0,0,0xFFFF}};
3132   XColor xcol;
3133   Boolean color_exist = FALSE;
3134   int i;
3135 
3136   if (color_cache != NULL)
3137   {
3138     for (i = 0; i < colors_count; ++i)
3139     {
3140       if (color_cache[i].pixel == color)
3141       {
3142         xftcol = color_cache[i];
3143         color_exist = TRUE;
3144         break;
3145       }
3146     }
3147   }
3148 
3149   if (!color_exist)
3150   {
3151     xcol.pixel = color;
3152     XQueryColor(display, DefaultColormap(display,
3153       DefaultScreen(display)), &xcol);
3154     xftcol.pixel = color;
3155     xftcol.color.red = xcol.red;
3156     xftcol.color.blue = xcol.blue;
3157     xftcol.color.green = xcol.green;
3158     xftcol.color.alpha = 0xFFFF;
3159 
3160     color_cache = (XftColor *) XtRealloc((char *) color_cache,
3161       (Cardinal) (sizeof(XftColor) * (colors_count + 1)));
3162     if (color_cache != NULL)
3163       color_cache[colors_count++] = xftcol;
3164   }
3165 
3166   return xftcol;
3167 }
3168 #endif
3169 
3170 XftColor
_XmXftGetXftColor(Display * display,Pixel color)3171 _XmXftGetXftColor(Display *display, Pixel color)
3172 {
3173 #ifdef FIX_1536
3174     return GetCachedXftColor(display, color);
3175 #else
3176     XColor xcol;
3177     XftColor xftcol;
3178 
3179     xcol.pixel = color;
3180     XQueryColor(display, DefaultColormap(display,
3181         DefaultScreen(display)), &xcol);
3182     xftcol.pixel = color;
3183     xftcol.color.red = xcol.red;
3184     xftcol.color.blue = xcol.blue;
3185     xftcol.color.green = xcol.green;
3186     xftcol.color.alpha = 0xFFFF;
3187     return xftcol;
3188 #endif
3189 }
3190 
3191 #ifdef FIX_1415
_XmXftFontAverageWidth(Widget w,XtPointer f,int * width)3192 void _XmXftFontAverageWidth(Widget w, XtPointer f, int *width)
3193 {
3194 	XftFont *fp = (XftFont *)f;
3195 	static char	*s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
3196 	int l = 62; /* strlen(s) */
3197 	XGlyphInfo	ext;
3198 
3199 	XftTextExtents8(XtDisplay(w), fp, (unsigned char *)s, l, &ext);
3200     if (width)
3201     	*width = ext.width / l;
3202 }
3203 #endif
3204 
3205 #endif
3206 
3207 /*ARGSUSED*/
3208 XmRenderTable
XmRenderTableCvtFromProp(Widget w,char * prop,unsigned int len)3209 XmRenderTableCvtFromProp(Widget w,
3210 			 char *prop,
3211 			 unsigned int len) /* unused */
3212 {
3213   XmRenderTable new_rt;
3214   XmRendition rendition;
3215   XmRendition *rarray;
3216   int rarray_count, rarray_max;
3217   /* These must both be big enough for the number of passed parameters */
3218   char *items[20];
3219   char *name;
3220   Arg args[20];
3221   /* This must be big enough to hold all the strings returned by
3222      readtoken */
3223   char *freelater[5];
3224   int scanpointer, j, count, freecount, i;
3225   Token token;
3226   _XmWidgetToAppContext(w);
3227 
3228   _XmAppLock(app);
3229   new_rt = NULL;
3230   scanpointer = 0;
3231   rarray_max = 10;
3232   rarray_count = 0;
3233   rarray = (XmRendition *) XtMalloc(sizeof(XmRendition) * rarray_max);
3234   name = "";
3235 
3236   for(j = 0; j < 20; j++) items[j] = NULL;
3237   /* Read the list of items */
3238   for(j = 0; j < 20; ) {
3239     token = ReadToken(prop, &scanpointer);
3240     if (token -> type == T_NL) break;
3241     if (token -> type == T_STR) {
3242       items[j] = token -> string;
3243       j++;
3244     }
3245   }
3246 
3247   j = -1;
3248   count = 0;
3249   freecount = 0;
3250   while(True) {
3251     token = ReadToken(prop, &scanpointer);
3252     /* We skip the separators */
3253     while(token -> type == T_SEP &&
3254 	  token -> type != T_EOF)
3255       token = ReadToken(prop, &scanpointer);
3256     if (token -> type == T_EOF) goto finish;
3257 
3258     j++; /* Go to next item in items array */
3259 
3260     if (items[j] == NULL) {
3261       /* End of line processing.  Scan for NewLine */
3262       while(token -> type != T_NL &&
3263 	    token -> type != T_EOF)
3264 	token = ReadToken(prop, &scanpointer);
3265       /* Store rendition */
3266       rendition = XmRenditionCreate(w, name, args, count);
3267       name = "";
3268       count = 0;
3269       /* Reset index into namelist */
3270       j = -1;
3271       /* Free temp strings returned by ReadToken */
3272       for(i = 0; i < freecount; i++) XtFree(freelater[i]);
3273       freecount = 0;
3274       /* Record rendition in array */
3275       if (rarray_count >= rarray_max) {
3276 	/* Extend array if necessary */
3277 	rarray_max += 10;
3278 	rarray = (XmRendition *) XtRealloc((char*) rarray,
3279 					   sizeof(XmRendition) * rarray_max);
3280       }
3281       if (token -> type == T_EOF) goto finish;
3282       rarray[rarray_count] = rendition;
3283       rarray_count++;
3284     } else if (strcmp(items[j], XmNtag) == 0) {
3285       /* Next item should be a string with the name of the new
3286 	 rendition to create */
3287       if (token -> type == T_STR) {
3288 	name = token -> string;
3289 	freelater[freecount] = token -> string; freecount++;
3290       } else {
3291 	goto error;
3292       }
3293     } else if (strcmp(items[j], XmNfont) == 0) {
3294       /* If the next item is a number then we have a font
3295 	 id,  otherwise we are reading in a fontset */
3296       if (token -> type != T_INT) goto error;
3297       if (token -> integer != -1) { /* AS IS */
3298 	XtSetArg(args[count], XmNfontType, token -> integer); count++;
3299 	token = ReadToken(prop, &scanpointer);
3300 	if (token -> type != T_STR) goto error;
3301 	XtSetArg(args[count], XmNfontName, token -> string); count++;
3302 	freelater[freecount] = token -> string; freecount++;
3303 	token = ReadToken(prop, &scanpointer);
3304 	if (token -> type != T_INT) goto error;
3305 	XtSetArg(args[count], XmNloadModel, token -> integer); count++;
3306       }
3307     } else if (strcmp(items[j], XmNtabList) == 0) {
3308       /* This starts with an OPEN then a number of
3309 	 FLOAT INT INT INT then CLOSE and SEP */
3310       if (token -> type == T_INT) { /* Should be AS IS */
3311 	if (token -> integer != -1) goto error;
3312       } else if (token -> type == T_OPEN) {
3313 	float value;
3314 	int units, align;
3315 	XmOffsetModel model;
3316 	XmTabList tablist;
3317 	XmTab tabs[1];
3318 
3319 	tablist = NULL;
3320 	token = ReadToken(prop, &scanpointer);
3321 	while(token -> type != T_CLOSE) {
3322 	  if (token -> type != T_FLOAT &&
3323 	      token -> type != T_INT) goto error;
3324 	  if (token -> type == T_FLOAT)
3325 	    value = token -> real;
3326 	  else
3327 	    value = (float) token -> integer;
3328 	  token = ReadToken(prop, &scanpointer);
3329 	  if (token -> type != T_INT) goto error;
3330 	  units = token -> integer;
3331 	  token = ReadToken(prop, &scanpointer);
3332 	  if (token -> type != T_INT) goto error;
3333 	  align = token -> integer;
3334 	  token = ReadToken(prop, &scanpointer);
3335 	  if (token -> type != T_INT) goto error;
3336 	  model = (XmOffsetModel) token -> integer;
3337 	  tabs[0] = XmTabCreate(value, units, model, align, NULL);
3338 	  tablist = XmTabListInsertTabs(tablist, tabs, 1, 1000);
3339 	  XtFree((char*) tabs[0]);
3340 	  /* Go to next separator to skip unknown future values */
3341 	  while(token -> type != T_SEP)
3342 	    token = ReadToken(prop, &scanpointer);
3343 	  if (token -> type == T_SEP)
3344 	    token = ReadToken(prop, &scanpointer);
3345 	}
3346 	XtSetArg(args[count], XmNtabList, tablist); count++;
3347       } else
3348 	goto error;
3349     } else if (strcmp(items[j], XmNbackground) == 0) {
3350       if (token -> type != T_INT) goto error;
3351       if (token -> type != -1) {
3352 	XtSetArg(args[count], XmNrenditionBackground, token -> integer); count++;
3353       }
3354     } else if (strcmp(items[j], XmNforeground) == 0) {
3355       if (token -> type != T_INT) goto error;
3356       if (token -> type != -1) {
3357 	XtSetArg(args[count], XmNrenditionForeground, token -> integer); count++;
3358       }
3359     } else if (strcmp(items[j], XmNunderlineType) == 0) {
3360       if (token -> type != T_INT) goto error;
3361       if (token -> type != -1) {
3362 	XtSetArg(args[count], XmNunderlineType, token -> integer); count++;
3363       }
3364     } else if (strcmp(items[j], XmNstrikethruType) == 0) {
3365       if (token -> type != T_INT) goto error;
3366       if (token -> type != -1) {
3367 	XtSetArg(args[count], XmNstrikethruType, token -> integer); count++;
3368       }
3369     }
3370   }
3371 
3372  finish:
3373   new_rt = XmRenderTableAddRenditions(new_rt, rarray, rarray_count, XmMERGE_REPLACE);
3374   for (i = 0; i < rarray_count; i++) XmRenditionFree(rarray[i]);
3375   _XmAppUnlock(app);
3376   return(new_rt);
3377 
3378  error:
3379   /* Free temp strings returned by ReadToken */
3380   for(i = 0; i < freecount; i++) XtFree((char*) freelater[i]);
3381   freecount = 0;
3382   goto finish;
3383 }
3384 
3385 void
XmRenderTableGetDefaultFontExtents(XmRenderTable rendertable,int * height,int * ascent,int * descent)3386 XmRenderTableGetDefaultFontExtents(XmRenderTable rendertable,
3387                                     int *height,
3388 				    int *ascent,
3389 				    int *descent)
3390 {
3391     XmStringTag	    tag = XmFONTLIST_DEFAULT_TAG;
3392     XmRendition     rend;
3393     Boolean         success;
3394     short           indx;
3395     int             h,a,d;
3396 
3397 #ifdef XTHREADS
3398   XtAppContext	       app=NULL;
3399 
3400   if ( _XmRTDisplay(rendertable) )
3401     app = XtDisplayToApplicationContext(_XmRTDisplay(rendertable));
3402 
3403   if (app)
3404     _XmAppLock(app);
3405   else
3406     _XmProcessLock();
3407 #endif
3408 
3409     a = d = h = 0;
3410     /* Get default rendition */
3411     success = _XmRenderTableFindFallback(rendertable, tag, FALSE, &indx, &rend);
3412 
3413     /* For backward compatibility we must try to return something for */
3414     /* any non-null charset, not just XmFONTLIST_DEFAULT_TAG. */
3415     if (rendertable && tag && !success)
3416       success = _XmRenderTableFindFirstFont(rendertable, &indx, &rend);
3417 
3418     if (success) {
3419         /* Find font height */
3420         switch (_XmRendFontType(rend)) {
3421             case XmFONT_IS_FONT:
3422                 if (_XmRendFont(rend)) {
3423                     a = ((XFontStruct*)_XmRendFont(rend))->ascent;
3424                     d = ((XFontStruct*)_XmRendFont(rend))->descent;
3425                     h = a + d;
3426                 }
3427                 break;
3428             case XmFONT_IS_FONTSET:
3429                 if (_XmRendFont(rend)) {
3430                     XFontStruct **font_struct_list;
3431                     char **font_name_list;
3432 
3433                     if (XFontsOfFontSet((XFontSet)_XmRendFont(rend),
3434                                 &font_struct_list, &font_name_list)) {
3435                         a = font_struct_list[0]->ascent;
3436                         d = font_struct_list[0]->descent;
3437                         h = a + d;
3438                     }
3439                 }
3440                 break;
3441 #ifdef USE_XFT
3442                 case XmFONT_IS_XFT:
3443                     if (_XmRendXftFont(rend)) {
3444                         a = _XmRendXftFont(rend)->ascent;
3445                         d = _XmRendXftFont(rend)->descent;
3446                         h = a + d;
3447                     }
3448                     break;
3449 #endif
3450         }
3451     }
3452 
3453 #ifdef XTHREADS
3454   if (app)
3455     _XmAppUnlock(app);
3456   else
3457     _XmProcessUnlock();
3458 #endif
3459 
3460   if (ascent) *ascent = a;
3461   if (descent) *descent = d;
3462   if (height) *height = h;
3463 }
3464