1 /*
2 
3 Copyright 1989, 1994, 1998  The Open Group
4 
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10 
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
24 
25 */
26 
27 /*
28  * Author:  Chris Peterson, MIT X Consortium.
29  *
30  * Much code taken from X11R3 AsciiSink.
31  */
32 
33 /*
34  * TextSink.c - TextSink object. (For use with the text widget).
35  *
36  */
37 
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <ctype.h>
44 #include <X11/IntrinsicP.h>
45 #include <X11/StringDefs.h>
46 #include <X11/Xaw/TextP.h>
47 #include <X11/Xaw/TextSinkP.h>
48 #include <X11/Xaw/XawInit.h>
49 #include "Private.h"
50 
51 /*
52  * Prototypes
53  */
54 static void XawTextSinkClassPartInitialize(WidgetClass);
55 static void XawTextSinkInitialize(Widget, Widget, ArgList, Cardinal*);
56 static void XawTextSinkDestroy(Widget);
57 static Boolean XawTextSinkSetValues(Widget, Widget, Widget,
58 				    ArgList, Cardinal*);
59 
60 static int  MaxLines(Widget, unsigned int);
61 static int  MaxHeight(Widget, int);
62 static void DisplayText(Widget, int, int, XawTextPosition, XawTextPosition,
63 			Bool);
64 static void InsertCursor(Widget, int, int, XawTextInsertState);
65 static void ClearToBackground(Widget, int, int, unsigned int, unsigned int);
66 static void FindPosition(Widget, XawTextPosition, int, int, Bool,
67 			 XawTextPosition*, int*, int*);
68 static void FindDistance(Widget, XawTextPosition, int, XawTextPosition, int*,
69 			 XawTextPosition*, int*);
70 static void Resolve(Widget, XawTextPosition, int, int, XawTextPosition*);
71 static void SetTabs(Widget, int, short*);
72 static void GetCursorBounds(Widget, XRectangle*);
73 
74 #ifndef OLDXAW
75 static Boolean CvtStringToPropertyList(Display*, XrmValue*, Cardinal*,
76 				       XrmValue*, XrmValue*, XtPointer*);
77 static Boolean CvtPropertyListToString(Display*, XrmValue*, Cardinal*,
78 				       XrmValue*, XrmValue*, XtPointer*);
79 static Bool BeginPaint(Widget);
80 static Bool EndPaint(Widget);
81 static void SetXlfdDefaults(Display*, XawTextProperty*);
82 #endif
83 
84 /*
85  * External
86  */
87 void _XawTextSinkClearToBackground(Widget, int, int, unsigned, unsigned);
88 void _XawTextSinkDisplayText(Widget, int, int, XawTextPosition, XawTextPosition,
89 			     Bool);
90 
91 /*
92  * Initialization
93  */
94 #define offset(field) XtOffsetOf(TextSinkRec, text_sink.field)
95 static XtResource resources[] = {
96   {
97     XtNforeground,
98     XtCForeground,
99     XtRPixel,
100     sizeof(Pixel),
101     offset(foreground),
102     XtRString,
103     (XtPointer)XtDefaultForeground
104   },
105   {
106     XtNbackground,
107     XtCBackground,
108     XtRPixel,
109     sizeof(Pixel),
110     offset(background),
111     XtRString,
112     (XtPointer)XtDefaultBackground
113   },
114 #ifndef OLDXAW
115   {
116     XtNcursorColor,
117     XtCColor,
118     XtRPixel,
119     sizeof(Pixel),
120     offset(cursor_color),
121     XtRString,
122     (XtPointer)XtDefaultForeground
123   },
124   {
125     XawNtextProperties,
126     XawCTextProperties,
127     XawRTextProperties,
128     sizeof(XawTextPropertyList*),
129     offset(properties),
130     XtRImmediate,
131     NULL
132   },
133 #endif
134 };
135 #undef offset
136 
137 #ifndef OLDXAW
138 static TextSinkExtRec extension_rec = {
139     NULL,				/* next_extension */
140     NULLQUARK,				/* record_type */
141     1,					/* version */
142     sizeof(TextSinkExtRec),		/* record_size */
143     BeginPaint,
144     NULL,
145     NULL,
146     EndPaint
147 };
148 
149 static XrmQuark Qdefault;
150 #endif
151 
152 #define Superclass	(&objectClassRec)
153 TextSinkClassRec textSinkClassRec = {
154   /* object */
155   {
156     (WidgetClass)Superclass,		/* superclass */
157     "TextSink",				/* class_name */
158     sizeof(TextSinkRec),		/* widget_size */
159     XawInitializeWidgetSet,		/* class_initialize */
160     XawTextSinkClassPartInitialize,	/* class_part_initialize */
161     False,				/* class_inited */
162     XawTextSinkInitialize,		/* initialize */
163     NULL,				/* initialize_hook */
164     NULL,				/* obj1 */
165     NULL,				/* obj2 */
166     0,					/* obj3 */
167     resources,				/* resources */
168     XtNumber(resources),		/* num_resources */
169     NULLQUARK,				/* xrm_class */
170     False,				/* obj4 */
171     False,				/* obj5 */
172     False,				/* obj6 */
173     False,				/* obj7 */
174     XawTextSinkDestroy,			/* destroy */
175     NULL,				/* obj8 */
176     NULL,				/* obj9 */
177     XawTextSinkSetValues,		/* set_values */
178     NULL,				/* set_values_hook */
179     NULL,				/* obj10 */
180     NULL,				/* get_values_hook */
181     NULL,				/* obj11 */
182     XtVersion,				/* version */
183     NULL,				/* callback_private */
184     NULL,				/* obj12 */
185     NULL,				/* obj13 */
186     NULL,				/* obj14 */
187     NULL,				/* extension */
188   },
189   /* text_sink */
190   {
191     DisplayText,			/* DisplayText */
192     InsertCursor,			/* InsertCursor */
193     ClearToBackground,			/* ClearToBackground */
194     FindPosition,			/* FindPosition */
195     FindDistance,			/* FindDistance */
196     Resolve,				/* Resolve */
197     MaxLines,				/* MaxLines */
198     MaxHeight,				/* MaxHeight */
199     SetTabs,				/* SetTabs */
200     GetCursorBounds,			/* GetCursorBounds */
201   },
202 };
203 
204 WidgetClass textSinkObjectClass = (WidgetClass)&textSinkClassRec;
205 
206 /*
207  * Implementation
208  */
209 static void
XawTextSinkClassPartInitialize(WidgetClass wc)210 XawTextSinkClassPartInitialize(WidgetClass wc)
211 {
212     TextSinkObjectClass t_src, superC;
213 #ifndef OLDXAW
214     static XtConvertArgRec CvtArgs[] = {
215       {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.self),
216        sizeof(Widget)},
217     };
218 #endif
219 
220     t_src = (TextSinkObjectClass) wc;
221     superC = (TextSinkObjectClass) t_src->object_class.superclass;
222 
223 #ifndef OLDXAW
224     extension_rec.record_type = XrmPermStringToQuark("TextSink");
225     extension_rec.next_extension = (XtPointer)t_src->text_sink_class.extension;
226     t_src->text_sink_class.extension = &extension_rec;
227 
228     Qdefault = XrmPermStringToQuark("default");
229 #endif
230 
231     /*
232      * We don't need to check for null super since we'll get to TextSink
233      * eventually.
234      */
235     if (t_src->text_sink_class.DisplayText == XtInheritDisplayText)
236 	t_src->text_sink_class.DisplayText =
237 	    superC->text_sink_class.DisplayText;
238 
239     if (t_src->text_sink_class.InsertCursor == XtInheritInsertCursor)
240 	t_src->text_sink_class.InsertCursor =
241 	    superC->text_sink_class.InsertCursor;
242 
243     if (t_src->text_sink_class.ClearToBackground== XtInheritClearToBackground)
244 	t_src->text_sink_class.ClearToBackground =
245 	    superC->text_sink_class.ClearToBackground;
246 
247     if (t_src->text_sink_class.FindPosition == XtInheritFindPosition)
248 	t_src->text_sink_class.FindPosition =
249 	    superC->text_sink_class.FindPosition;
250 
251     if (t_src->text_sink_class.FindDistance == XtInheritFindDistance)
252 	t_src->text_sink_class.FindDistance =
253 	    superC->text_sink_class.FindDistance;
254 
255     if (t_src->text_sink_class.Resolve == XtInheritResolve)
256 	t_src->text_sink_class.Resolve =
257 	    superC->text_sink_class.Resolve;
258 
259     if (t_src->text_sink_class.MaxLines == XtInheritMaxLines)
260 	t_src->text_sink_class.MaxLines =
261 	    superC->text_sink_class.MaxLines;
262 
263     if (t_src->text_sink_class.MaxHeight == XtInheritMaxHeight)
264 	t_src->text_sink_class.MaxHeight =
265 	    superC->text_sink_class.MaxHeight;
266 
267     if (t_src->text_sink_class.SetTabs == XtInheritSetTabs)
268 	t_src->text_sink_class.SetTabs =
269 	    superC->text_sink_class.SetTabs;
270 
271     if (t_src->text_sink_class.GetCursorBounds == XtInheritGetCursorBounds)
272 	t_src->text_sink_class.GetCursorBounds =
273 	    superC->text_sink_class.GetCursorBounds;
274 
275 #ifndef OLDXAW
276     XtSetTypeConverter(XtRString, XawRTextProperties, CvtStringToPropertyList,
277 		       &CvtArgs[0], XtNumber(CvtArgs), XtCacheNone, NULL);
278     XtSetTypeConverter(XawRTextProperties, XtRString, CvtPropertyListToString,
279 		       NULL, 0, XtCacheNone, NULL);
280 #endif
281 }
282 
283 /*
284  * Function:
285  *	XawTextSinkInitialize
286  *
287  * Parameters:
288  *	request - requested and new values for the object instance
289  *	cnew	- ""
290  *
291  * Description:
292  *	Initializes the TextSink Object.
293  */
294 /*ARGSUSED*/
295 static void
XawTextSinkInitialize(Widget request _X_UNUSED,Widget cnew,ArgList args _X_UNUSED,Cardinal * num_args _X_UNUSED)296 XawTextSinkInitialize(Widget request _X_UNUSED, Widget cnew,
297 		      ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED)
298 {
299     TextSinkObject sink = (TextSinkObject)cnew;
300 
301     sink->text_sink.tab_count = 0; /* Initialize the tab stops. */
302     sink->text_sink.tabs = NULL;
303     sink->text_sink.char_tabs = NULL;
304 #ifndef OLDXAW
305     sink->text_sink.paint = NULL;
306 #endif
307 }
308 
309 /*
310  * Function:
311  *	XawTextSinkDestroy
312  *
313  * Parameters:
314  *	w - TextSink Object
315  *
316  * Description:
317  *	This function cleans up when the object is destroyed.
318  */
319 static void
XawTextSinkDestroy(Widget w)320 XawTextSinkDestroy(Widget w)
321 {
322     TextSinkObject sink = (TextSinkObject) w;
323 
324     XtFree((char *)sink->text_sink.tabs);
325     XtFree((char *)sink->text_sink.char_tabs);
326 }
327 
328 /*
329  * Function:
330  *	XawTextSinkSetValues
331  *
332  * Parameters:
333  *	current - current state of the object
334  *	request - what was requested
335  *	cnew	- what the object will become
336  *
337  * Description:
338  *	Sets the values for the TextSink.
339  *
340  * Returns:
341  *	True if redisplay is needed
342  */
343 /*ARGSUSED*/
344 static Boolean
XawTextSinkSetValues(Widget current,Widget request _X_UNUSED,Widget cnew,ArgList args _X_UNUSED,Cardinal * num_args _X_UNUSED)345 XawTextSinkSetValues(Widget current, Widget request _X_UNUSED, Widget cnew,
346 		     ArgList args _X_UNUSED, Cardinal *num_args _X_UNUSED)
347 {
348     TextSinkObject w = (TextSinkObject)cnew;
349     TextSinkObject old_w = (TextSinkObject)current;
350 
351     if (w->text_sink.foreground != old_w->text_sink.foreground)
352 	((TextWidget)XtParent(cnew))->text.redisplay_needed = True;
353 
354     return (False);
355 }
356 
357 /*
358  * Function:
359  *	DisplayText
360  *
361  * Parameters:
362  *	w	  - TextSink Object
363  *	x	  - location to start drawing text
364  *	y	  - ""
365  *	pos1	  - location of starting and ending points in the text buffer
366  *	pos2	  - ""
367  *		 highlight - hightlight this text?
368  *
369  * Description:
370  *	Stub function that in subclasses will display text.
371  */
372 /*ARGSUSED*/
373 static void
DisplayText(Widget w _X_UNUSED,int x _X_UNUSED,int y _X_UNUSED,XawTextPosition pos1 _X_UNUSED,XawTextPosition pos2 _X_UNUSED,Bool highlight _X_UNUSED)374 DisplayText(Widget w _X_UNUSED, int x _X_UNUSED, int y _X_UNUSED,
375 	    XawTextPosition pos1 _X_UNUSED, XawTextPosition pos2 _X_UNUSED, Bool highlight _X_UNUSED)
376 {
377     return;
378 }
379 
380 /*
381  * Function:
382  *	InsertCursor
383  *
384  * Parameters:
385  *	w     - TextSink Object
386  *	x     - location for the cursor
387  *	y     - ""
388  *	state - whether to turn the cursor on, or off
389  *
390  * Description:
391  *	Places the InsertCursor.
392  */
393 /*ARGSUSED*/
394 static void
InsertCursor(Widget w _X_UNUSED,int x _X_UNUSED,int y _X_UNUSED,XawTextInsertState state _X_UNUSED)395 InsertCursor(Widget w _X_UNUSED, int x _X_UNUSED, int y _X_UNUSED, XawTextInsertState state _X_UNUSED)
396 {
397     return;
398 }
399 
400 /*
401  * Function:
402  *	ClearToBackground
403  *
404  * Parameters:
405  *	w      - TextSink Object
406  *	x      - location of area to clear
407  *	y      - ""
408  *	width  - size of area to clear
409  *	height - ""
410  *
411  * Description:
412  *	Clears a region of the sink to the background color.
413  */
414 /*ARGSUSED*/
415 static void
ClearToBackground(Widget w,int x,int y,unsigned int width,unsigned int height)416 ClearToBackground(Widget w, int x, int y,
417 		  unsigned int width, unsigned int height)
418 {
419     /*
420      * Don't clear in height or width are zero
421      * XClearArea() has special semantic for these values
422      */
423     TextWidget xaw = (TextWidget)XtParent(w);
424     Position x1, y1, x2, y2;
425 
426     x1 = (XawMax(x, xaw->text.r_margin.left));
427     y1 = (XawMax(y, xaw->text.r_margin.top));
428     x2 = (XawMin(x + (int)width, (int)XtWidth(xaw) - xaw->text.r_margin.right));
429     y2 = (XawMin(y + (int)height, (int)XtHeight(xaw) - xaw->text.r_margin.bottom));
430 
431     x = (int)x1;
432     y = (int)y1;
433     width = (unsigned)(XawMax(0, x2 - x1));
434     height = (unsigned)(XawMax(0, y2 - y1));
435 
436     if (height != 0 && width != 0)
437 	XClearArea(XtDisplayOfObject(w), XtWindowOfObject(w),
438 		   x, y, width, height, False);
439 }
440 
441 /*
442  * Function:
443  *	FindPosition
444  *
445  * Parameters:
446  *	w		- TextSink Object
447  *	fromPos		- reference position
448  *	fromX		- reference location
449  *	width		- width of section to paint text
450  *	stopAtWordBreak - returned position is a word break?
451  *	resPos		- position found (return)
452  *	resWidth	- Width actually used (return)
453  *	resHeight	- Height actually used (return)
454  *
455  * Description:
456  *	Finds a position in the text.
457  */
458 /*ARGSUSED*/
459 static void
FindPosition(Widget w _X_UNUSED,XawTextPosition fromPos _X_UNUSED,int fromx _X_UNUSED,int width _X_UNUSED,Bool stopAtWordBreak _X_UNUSED,XawTextPosition * resPos,int * resWidth,int * resHeight)460 FindPosition(Widget w _X_UNUSED, XawTextPosition fromPos _X_UNUSED, int fromx _X_UNUSED, int width _X_UNUSED,
461 	     Bool stopAtWordBreak _X_UNUSED, XawTextPosition *resPos,
462 	     int *resWidth, int *resHeight)
463 {
464     *resPos = fromPos;
465     *resHeight = *resWidth = 0;
466 }
467 
468 /*
469  * Function:
470  *	FindDistance
471  *
472  * Parameters:
473  *	w	  - TextSink Object
474  *	fromPos	  - starting Position
475  *	fromX	  - x location of starting Position
476  *	toPos	  - end Position
477  *	resWidth  - Distance between fromPos and toPos
478  *	resPos	  - Acutal toPos used
479  *	resHeight - Height required by this text
480  *
481  * Description:
482  *	Find the Pixel Distance between two text Positions.
483  */
484 /*ARGSUSED*/
485 static void
FindDistance(Widget w _X_UNUSED,XawTextPosition fromPos,int fromx _X_UNUSED,XawTextPosition toPos _X_UNUSED,int * resWidth,XawTextPosition * resPos,int * resHeight)486 FindDistance(Widget w _X_UNUSED, XawTextPosition fromPos, int fromx _X_UNUSED,
487 	     XawTextPosition toPos _X_UNUSED, int *resWidth,
488 	     XawTextPosition *resPos, int *resHeight)
489 {
490     *resWidth = *resHeight = 0;
491     *resPos = fromPos;
492 }
493 
494 /*
495  * Function:
496  *	Resolve
497  *
498  * Parameters:
499  *	w      - TextSink Object
500  *	pos    - reference Position
501  *	fromx  - reference Location
502  *	width  - width to move
503  *	resPos - resulting position
504  *
505  * Description:
506  *	Resloves a location to a position.
507  */
508 /*ARGSUSED*/
509 static void
Resolve(Widget w _X_UNUSED,XawTextPosition pos _X_UNUSED,int fromx _X_UNUSED,int width _X_UNUSED,XawTextPosition * resPos)510 Resolve(Widget w _X_UNUSED, XawTextPosition pos _X_UNUSED, int fromx _X_UNUSED, int width _X_UNUSED,
511 	XawTextPosition *resPos)
512 {
513     *resPos = pos;
514 }
515 
516 /*
517  * Function:
518  *	MaxLines
519  *
520  * Parameters:
521  *	w      - TextSink Object
522  *	height - height to fit lines into
523  *
524  * Description:
525  *	Finds the Maximum number of lines that will fit in a given height.
526  *
527  * Returns:
528  *	Number of lines that will fit
529  */
530 /*ARGSUSED*/
531 static int
MaxLines(Widget w _X_UNUSED,unsigned int height _X_UNUSED)532 MaxLines(Widget w _X_UNUSED, unsigned int height _X_UNUSED)
533 {
534     /*
535      * The fontset has gone down to descent Sink Widget, so
536      * the functions such MaxLines, SetTabs... are bound to the descent.
537      *
538      * by Li Yuhong, Jan. 15, 1991
539      */
540     return (0);
541 }
542 
543 /*
544  * Function:
545  *	MaxHeight
546  *
547  * Parameters:
548  *	w     - TextSink Object
549  *	lines - number of lines
550  *
551  * Description:
552  *	Finds the Minium height that will contain a given number lines.
553  *
554  * Returns:
555  *	the height
556  */
557 /*ARGSUSED*/
558 static int
MaxHeight(Widget w _X_UNUSED,int lines _X_UNUSED)559 MaxHeight(Widget w _X_UNUSED, int lines _X_UNUSED)
560 {
561     return (0);
562 }
563 
564 /*
565  * Function:
566  *	SetTabs
567  *
568  * Parameters:
569  *	w	  - TextSink Object
570  *	tab_count - the number of tabs in the list
571  *	tabs	  - text positions of the tabs
572  * Description:
573  *	Sets the Tab stops.
574  */
575 /*ARGSUSED*/
576 static void
SetTabs(Widget w _X_UNUSED,int tab_count _X_UNUSED,short * tabs _X_UNUSED)577 SetTabs(Widget w _X_UNUSED, int tab_count _X_UNUSED, short *tabs _X_UNUSED)
578 {
579     return;
580 }
581 
582 /*
583  * Function:
584  *	GetCursorBounds
585  *
586  * Parameters:
587  *	w - TextSinkObject.
588  *	rect - X rectangle containing the cursor bounds
589  *
590  * Description:
591  *	Finds the bounding box for the insert cursor (caret)
592  */
593 /*ARGSUSED*/
594 static void
GetCursorBounds(Widget w _X_UNUSED,XRectangle * rect)595 GetCursorBounds(Widget w _X_UNUSED, XRectangle *rect)
596 {
597     rect->x = rect->y = (short)(rect->width = rect->height = 0);
598 }
599 
600 /*
601  * Public Functions
602  */
603 /*
604  * Function:
605  *	XawTextSinkDisplayText
606  *
607  * Parameters:
608  *	w	  - TextSink Object
609  *	x	  - location to start drawing text
610  *	y	  - ""
611  *	pos1	  - location of starting and ending points in the text buffer
612  *	pos2	  - ""
613  *	highlight - hightlight this text?
614  */
615 /*ARGSUSED*/
616 void
XawTextSinkDisplayText(Widget w,int x,int y,XawTextPosition pos1,XawTextPosition pos2,int highlight)617 XawTextSinkDisplayText(Widget w,
618 #if NeedWidePrototypes
619 		       int x, int y,
620 #else
621 		       Position x, Position y,
622 #endif
623 		       XawTextPosition pos1, XawTextPosition pos2,
624 #if NeedWidePrototypes
625 		       int highlight
626 #else
627 		       Boolean highlight
628 #endif
629 )
630 {
631     _XawTextSinkDisplayText(w, x, y, pos1, pos2, highlight);
632 }
633 
634 void
_XawTextSinkDisplayText(Widget w,int x,int y,XawTextPosition pos1,XawTextPosition pos2,Bool highlight)635 _XawTextSinkDisplayText(Widget w, int x, int y,
636 			XawTextPosition pos1, XawTextPosition pos2,
637 			Bool highlight)
638 {
639     TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
640 
641     (*cclass->text_sink_class.DisplayText)(w, x, y, pos1, pos2, highlight);
642 }
643 
644 /*
645  * Function:
646  *	XawTextSinkInsertCursor
647  *
648  * Parameters:
649  *	w     - TextSink Object
650  *	x     - location for the cursor
651  *	y     - ""
652  *	state - whether to turn the cursor on, or off
653  *
654  * Description:
655  *	Places the InsertCursor.
656  */
657 /*ARGSUSED*/
658 void
659 #if NeedWidePrototypes
XawTextSinkInsertCursor(Widget w,int x,int y,int state)660 XawTextSinkInsertCursor(Widget w, int x, int y, int state)
661 #else
662 XawTextSinkInsertCursor(Widget w, Position x, Position y, XawTextInsertState state)
663 #endif
664 {
665     TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
666 
667     (*cclass->text_sink_class.InsertCursor)(w, x, y, state);
668 }
669 
670 /*
671  * Function:
672  *	XawTextSinkClearToBackground
673  *
674  * Parameters:
675  *	w      - TextSink Object
676  *	x      - location of area to clear
677  *	y      - ""
678  *	width  - size of area to clear
679  *	height - ""
680  *
681  * Description:
682  *	Clears a region of the sink to the background color.
683  */
684 /*ARGSUSED*/
685 void
XawTextSinkClearToBackground(Widget w,int x,int y,unsigned int width,unsigned int height)686 XawTextSinkClearToBackground(Widget w,
687 #if NeedWidePrototypes
688 			     int x, int y,
689 			     unsigned int width, unsigned int height
690 #else
691 			     Position x, Position y,
692 			     Dimension width, Dimension height
693 #endif
694 )
695 {
696     _XawTextSinkClearToBackground(w, x, y, width, height);
697 }
698 
699 void
_XawTextSinkClearToBackground(Widget w,int x,int y,unsigned int width,unsigned int height)700 _XawTextSinkClearToBackground(Widget w,
701 			      int x, int y,
702 			      unsigned int width, unsigned int height)
703 {
704     TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
705 
706     (*cclass->text_sink_class.ClearToBackground)(w, x, y, width, height);
707 }
708 
709 /*
710  * Function:
711  *	XawTextSinkFindPosition
712  *
713  *  Parameters:
714  *	w		- TextSink Object
715  *	fromPos		- reference position
716  *	fromX		- reference location
717  *	width		- width of section to paint text
718  *	stopAtWordBreak - returned position is a word break?
719  *	resPos		- position found (return)
720  *	resWidth	- Width actually used (return)
721  *	resHeight	- Height actually used (return)
722  *
723  * Description:
724  *	Finds a position in the text.
725  */
726 /*ARGSUSED*/
727 void
XawTextSinkFindPosition(Widget w,XawTextPosition fromPos,int fromx,int width,int stopAtWordBreak,XawTextPosition * resPos,int * resWidth,int * resHeight)728 XawTextSinkFindPosition(Widget w, XawTextPosition fromPos, int fromx, int width,
729 #if NeedWidePrototypes
730 			int stopAtWordBreak,
731 #else
732 			Boolean stopAtWordBreak,
733 #endif
734 			XawTextPosition *resPos, int *resWidth, int *resHeight)
735 {
736     TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
737 
738     (*cclass->text_sink_class.FindPosition)(w, fromPos, fromx, width,
739 					    stopAtWordBreak,
740 					    resPos, resWidth, resHeight);
741 }
742 
743 /*
744  * Function:
745  *	XawTextSinkFindDistance
746  *
747  *  Parameters:
748  *	w	  - TextSink Object
749  *	fromPos	  - starting Position
750  *	fromX	  - x location of starting Position
751  *	toPos	  - end Position
752  *	resWidth  - Distance between fromPos and toPos
753  *	resPos	  - Acutal toPos used
754  *	resHeight - Height required by this text
755  *
756  * Description:
757  *	Find the Pixel Distance between two text Positions.
758  */
759 /*ARGSUSED*/
760 void
XawTextSinkFindDistance(Widget w,XawTextPosition fromPos,int fromx,XawTextPosition toPos,int * resWidth,XawTextPosition * resPos,int * resHeight)761 XawTextSinkFindDistance(Widget w, XawTextPosition fromPos, int fromx,
762 			XawTextPosition toPos, int *resWidth,
763 			XawTextPosition *resPos, int *resHeight)
764 {
765     TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
766 
767     (*cclass->text_sink_class.FindDistance)(w, fromPos, fromx, toPos,
768 					    resWidth, resPos, resHeight);
769 }
770 
771 /*
772  * Function:
773  *	XawTextSinkResolve
774  *
775  *  Parameters:
776  *	w      - TextSink Object
777  *	pos    - reference Position
778  *	fromx  - reference Location
779  *	width  - width to move
780  *	resPos - resulting position
781  *
782  * Description:
783  *	Resloves a location to a position.
784  */
785 /*ARGSUSED*/
786 void
XawTextSinkResolve(Widget w,XawTextPosition pos,int fromx,int width,XawTextPosition * resPos)787 XawTextSinkResolve(Widget w, XawTextPosition pos, int fromx, int width,
788 		   XawTextPosition *resPos)
789 {
790     TextSinkObjectClass cclass = (TextSinkObjectClass) w->core.widget_class;
791 
792     (*cclass->text_sink_class.Resolve)(w, pos, fromx, width, resPos);
793 }
794 
795 /*
796  * Function:
797  *	XawTextSinkMaxLines
798  *
799  *  Parameters:
800  *	w      - TextSink Object
801  *	height - height to fit lines into
802  *
803  * Description:
804  *	Finds the Maximum number of lines that will fit in a given height.
805  *
806  * Returns:
807  *	Number of lines that will fit
808  */
809 /*ARGSUSED*/
810 int
811 #if NeedWidePrototypes
XawTextSinkMaxLines(Widget w,unsigned int height)812 XawTextSinkMaxLines(Widget w, unsigned int height)
813 #else
814 XawTextSinkMaxLines(Widget w, Dimension height)
815 #endif
816 {
817     TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
818 
819     return((*cclass->text_sink_class.MaxLines)(w, height));
820 }
821 
822 /*
823  * Function:
824  *	XawTextSinkMaxHeight
825  *
826  *  Parameters:
827  *	w     - TextSink Object
828  *	lines - number of lines
829  *
830  * Description:
831  *	Finds the Minium height that will contain a given number lines.
832  *
833  * Returns:
834  *	the height
835  */
836 /*ARGSUSED*/
837 int
XawTextSinkMaxHeight(Widget w,int lines)838 XawTextSinkMaxHeight(Widget w, int lines)
839 {
840     TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
841 
842     return((*cclass->text_sink_class.MaxHeight)(w, lines));
843 }
844 
845 /*
846  * Function:
847  *	XawTextSinkSetTabs
848  *
849  *  Parameters:
850  *	w	  - TextSink Object
851  *	tab_count - the number of tabs in the list
852  *	tabs	  - text positions of the tabs
853  * Description:
854  *	Sets the Tab stops.
855  */
856 void
XawTextSinkSetTabs(Widget w,int tab_count,int * tabs)857 XawTextSinkSetTabs(Widget w, int tab_count, int *tabs)
858 {
859     if (tab_count > 0) {
860 	TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
861 	short *char_tabs = (short*)XtMalloc((Cardinal)((unsigned)tab_count * sizeof(short)));
862 	short *tab, len = 0;
863 	int i;
864 
865 	for (i = tab_count, tab = char_tabs; i; i--) {
866 	    if ((short)*tabs > len)
867 		*tab++ = (len = (short)*tabs++);
868 	    else {
869 		tabs++;
870 		--tab_count;
871 	    }
872 	}
873 
874 	if (tab_count > 0)
875 	    (*cclass->text_sink_class.SetTabs)(w, tab_count, char_tabs);
876 	XtFree((char *)char_tabs);
877     }
878 }
879 
880 /*
881  * Function:
882  *	XawTextSinkGetCursorBounds
883  *
884  * Parameters:
885  *	w    - TextSinkObject
886  *	rect - X rectance containing the cursor bounds
887  *
888  * Description:
889  *	Finds the bounding box for the insert cursor (caret).
890  */
891 /*ARGSUSED*/
892 void
XawTextSinkGetCursorBounds(Widget w,XRectangle * rect)893 XawTextSinkGetCursorBounds(Widget w, XRectangle *rect)
894 {
895     TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
896 
897     (*cclass->text_sink_class.GetCursorBounds)(w, rect);
898 }
899 
900 #ifndef OLDXAW
901 Bool
XawTextSinkBeginPaint(Widget w)902 XawTextSinkBeginPaint(Widget w)
903 {
904     TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
905 
906     if (cclass->text_sink_class.extension->BeginPaint == NULL ||
907 	cclass->text_sink_class.extension->PreparePaint == NULL ||
908 	cclass->text_sink_class.extension->DoPaint == NULL ||
909 	cclass->text_sink_class.extension->EndPaint == NULL)
910 	return (False);
911 
912     return ((*cclass->text_sink_class.extension->BeginPaint)(w));
913 }
914 
915 static Bool
BeginPaint(Widget w)916 BeginPaint(Widget w)
917 {
918     TextSinkObject sink = (TextSinkObject)w;
919 
920     if (sink->text_sink.paint != NULL)
921 	return (False);
922 
923     sink->text_sink.paint = XtNew(XawTextPaintList);
924     sink->text_sink.paint->clip = XmuCreateArea();
925     sink->text_sink.paint->hightabs = NULL;
926     sink->text_sink.paint->paint = NULL;
927     sink->text_sink.paint->bearings = NULL;
928 
929     return (True);
930 }
931 
932 void
XawTextSinkPreparePaint(Widget w,int y,int line,XawTextPosition from,XawTextPosition to,Bool highlight)933 XawTextSinkPreparePaint(Widget w, int y, int line, XawTextPosition from,
934 			XawTextPosition to, Bool highlight)
935 {
936     TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
937 
938     (*cclass->text_sink_class.extension->PreparePaint)
939 	(w, y, line, from, to, highlight);
940 }
941 
942 #if 0
943 /*ARGSUSED*/
944 static void
945 PreparePaint(Widget w, int y, int line, XawTextPosition from, XawTextPosition to,
946 	     Bool highlight)
947 {
948 }
949 #endif
950 
951 void
XawTextSinkDoPaint(Widget w)952 XawTextSinkDoPaint(Widget w)
953 {
954     TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
955 
956     (*cclass->text_sink_class.extension->DoPaint)(w);
957 }
958 
959 #if 0
960 /*ARGSUSED*/
961 static void
962 DoPaint(Widget w)
963 {
964 }
965 #endif
966 
967 Bool
XawTextSinkEndPaint(Widget w)968 XawTextSinkEndPaint(Widget w)
969 {
970     TextSinkObjectClass cclass = (TextSinkObjectClass)w->core.widget_class;
971 
972     return ((*cclass->text_sink_class.extension->EndPaint)(w));
973 }
974 
975 static Bool
EndPaint(Widget w)976 EndPaint(Widget w)
977 {
978     TextSinkObject sink = (TextSinkObject)w;
979     XawTextPaintStruct *paint, *next;
980 
981     if (sink->text_sink.paint == NULL)
982 	return (False);
983 
984     XmuDestroyArea(sink->text_sink.paint->clip);
985     if (sink->text_sink.paint->hightabs)
986 	XmuDestroyArea(sink->text_sink.paint->hightabs);
987     paint = sink->text_sink.paint->paint;
988     while (paint) {
989 	next = paint->next;
990 	if (paint->text)
991 	    XtFree((XtPointer)paint->text);
992 	if (paint->backtabs)
993 	    XmuDestroyArea(paint->backtabs);
994 	XtFree((XtPointer)paint);
995 	paint = next;
996     }
997 
998     paint = sink->text_sink.paint->bearings;
999     while (paint) {
1000 	next = paint->next;
1001 	if (paint->text)
1002 	    XtFree((XtPointer)paint->text);
1003 	XtFree((XtPointer)paint);
1004 	paint = next;
1005     }
1006 
1007     XtFree((XtPointer)sink->text_sink.paint);
1008     sink->text_sink.paint = NULL;
1009     return (True);
1010 }
1011 
1012 static XawTextPropertyList **prop_lists;
1013 static Cardinal num_prop_lists;
1014 
1015 static int
bcmp_qident(_Xconst void * left,_Xconst void * right)1016 bcmp_qident(_Xconst void *left, _Xconst void *right)
1017 {
1018     return (int)((long)left - (*(XawTextProperty**)right)->identifier);
1019 }
1020 
1021 static int
qcmp_qident(_Xconst void * left,_Xconst void * right)1022 qcmp_qident(_Xconst void *left, _Xconst void *right)
1023 {
1024     return ((*(XawTextProperty**)left)->identifier -
1025 	    (*(XawTextProperty**)right)->identifier);
1026 }
1027 
1028 static void
SetXlfdDefaults(Display * display,XawTextProperty * property)1029 SetXlfdDefaults(Display *display, XawTextProperty *property)
1030 {
1031     Atom atom = XInternAtom(display, "FONT", True);
1032     unsigned long value;
1033     char *str;
1034 
1035     if (XGetFontProperty(property->font, atom, &value)) {
1036 	char *xlfd = XGetAtomName(display, value);
1037 
1038 	if (xlfd) {
1039 	    char *sep = xlfd + 1;
1040 	    char *name = sep;
1041 
1042 	    property->xlfd = XrmStringToQuark(xlfd);
1043 
1044 	    sep = strchr(sep, '-');     *sep++ = '\0';
1045 	    property->foundry = XrmStringToQuark(name);
1046 	    name = sep;
1047 
1048 	    sep = strchr(sep, '-');	*sep++ = '\0';
1049 	    property->family = XrmStringToQuark(name);
1050 	    name = sep;
1051 
1052 	    sep = strchr(sep, '-');	*sep++ = '\0';
1053 	    property->weight = XrmStringToQuark(name);
1054 	    name = sep;
1055 
1056 	    sep = strchr(sep, '-');	*sep++ = '\0';
1057 	    property->slant = XrmStringToQuark(name);
1058 	    name = sep;
1059 
1060 	    sep = strchr(sep, '-');	*sep++ = '\0';
1061 	    property->setwidth = XrmStringToQuark(name);
1062 	    name = sep;
1063 
1064 	    sep = strchr(sep, '-');     *sep++ = '\0';
1065 	    property->addstyle = XrmStringToQuark(name);
1066 	    name = sep;
1067 
1068 	    sep = strchr(sep, '-');     *sep++ = '\0';
1069 	    property->pixel_size = XrmStringToQuark(name);
1070 	    name = sep;
1071 
1072 	    sep = strchr(sep, '-');     *sep++ = '\0';
1073 	    property->point_size = XrmStringToQuark(name);
1074 	    name = sep;
1075 
1076 	    sep = strchr(sep, '-');     *sep++ = '\0';
1077 	    property->res_x = XrmStringToQuark(name);
1078 	    name = sep;
1079 
1080 	    sep = strchr(sep, '-');     *sep++ = '\0';
1081 	    property->res_y = XrmStringToQuark(name);
1082 	    name = sep;
1083 
1084 	    sep = strchr(sep, '-');     *sep++ = '\0';
1085 	    property->spacing = XrmStringToQuark(name);
1086 	    name = sep;
1087 
1088 	    sep = strchr(sep, '-');     *sep++ = '\0';
1089 	    property->avgwidth = XrmStringToQuark(name);
1090 	    name = sep;
1091 
1092 	    sep = strchr(sep, '-');     *sep++ = '\0';
1093 	    property->registry = XrmStringToQuark(name);
1094 	    name = sep;
1095 
1096 	    property->encoding = XrmStringToQuark(name);
1097 
1098 	    XFree(xlfd);
1099 	}
1100     }
1101 
1102     atom = XInternAtom(display, "UNDERLINE_THICKNESS", True);
1103     if (XGetFontProperty(property->font, atom, &value) &&
1104 	(str = XGetAtomName(display, value)) != NULL) {
1105 	property->underline_thickness = (short)(atoi(str));
1106 	XFree(str);
1107     }
1108     else {
1109 	/* XLFD says:
1110 	 * CapStemWidth = average width of the stems of capitals
1111 	 * if (UNDERLINE_THICKNESS undefined) then
1112 	 *   UNDERLINE_THICKNESS = CapStemWidth
1113 	 *
1114 	 * How do I know the value of CapStemWidth??
1115 	 */
1116 	if (property->pixel_size != NULLQUARK) {
1117 	    property->underline_thickness =
1118 		(short)(atoi(XrmQuarkToString(property->pixel_size)) / 10);
1119 	    property->underline_thickness =
1120 		(XawMax(1, property->underline_thickness));
1121 	}
1122 	else
1123 	    property->underline_thickness = 1;
1124     }
1125 
1126     atom = XInternAtom(display, "UNDERLINE_POSITION", True);
1127     if (XGetFontProperty(property->font, atom, &value) &&
1128 	(str = XGetAtomName(display, value)) != NULL) {
1129 	property->underline_position = (short)(atoi(str));
1130 	XFree(str);
1131     }
1132     else
1133 	/* XLFD says:
1134 	 * if (UNDERLINE_POSITION undefined) then
1135 	 *   UNDERLINE_POSITION = ROUND((maximum_descent) / 2)
1136 	 */
1137 	property->underline_position =
1138 	    property->font->max_bounds.descent >> 1;
1139 
1140     /* I am assuming xlfd does not consider that lines are
1141      * centered in the path */
1142     property->underline_position = (short)(property->underline_position
1143 					   + (property->underline_thickness >> 1));
1144 }
1145 
1146 static void
DestroyTextPropertyList(XawTextPropertyList * list)1147 DestroyTextPropertyList(XawTextPropertyList *list)
1148 {
1149     int i;
1150 
1151     for (i = 0; (Cardinal)i < list->num_properties; i++) {
1152 	if (list->properties[i]->font)
1153 	    XFreeFont(DisplayOfScreen(list->screen), list->properties[i]->font);
1154 	XtFree((char*)list->properties[i]);
1155     }
1156     if (list->properties)
1157 	XtFree((char*)list->properties);
1158     XtFree((char*)list);
1159 }
1160 
1161 static XawTextProperty *
_XawTextSinkGetProperty(XawTextPropertyList * list,XrmQuark property)1162 _XawTextSinkGetProperty(XawTextPropertyList *list, XrmQuark property)
1163 {
1164     if (property != NULLQUARK && list && list->properties) {
1165 	XawTextProperty **ptr = (XawTextProperty**)
1166 	    bsearch((void*)(long)property,
1167 		    list->properties, list->num_properties,
1168 		    sizeof(XawTextProperty*), bcmp_qident);
1169 
1170 	if (ptr)
1171 	    return (*ptr);
1172     }
1173 
1174     return (NULL);
1175 }
1176 
1177 XawTextProperty *
XawTextSinkGetProperty(Widget w,XrmQuark property)1178 XawTextSinkGetProperty(Widget w, XrmQuark property)
1179 {
1180     TextSinkObject sink = (TextSinkObject)w;
1181     XawTextPropertyList *list = sink->text_sink.properties;
1182 
1183     return (_XawTextSinkGetProperty(list, property));
1184 }
1185 
1186 XawTextProperty *
XawTextSinkCopyProperty(Widget w,XrmQuark property)1187 XawTextSinkCopyProperty(Widget w, XrmQuark property)
1188 {
1189     XawTextProperty *cur, *ret;
1190 
1191     if ((cur = XawTextSinkGetProperty(w, property)) == NULL)
1192 	cur = XawTextSinkGetProperty(w, Qdefault);
1193     ret = (XawTextProperty*)XtCalloc(1, sizeof(XawTextProperty));
1194     if (cur)
1195 	memcpy(ret, cur, sizeof(XawTextProperty));
1196     ret->identifier = NULLQUARK;
1197     ret->mask &= (unsigned long)(~XAW_TPROP_FONT);
1198 
1199     return (ret);
1200 }
1201 
1202 static XawTextProperty *
_XawTextSinkAddProperty(XawTextPropertyList * list,XawTextProperty * property,Bool replace)1203 _XawTextSinkAddProperty(XawTextPropertyList *list, XawTextProperty *property,
1204 			Bool replace)
1205 {
1206     XawTextProperty *result;
1207     XColor color;
1208     char identifier[1024];
1209     char foreground[16];
1210     char background[16];
1211     const char *foundry, *family, *weight, *slant, *setwidth, *addstyle, *pixel_size,
1212 	 *point_size, *res_x, *res_y, *spacing, *avgwidth, *registry, *encoding;
1213     const char *xlfd;
1214     static const char *asterisk = "*";
1215     static const char *null = "";
1216     XrmQuark quark;
1217 
1218     if (list == NULL || property == NULL)
1219 	return (NULL);
1220 
1221     if (property->mask & XAW_TPROP_FOREGROUND) {
1222 	color.pixel = property->foreground;
1223 	XQueryColor(DisplayOfScreen(list->screen), list->colormap, &color);
1224 	snprintf(foreground, sizeof(foreground), "%04x%04x%04x",
1225 		 color.red, color.green, color.blue);
1226     }
1227     else
1228 	strcpy(foreground, asterisk);
1229     if (property->mask & XAW_TPROP_BACKGROUND) {
1230 	color.pixel = property->background;
1231 	XQueryColor(DisplayOfScreen(list->screen), list->colormap, &color);
1232 	snprintf(background, sizeof(background), "%04x%04x%04x",
1233 		 color.red, color.green, color.blue);
1234     }
1235     else
1236 	strcpy(background, asterisk);
1237 
1238     if (property->xlfd_mask & XAW_TPROP_FOUNDRY)
1239 	foundry = XrmQuarkToString(property->foundry);
1240     else
1241 	foundry = asterisk;
1242 
1243     /* use default, or what was requested */
1244     if (property->family != NULLQUARK)
1245 	family = XrmQuarkToString(property->family);
1246     else
1247 	family = asterisk;
1248     if (property->weight != NULLQUARK)
1249 	weight = XrmQuarkToString(property->weight);
1250     else
1251 	weight = asterisk;
1252     if (property->slant != NULLQUARK) {
1253 	slant = XrmQuarkToString(property->slant);
1254 	if (toupper(*slant) != 'R')
1255 	    slant = asterisk;	/* X defaults to italics, so, don't
1256 				   care in resolving between `I' and `O' */
1257     }
1258     else
1259 	slant = asterisk;
1260 
1261     if (property->xlfd_mask & XAW_TPROP_SETWIDTH)
1262 	setwidth = XrmQuarkToString(property->setwidth);
1263     else
1264 	setwidth = asterisk;
1265     if (property->xlfd_mask & XAW_TPROP_ADDSTYLE)
1266 	addstyle = XrmQuarkToString(property->addstyle);
1267     else
1268 	addstyle = null;
1269 
1270     /* use default, or what was requested */
1271     if (!(property->mask & XAW_TPROP_POINTSIZE) &&
1272 	property->pixel_size != NULLQUARK)
1273 	pixel_size = XrmQuarkToString(property->pixel_size);
1274     else
1275 	pixel_size = asterisk;
1276 
1277     if (property->xlfd_mask & XAW_TPROP_POINTSIZE)
1278 	point_size = XrmQuarkToString(property->point_size);
1279     else
1280 	point_size = asterisk;
1281     if (property->xlfd_mask & XAW_TPROP_RESX)
1282 	res_x = XrmQuarkToString(property->res_x);
1283     else
1284 	res_x = asterisk;
1285     if (property->xlfd_mask & XAW_TPROP_RESY)
1286 	res_y = XrmQuarkToString(property->res_y);
1287     else
1288 	res_y = asterisk;
1289     if (property->xlfd_mask & XAW_TPROP_SPACING)
1290 	spacing = XrmQuarkToString(property->spacing);
1291     else
1292 	spacing = asterisk;
1293     if (property->xlfd_mask & XAW_TPROP_AVGWIDTH)
1294 	avgwidth = XrmQuarkToString(property->avgwidth);
1295     else
1296 	avgwidth = asterisk;
1297 
1298     /* use default, or what that was requested */
1299     if (property->registry != NULLQUARK)
1300 	registry = XrmQuarkToString(property->registry);
1301     else
1302 	registry = asterisk;
1303     if (property->encoding != NULLQUARK)
1304 	encoding = XrmQuarkToString(property->encoding);
1305     else
1306 	encoding = asterisk;
1307 
1308     if (replace) {
1309 	result = XtNew(XawTextProperty);
1310 	memcpy(result, property, sizeof(XawTextProperty));
1311     }
1312     else
1313 	result = property;
1314 
1315     /* XXX should do the best to load a suitable font here */
1316     if (!(result->mask & XAW_TPROP_FONT)) {
1317 	snprintf(identifier, sizeof(identifier),
1318 		 "-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s-%s",
1319 		 foundry, family, weight, slant, setwidth, addstyle,
1320 		 pixel_size, point_size, res_x, res_y, spacing, avgwidth,
1321 		 registry, encoding);
1322 	if ((result->font = XLoadQueryFont(DisplayOfScreen(list->screen),
1323 					   identifier)) != NULL) {
1324 	    result->mask |= XAW_TPROP_FONT;
1325 	    SetXlfdDefaults(DisplayOfScreen(list->screen), result);
1326 	}
1327 	else
1328 	    result->mask &= (unsigned long)(~XAW_TPROP_FONT);
1329     }
1330 
1331     if (result->font)
1332 	xlfd = XrmQuarkToString(result->xlfd);
1333     else
1334 	xlfd = null;
1335 
1336     snprintf(identifier, sizeof(identifier), "%08lx%08lx%s%s%d%d%d%d%s",
1337 	     property->mask, property->xlfd_mask,
1338 	     foreground, background,
1339 	     (result->mask & XAW_TPROP_UNDERLINE) != 0,
1340 	     (result->mask & XAW_TPROP_OVERSTRIKE) != 0,
1341 	     (result->mask & XAW_TPROP_SUBSCRIPT) != 0,
1342 	     (result->mask & XAW_TPROP_SUPERSCRIPT) != 0,
1343 	     xlfd);
1344 
1345     quark = XrmStringToQuark(identifier);
1346     if (result->identifier == NULLQUARK)
1347 	result->identifier = quark;
1348     result->code = quark;
1349 
1350     if ((property = _XawTextSinkGetProperty(list, result->identifier)) != NULL) {
1351 	if (result->font)
1352 	    XFreeFont(DisplayOfScreen(list->screen), result->font);
1353 	if (replace)
1354 	    XtFree((XtPointer)result);
1355 
1356 	return (property);
1357     }
1358 
1359     list->properties = (XawTextProperty**)
1360 	XtRealloc((XtPointer)list->properties,
1361 		  (Cardinal)(sizeof(XawTextProperty*) *
1362 			     (list->num_properties + 1)));
1363     list->properties[list->num_properties++] = result;
1364     qsort((void*)list->properties, list->num_properties,
1365 	      sizeof(XawTextProperty*), qcmp_qident);
1366 
1367     return (result);
1368 }
1369 
1370 XawTextProperty *
XawTextSinkAddProperty(Widget w,XawTextProperty * property)1371 XawTextSinkAddProperty(Widget w, XawTextProperty *property)
1372 {
1373     TextSinkObject sink = (TextSinkObject)w;
1374     XawTextPropertyList *list = sink->text_sink.properties;
1375 
1376     return (_XawTextSinkAddProperty(list, property, True));
1377 }
1378 
1379 XawTextProperty *
XawTextSinkCombineProperty(Widget w _X_UNUSED,XawTextProperty * property,XawTextProperty * combine,Bool override)1380 XawTextSinkCombineProperty(Widget w _X_UNUSED,
1381 			   XawTextProperty *property, XawTextProperty *combine,
1382 			   Bool override)
1383 {
1384     if (property == NULL || combine == NULL)
1385 	return (property);
1386 
1387     if ((override || !(property->mask & XAW_TPROP_FOREGROUND)) &&
1388 	(combine->mask & XAW_TPROP_FOREGROUND)) {
1389 	property->mask |= XAW_TPROP_FOREGROUND;
1390 	property->foreground = combine->foreground;
1391     }
1392     if ((override || !(property->mask & XAW_TPROP_BACKGROUND)) &&
1393 	(combine->mask & XAW_TPROP_BACKGROUND)) {
1394 	property->mask |= XAW_TPROP_BACKGROUND;
1395 	property->background = combine->background;
1396     }
1397     if ((override || !(property->mask & XAW_TPROP_FPIXMAP)) &&
1398 	(combine->mask & XAW_TPROP_FPIXMAP)) {
1399 	property->mask |= XAW_TPROP_FPIXMAP;
1400 	property->foreground_pixmap = combine->foreground_pixmap;
1401     }
1402     if ((override || !(property->mask & XAW_TPROP_BPIXMAP)) &&
1403 	(combine->mask & XAW_TPROP_BPIXMAP)) {
1404 	property->mask |= XAW_TPROP_BPIXMAP;
1405 	property->background_pixmap = combine->background_pixmap;
1406     }
1407     if (combine->mask & XAW_TPROP_UNDERLINE)
1408 	property->mask |= XAW_TPROP_UNDERLINE;
1409     if (combine->mask & XAW_TPROP_OVERSTRIKE)
1410 	property->mask |= XAW_TPROP_OVERSTRIKE;
1411     if ((override || !(property->mask & XAW_TPROP_SUPERSCRIPT)) &&
1412 	(combine->mask & XAW_TPROP_SUBSCRIPT))
1413 	property->mask |= XAW_TPROP_SUBSCRIPT;
1414     if ((property->mask & XAW_TPROP_SUBSCRIPT) &&
1415 	(combine->mask & XAW_TPROP_SUPERSCRIPT))
1416 	property->mask |= XAW_TPROP_SUPERSCRIPT;
1417     if ((override || !(property->xlfd_mask & XAW_TPROP_FOUNDRY)) &&
1418 	(combine->xlfd_mask & XAW_TPROP_FOUNDRY)) {
1419 	property->xlfd_mask |= XAW_TPROP_FOUNDRY;
1420 	property->foundry = combine->foundry;
1421     }
1422     if ((override || !(property->xlfd_mask & XAW_TPROP_FAMILY)) &&
1423 	(combine->xlfd_mask & XAW_TPROP_FAMILY)) {
1424 	property->xlfd_mask |= XAW_TPROP_FAMILY;
1425 	property->family = combine->family;
1426     }
1427     if ((override || !(property->xlfd_mask & XAW_TPROP_WEIGHT)) &&
1428 	(combine->xlfd_mask & XAW_TPROP_WEIGHT)) {
1429 	property->xlfd_mask |= XAW_TPROP_WEIGHT;
1430 	property->weight = combine->weight;
1431     }
1432     if ((override || !(property->xlfd_mask & XAW_TPROP_SLANT)) &&
1433 	(combine->xlfd_mask & XAW_TPROP_SLANT)) {
1434 	property->xlfd_mask |= XAW_TPROP_SLANT;
1435 	property->slant = combine->slant;
1436     }
1437     if ((override || !(property->xlfd_mask & XAW_TPROP_SETWIDTH)) &&
1438 	(combine->xlfd_mask & XAW_TPROP_SETWIDTH)) {
1439 	property->xlfd_mask |= XAW_TPROP_SETWIDTH;
1440 	property->setwidth = combine->setwidth;
1441     }
1442     if ((override || !(property->xlfd_mask & XAW_TPROP_ADDSTYLE)) &&
1443 	(combine->xlfd_mask & XAW_TPROP_ADDSTYLE)) {
1444 	property->xlfd_mask |= XAW_TPROP_ADDSTYLE;
1445 	property->addstyle = combine->addstyle;
1446     }
1447     if ((override || !(property->xlfd_mask & XAW_TPROP_PIXELSIZE)) &&
1448 	(combine->xlfd_mask & XAW_TPROP_PIXELSIZE)) {
1449 	property->xlfd_mask |= XAW_TPROP_PIXELSIZE;
1450 	property->pixel_size = combine->pixel_size;
1451     }
1452     if ((override || !(property->xlfd_mask & XAW_TPROP_POINTSIZE)) &&
1453 	(combine->xlfd_mask & XAW_TPROP_POINTSIZE)) {
1454 	property->xlfd_mask |= XAW_TPROP_POINTSIZE;
1455 	property->point_size = combine->point_size;
1456     }
1457     if ((override || !(property->xlfd_mask & XAW_TPROP_RESX)) &&
1458 	(combine->xlfd_mask & XAW_TPROP_RESX)) {
1459 	property->xlfd_mask |= XAW_TPROP_RESX;
1460 	property->res_x = combine->res_x;
1461     }
1462     if ((override || !(property->xlfd_mask & XAW_TPROP_RESY)) &&
1463 	(combine->xlfd_mask & XAW_TPROP_RESY)) {
1464 	property->xlfd_mask |= XAW_TPROP_RESY;
1465 	property->res_y = combine->res_y;
1466     }
1467     if ((override || !(property->xlfd_mask & XAW_TPROP_SPACING)) &&
1468 	(combine->xlfd_mask & XAW_TPROP_SPACING)) {
1469 	property->xlfd_mask |= XAW_TPROP_SPACING;
1470 	property->spacing = combine->spacing;
1471     }
1472     if ((override || !(property->xlfd_mask & XAW_TPROP_AVGWIDTH)) &&
1473 	(combine->xlfd_mask & XAW_TPROP_AVGWIDTH)) {
1474 	property->xlfd_mask |= XAW_TPROP_AVGWIDTH;
1475 	property->avgwidth = combine->avgwidth;
1476     }
1477     if ((override || !(property->xlfd_mask & XAW_TPROP_REGISTRY)) &&
1478 	(combine->xlfd_mask & XAW_TPROP_REGISTRY)) {
1479 	property->xlfd_mask |= XAW_TPROP_REGISTRY;
1480 	property->registry = combine->registry;
1481     }
1482     if ((override || !(property->xlfd_mask & XAW_TPROP_ENCODING)) &&
1483 	(combine->xlfd_mask & XAW_TPROP_ENCODING)) {
1484 	property->xlfd_mask |= XAW_TPROP_ENCODING;
1485 	property->encoding = combine->encoding;
1486     }
1487 
1488     return (property);
1489 }
1490 
1491 /*
1492  * The default property must be defined first, if the code is willing to
1493  * combine properties.
1494  */
1495 XawTextPropertyList *
XawTextSinkConvertPropertyList(String name,String spec,Screen * screen,Colormap colormap,int depth)1496 XawTextSinkConvertPropertyList(String name, String spec, Screen *screen,
1497 			       Colormap colormap, int depth)
1498 {
1499     XrmQuark qname = XrmStringToQuark(name);
1500     XawTextPropertyList **ptr = NULL;
1501     XawTextPropertyList *propl, *prev = NULL;
1502     XawTextProperty *def_prop = NULL;
1503     char * str;
1504     String tok;
1505     char *tmp;
1506     char buffer[BUFSIZ];
1507 
1508     if (prop_lists) ptr = (XawTextPropertyList**)
1509 	bsearch((void*)(long)qname, prop_lists, num_prop_lists,
1510 		sizeof(XawTextPropertyList*), bcmp_qident);
1511     if (ptr) {
1512 	propl = *ptr;
1513 	while (propl) {
1514 	    prev = propl;
1515 	    if (propl->screen == screen &&
1516 		propl->colormap == colormap &&
1517 		propl->depth == depth)
1518 		return (propl);
1519 	    propl = propl->next;
1520 	}
1521     }
1522 
1523     propl = XtNew(XawTextPropertyList);
1524     propl->identifier = qname;
1525     propl->screen = screen;
1526     propl->colormap = colormap;
1527     propl->depth = depth;
1528     propl->next = NULL;
1529 
1530     if (prev)
1531 	prev->next = propl;
1532 
1533     propl->properties = NULL;
1534     propl->num_properties = 0;
1535 
1536     str = XtNewString(spec);
1537     for (tok = str; tok; tok = tmp) {
1538 	XawTextProperty *prop;
1539 	XawParams *params;
1540 	XrmQuark ident;
1541 	XawArgVal *argval;
1542 	XColor color, exact;
1543 
1544 	if (def_prop == NULL && propl->num_properties)
1545 	    def_prop = _XawTextSinkGetProperty(propl, Qdefault);
1546 	tmp = strchr(tok, ',');
1547 	if (tmp) {
1548 	    *tmp = '\0';
1549 	    if (*++tmp == '\0')
1550 		tmp = NULL;
1551 	}
1552 	params = XawParseParamsString(tok);
1553 	ident = XrmStringToQuark(params->name);
1554 	if (ident == NULLQUARK) {
1555 	    snprintf(buffer, sizeof(buffer), "Bad text property name \"%s\".",
1556 		     params->name);
1557 	    XtAppWarning(XtDisplayToApplicationContext
1558 			 (DisplayOfScreen(screen)), buffer);
1559 	    DestroyTextPropertyList(propl);
1560 	    if (prev)
1561 		prev->next = NULL;
1562 	    XawFreeParamsStruct(params);
1563 	    return (NULL);
1564 	}
1565 	else if (_XawTextSinkGetProperty(propl, ident) != NULL) {
1566 	    XawFreeParamsStruct(params);
1567 	    continue;
1568 	}
1569 
1570 	prop = (XawTextProperty*)XtCalloc(1, sizeof(XawTextProperty));
1571 	prop->identifier = ident;
1572 
1573 	if ((argval = XawFindArgVal(params, "font")) != NULL &&
1574 	    argval->value) {
1575 
1576 	    if ((prop->font = XLoadQueryFont(DisplayOfScreen(screen),
1577 					     argval->value)) == NULL) {
1578 		snprintf(buffer, sizeof(buffer), "Cannot load font \"%s\".",
1579 			 argval->value);
1580 		XtAppWarning(XtDisplayToApplicationContext
1581 			     (DisplayOfScreen(screen)), buffer);
1582 		DestroyTextPropertyList(propl);
1583 		if (prev)
1584 		    prev->next = NULL;
1585 		XawFreeParamsStruct(params);
1586 		return (NULL);
1587 	    }
1588 	    prop->mask |= XAW_TPROP_FONT;
1589 	    SetXlfdDefaults(DisplayOfScreen(screen), prop);
1590 	}
1591 	/* fontset processing here */
1592 
1593 	if ((argval = XawFindArgVal(params, "foreground")) != NULL &&
1594 	    argval->value) {
1595 	    if (!XAllocNamedColor(DisplayOfScreen(screen), colormap,
1596 				  argval->value, &color, &exact)) {
1597 		snprintf(buffer, sizeof(buffer),
1598 			 "Cannot allocate color \"%s\".", argval->value);
1599 		XtAppWarning(XtDisplayToApplicationContext
1600 			     (DisplayOfScreen(screen)), buffer);
1601 		DestroyTextPropertyList(propl);
1602 		if (prev)
1603 		    prev->next = NULL;
1604 		XawFreeParamsStruct(params);
1605 		return (NULL);
1606 	    }
1607 	    prop->foreground = color.pixel;
1608 	    prop->mask |= XAW_TPROP_FOREGROUND;
1609 	}
1610 	if ((argval = XawFindArgVal(params, "background")) != NULL &&
1611 	    argval->value) {
1612 	    if (!XAllocNamedColor(DisplayOfScreen(screen), colormap,
1613 				  argval->value, &color, &exact)) {
1614 		snprintf(buffer, sizeof(buffer),
1615 			 "Cannot allocate color \"%s\".", argval->value);
1616 		XtAppWarning(XtDisplayToApplicationContext
1617 			     (DisplayOfScreen(screen)), buffer);
1618 		DestroyTextPropertyList(propl);
1619 		if (prev)
1620 		    prev->next = NULL;
1621 		XawFreeParamsStruct(params);
1622 		return (NULL);
1623 	    }
1624 	    prop->background = color.pixel;
1625 	    prop->mask |= XAW_TPROP_BACKGROUND;
1626 	}
1627 	/* foreground_pixmap and background_pixmap processing here */
1628 
1629 	if (XawFindArgVal(params, "underline"))
1630 	    prop->mask |= XAW_TPROP_UNDERLINE;
1631 	if (XawFindArgVal(params, "overstrike"))
1632 	    prop->mask |= XAW_TPROP_OVERSTRIKE;
1633 
1634 	if (XawFindArgVal(params, "subscript"))
1635 	    prop->mask |= XAW_TPROP_SUBSCRIPT;
1636 	else if (XawFindArgVal(params, "superscript"))
1637 	    prop->mask |= XAW_TPROP_SUPERSCRIPT;
1638 
1639 	/* xlfd */
1640 	if ((argval = XawFindArgVal(params, "foundry")) != NULL &&
1641 	    argval->value) {
1642 	    prop->xlfd_mask |= XAW_TPROP_FOUNDRY;
1643 	    prop->foundry = XrmStringToQuark(argval->value);
1644 	}
1645 	if ((argval = XawFindArgVal(params, "family")) != NULL &&
1646 	    argval->value) {
1647 	    prop->xlfd_mask |= XAW_TPROP_FAMILY;
1648 	    prop->family = XrmStringToQuark(argval->value);
1649 	}
1650 	if ((argval = XawFindArgVal(params, "weight")) != NULL &&
1651 	    argval->value) {
1652 	    prop->xlfd_mask |= XAW_TPROP_WEIGHT;
1653 	    prop->weight = XrmStringToQuark(argval->value);
1654 	}
1655 	if ((argval = XawFindArgVal(params, "slant")) != NULL &&
1656 	    argval->value) {
1657 	    prop->xlfd_mask |= XAW_TPROP_SLANT;
1658 	    prop->slant = XrmStringToQuark(argval->value);
1659 	}
1660 	if ((argval = XawFindArgVal(params, "setwidth")) != NULL &&
1661 	    argval->value) {
1662 	    prop->xlfd_mask |= XAW_TPROP_SETWIDTH;
1663 	    prop->setwidth = XrmStringToQuark(argval->value);
1664 	}
1665 	if ((argval = XawFindArgVal(params, "addstyle")) != NULL &&
1666 	    argval->value) {
1667 	    prop->xlfd_mask |= XAW_TPROP_ADDSTYLE;
1668 	    prop->addstyle = XrmStringToQuark(argval->value);
1669 	}
1670 	if ((argval = XawFindArgVal(params, "pixelsize")) != NULL &&
1671 	    argval->value) {
1672 	    prop->xlfd_mask |= XAW_TPROP_PIXELSIZE;
1673 	    prop->pixel_size = XrmStringToQuark(argval->value);
1674 	}
1675 	if ((argval = XawFindArgVal(params, "pointsize")) != NULL &&
1676 	    argval->value) {
1677 	    prop->xlfd_mask |= XAW_TPROP_POINTSIZE;
1678 	    prop->point_size = XrmStringToQuark(argval->value);
1679 	}
1680 	if ((argval = XawFindArgVal(params, "resx")) != NULL &&
1681 	    argval->value) {
1682 	    prop->xlfd_mask |= XAW_TPROP_RESX;
1683 	    prop->res_x = XrmStringToQuark(argval->value);
1684 	}
1685 	if ((argval = XawFindArgVal(params, "resy")) != NULL &&
1686 	    argval->value) {
1687 	    prop->xlfd_mask |= XAW_TPROP_RESY;
1688 	    prop->res_y = XrmStringToQuark(argval->value);
1689 	}
1690 	if ((argval = XawFindArgVal(params, "spacing")) != NULL &&
1691 	    argval->value) {
1692 	    prop->xlfd_mask |= XAW_TPROP_SPACING;
1693 	    prop->spacing = XrmStringToQuark(argval->value);
1694 	}
1695 	if ((argval = XawFindArgVal(params, "avgwidth")) != NULL &&
1696 	    argval->value) {
1697 	    prop->xlfd_mask |= XAW_TPROP_AVGWIDTH;
1698 	    prop->avgwidth = XrmStringToQuark(argval->value);
1699 	}
1700 	if ((argval = XawFindArgVal(params, "registry")) != NULL &&
1701 	    argval->value) {
1702 	    prop->xlfd_mask |= XAW_TPROP_REGISTRY;
1703 	    prop->registry = XrmStringToQuark(argval->value);
1704 	}
1705 	if ((argval = XawFindArgVal(params, "encoding")) != NULL &&
1706 	    argval->value) {
1707 	    prop->xlfd_mask |= XAW_TPROP_ENCODING;
1708 	    prop->encoding = XrmStringToQuark(argval->value);
1709 	}
1710 
1711 	if (def_prop)
1712 	    (void)XawTextSinkCombineProperty(NULL, prop, def_prop, False);
1713 	(void)_XawTextSinkAddProperty(propl, prop, False);
1714 
1715 	XawFreeParamsStruct(params);
1716     }
1717 
1718     prop_lists = (XawTextPropertyList**)
1719     XtRealloc((XtPointer)prop_lists,
1720 	      (Cardinal)(sizeof(XawTextPropertyList*) *
1721 			 (num_prop_lists + 1)));
1722     prop_lists[num_prop_lists++] = propl;
1723     qsort((void*)prop_lists, num_prop_lists, sizeof(XawTextPropertyList*),
1724 	  qcmp_qident);
1725 
1726     XtFree(str);
1727 
1728     return (propl);
1729 }
1730 
1731 /*ARGSUSED*/
1732 static Boolean
CvtStringToPropertyList(Display * dpy,XrmValue * args,Cardinal * num_args,XrmValue * fromVal,XrmValue * toVal,XtPointer * converter_data _X_UNUSED)1733 CvtStringToPropertyList(Display *dpy, XrmValue *args, Cardinal *num_args,
1734 			XrmValue *fromVal, XrmValue *toVal,
1735 			XtPointer *converter_data _X_UNUSED)
1736 {
1737     XawTextPropertyList *propl = NULL;
1738     String name;
1739     Widget w;
1740 
1741     if (*num_args != 1) {
1742       XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1743 		      "wrongParameters", "cvtStringToTextProperties",
1744 		      "ToolkitError",
1745 		      "String to textProperties conversion needs widget argument",
1746 		      NULL, NULL);
1747 	return (False);
1748     }
1749 
1750     w = *(Widget*)args[0].addr;
1751     while (w && !XtIsWidget(w))
1752 	w = XtParent(w);
1753 
1754     name = (String)(fromVal[0].addr);
1755 
1756     if (w) {
1757 	XawTextPropertyList **ptr = NULL;
1758 	if (prop_lists) ptr = (XawTextPropertyList**)
1759 	    bsearch((void*)(long)XrmStringToQuark(name),
1760 		    prop_lists, num_prop_lists,
1761 		    sizeof(XawTextPropertyList*), bcmp_qident);
1762 
1763 	if (ptr) {
1764 	    Screen *screen = w->core.screen;
1765 	    Colormap colormap = w->core.colormap;
1766 	    int depth = (int)w->core.depth;
1767 
1768 	    propl = *ptr;
1769 	    while (propl) {
1770 		if (propl->screen == screen &&
1771 		    propl->colormap == colormap &&
1772 		    propl->depth == depth)
1773 		    break;
1774 		propl = propl->next;
1775 	    }
1776 	}
1777     }
1778 
1779     if (!propl) {
1780 	XtDisplayStringConversionWarning(dpy, (String)fromVal->addr,
1781 					 XawRTextProperties);
1782 	toVal->addr = NULL;
1783 	toVal->size = sizeof(XawTextPropertyList*);
1784 	return (False);
1785     }
1786 
1787     if (toVal->addr != NULL) {
1788 	if (toVal->size < sizeof(XawTextPropertyList*))	{
1789 	    toVal->size = sizeof(XawTextPropertyList*);
1790 	    return (False);
1791 	}
1792 	*(XawTextPropertyList**)(toVal->addr) = propl;
1793     }
1794     else {
1795 	static XawTextPropertyList *static_val;
1796 
1797 	static_val = propl;
1798 	toVal->addr = (XPointer)&static_val;
1799     }
1800     toVal->size = sizeof(XawTextProperty*);
1801 
1802     return (True);
1803 }
1804 
1805 /*ARGSUSED*/
1806 static Boolean
CvtPropertyListToString(Display * dpy,XrmValue * args _X_UNUSED,Cardinal * num_args _X_UNUSED,XrmValue * fromVal,XrmValue * toVal,XtPointer * converter_data _X_UNUSED)1807 CvtPropertyListToString(Display *dpy, XrmValue *args _X_UNUSED, Cardinal *num_args _X_UNUSED,
1808 			XrmValue *fromVal, XrmValue *toVal,
1809 			XtPointer *converter_data _X_UNUSED)
1810 {
1811     static char *buffer;
1812     Cardinal size;
1813     XawTextPropertyList *propl;
1814 
1815     propl = *(XawTextPropertyList**)fromVal[0].addr;
1816     if (propl == NULL) {
1817         XtAppWarningMsg(XtDisplayToApplicationContext(dpy),
1818 		      "wrongParameters", "cvtPropertyListToString",
1819 		      "ToolkitError",
1820 		      "textProperties to String conversion needs property list argument",
1821 		      NULL, NULL);
1822 	return (False);
1823     }
1824 
1825     buffer = XrmQuarkToString(propl->identifier);
1826     size = (Cardinal)(strlen(buffer) + 1);
1827 
1828     if (toVal->addr != NULL) {
1829 	if (toVal->size < size) {
1830 	    toVal->size = size;
1831 	    return (False);
1832 	}
1833 	strcpy((char *)toVal->addr, buffer);
1834     }
1835     else
1836 	toVal->addr = buffer;
1837     toVal->size = size;
1838 
1839     return (True);
1840 }
1841 #endif
1842