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