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