1 #if ( !defined(lint) && !defined(SABER) )
2 static char Xrcsid
[] = "$XConsortium: TextSink.c,v 1.9 89/11/21 15:53:22 swick Exp $";
6 * Copyright 1989 Massachusetts Institute of Technology
8 * Permission to use, copy, modify, distribute, and sell this software and its
9 * documentation for any purpose is hereby granted without fee, provided that
10 * the above copyright notice appear in all copies and that both that
11 * copyright notice and this permission notice appear in supporting
12 * documentation, and that the name of M.I.T. not be used in advertising or
13 * publicity pertaining to distribution of the software without specific,
14 * written prior permission. M.I.T. makes no representations about the
15 * suitability of this software for any purpose. It is provided "as is"
16 * without express or implied warranty.
18 * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
20 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
22 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
23 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 * Author: Chris Peterson, MIT X Consortium.
27 * Much code taken from X11R3 AsciiSink.
31 * TextSink.c - TextSink object. (For use with the text widget).
37 #include <X11/IntrinsicP.h>
38 #include <X11/StringDefs.h>
39 #include <./Xaw3_1XawInit.h>
40 #include <./Xaw3_1TextSinkP.h>
41 #include <./Xaw3_1TextP.h>
43 /****************************************************************
45 * Full class record constant
47 ****************************************************************/
49 static void ClassPartInitialize(), Initialize(), Destroy();
50 static Boolean
SetValues();
52 static int MaxHeight(), MaxLines();
53 static void DisplayText(), InsertCursor(), ClearToBackground(), FindPosition();
54 static void FindDistance(), Resolve(), SetTabs(), GetCursorBounds();
56 #define offset(field) XtOffset(TextSinkObject, text_sink.field)
57 static XtResource resources
[] = {
58 {XtNfont
, XtCFont
, XtRFontStruct
, sizeof (XFontStruct
*),
59 offset(font
), XtRString
, XtDefaultFont
},
60 {XtNforeground
, XtCForeground
, XtRPixel
, sizeof (Pixel
),
61 offset(foreground
), XtRString
, XtDefaultForeground
},
62 {XtNbackground
, XtCBackground
, XtRPixel
, sizeof (Pixel
),
63 offset(background
), XtRString
, XtDefaultBackground
},
67 #define SuperClass (&objectClassRec)
68 TextSinkClassRec textSinkClassRec
= {
70 /* core_class fields */
71 /* superclass */ (WidgetClass
) SuperClass
,
72 /* class_name */ "TextSink",
73 /* widget_size */ sizeof(TextSinkRec
),
74 /* class_initialize */ XawInitializeWidgetSet
,
75 /* class_part_initialize */ ClassPartInitialize
,
76 /* class_inited */ FALSE
,
77 /* initialize */ Initialize
,
78 /* initialize_hook */ NULL
,
82 /* resources */ resources
,
83 /* num_resources */ XtNumber(resources
),
84 /* xrm_class */ NULLQUARK
,
89 /* destroy */ Destroy
,
92 /* set_values */ SetValues
,
93 /* set_values_hook */ NULL
,
95 /* get_values_hook */ NULL
,
97 /* version */ XtVersion
,
98 /* callback_private */ NULL
,
104 /* textSink_class fields */
106 /* DisplayText */ DisplayText
,
107 /* InsertCursor */ InsertCursor
,
108 /* ClearToBackground */ ClearToBackground
,
109 /* FindPosition */ FindPosition
,
110 /* FindDistance */ FindDistance
,
111 /* Resolve */ Resolve
,
112 /* MaxLines */ MaxLines
,
113 /* MaxHeight */ MaxHeight
,
114 /* SetTabs */ SetTabs
,
115 /* GetCursorBounds */ GetCursorBounds
,
119 WidgetClass textSinkObjectClass
= (WidgetClass
)&textSinkClassRec
;
122 ClassPartInitialize(wc
)
125 register TextSinkObjectClass t_src
, superC
;
127 t_src
= (TextSinkObjectClass
) wc
;
128 superC
= (TextSinkObjectClass
) t_src
->object_class
.superclass
;
131 * We don't need to check for null super since we'll get to TextSink
135 if (t_src
->text_sink_class
.DisplayText
== XtInheritDisplayText
)
136 t_src
->text_sink_class
.DisplayText
= superC
->text_sink_class
.DisplayText
;
138 if (t_src
->text_sink_class
.InsertCursor
== XtInheritInsertCursor
)
139 t_src
->text_sink_class
.InsertCursor
=
140 superC
->text_sink_class
.InsertCursor
;
142 if (t_src
->text_sink_class
.ClearToBackground
== XtInheritClearToBackground
)
143 t_src
->text_sink_class
.ClearToBackground
=
144 superC
->text_sink_class
.ClearToBackground
;
146 if (t_src
->text_sink_class
.FindPosition
== XtInheritFindPosition
)
147 t_src
->text_sink_class
.FindPosition
=
148 superC
->text_sink_class
.FindPosition
;
150 if (t_src
->text_sink_class
.FindDistance
== XtInheritFindDistance
)
151 t_src
->text_sink_class
.FindDistance
=
152 superC
->text_sink_class
.FindDistance
;
154 if (t_src
->text_sink_class
.Resolve
== XtInheritResolve
)
155 t_src
->text_sink_class
.Resolve
= superC
->text_sink_class
.Resolve
;
157 if (t_src
->text_sink_class
.MaxLines
== XtInheritMaxLines
)
158 t_src
->text_sink_class
.MaxLines
= superC
->text_sink_class
.MaxLines
;
160 if (t_src
->text_sink_class
.MaxHeight
== XtInheritMaxHeight
)
161 t_src
->text_sink_class
.MaxHeight
= superC
->text_sink_class
.MaxHeight
;
163 if (t_src
->text_sink_class
.SetTabs
== XtInheritSetTabs
)
164 t_src
->text_sink_class
.SetTabs
= superC
->text_sink_class
.SetTabs
;
166 if (t_src
->text_sink_class
.GetCursorBounds
== XtInheritGetCursorBounds
)
167 t_src
->text_sink_class
.GetCursorBounds
=
168 superC
->text_sink_class
.GetCursorBounds
;
171 /* Function Name: Initialize
172 * Description: Initializes the TextSink Object.
173 * Arguments: request, new - the requested and new values for the object
181 Initialize(request
, new)
184 TextSinkObject sink
= (TextSinkObject
) new;
186 sink
->text_sink
.tab_count
= 0; /* Initialize the tab stops. */
187 sink
->text_sink
.tabs
= NULL
;
188 sink
->text_sink
.char_tabs
= NULL
;
191 /* Function Name: Destroy
192 * Description: This function cleans up when the object is
194 * Arguments: w - the TextSink Object.
201 TextSinkObject sink
= (TextSinkObject
) w
;
203 if (sink
->text_sink
.tabs
!= NULL
)
204 XtFree((char *) sink
->text_sink
.tabs
);
207 /* Function Name: SetValues
208 * Description: Sets the values for the TextSink
209 * Arguments: current - current state of the object.
210 * request - what was requested.
211 * new - what the object will become.
212 * Returns: True if redisplay is needed.
217 SetValues(current
, request
, new)
218 Widget current
, request
, new;
220 TextSinkObject w
= (TextSinkObject
) new;
221 TextSinkObject old_w
= (TextSinkObject
) current
;
222 TextSinkObjectClass
class = (TextSinkObjectClass
) w
->object
.widget_class
;
224 if (w
->text_sink
.font
!= old_w
->text_sink
.font
) {
225 (*class->text_sink_class
.SetTabs
)(new, w
->text_sink
.tab_count
,
226 w
->text_sink
.char_tabs
);
227 ((TextWidget
)XtParent(new))->text
.redisplay_needed
= True
;
229 if (w
->text_sink
.foreground
!= old_w
->text_sink
.foreground
)
230 ((TextWidget
)XtParent(new))->text
.redisplay_needed
= True
;
236 /************************************************************
238 * Class specific methods.
240 ************************************************************/
242 /* Function Name: DisplayText
243 * Description: Stub function that in subclasses will display text.
244 * Arguments: w - the TextSink Object.
245 * x, y - location to start drawing text.
246 * pos1, pos2 - location of starting and ending points
247 * in the text buffer.
248 * highlight - hightlight this text?
251 * This function doesn't actually display anything, it is only a place
257 DisplayText(w
, x
, y
, pos1
, pos2
, highlight
)
261 XawTextPosition pos1
, pos2
;
266 /* Function Name: InsertCursor
267 * Description: Places the InsertCursor.
268 * Arguments: w - the TextSink Object.
269 * x, y - location for the cursor.
270 * staye - whether to turn the cursor on, or off.
273 * This function doesn't actually display anything, it is only a place
279 InsertCursor(w
, x
, y
, state
)
282 XawTextInsertState state
;
287 /* Function Name: ClearToBackground
288 * Description: Clears a region of the sink to the background color.
289 * Arguments: w - the TextSink Object.
290 * x, y - location of area to clear.
291 * width, height - size of area to clear
298 ClearToBackground (w
, x
, y
, width
, height
)
301 Dimension width
, height
;
304 * Don't clear in height or width are zero.
305 * XClearArea() has special semantic for these values.
308 if ( (height
== 0) || (width
== 0) ) return;
309 XClearArea(XtDisplayOfObject(w
), XtWindowOfObject(w
),
310 x
, y
, width
, height
, False
);
313 /* Function Name: FindPosition
314 * Description: Finds a position in the text.
315 * Arguments: w - the TextSink Object.
316 * fromPos - reference position.
317 * fromX - reference location.
318 * width, - width of section to paint text.
319 * stopAtWordBreak - returned position is a word break?
320 * resPos - Position to return. *** RETURNED ***
321 * resWidth - Width actually used. *** RETURNED ***
322 * resHeight - Height actually used. *** RETURNED ***
323 * Returns: none (see above).
328 FindPosition(w
, fromPos
, fromx
, width
, stopAtWordBreak
,
329 resPos
, resWidth
, resHeight
)
331 XawTextPosition fromPos
;
333 Boolean stopAtWordBreak
;
334 XawTextPosition
*resPos
;
335 int *resWidth
, *resHeight
;
338 *resHeight
= *resWidth
= 0;
341 /* Function Name: FindDistance
342 * Description: Find the Pixel Distance between two text Positions.
343 * Arguments: w - the TextSink Object.
344 * fromPos - starting Position.
345 * fromX - x location of starting Position.
346 * toPos - end Position.
347 * resWidth - Distance between fromPos and toPos.
348 * resPos - Acutal toPos used.
349 * resHeight - Height required by this text.
355 FindDistance (w
, fromPos
, fromx
, toPos
, resWidth
, resPos
, resHeight
)
357 XawTextPosition fromPos
;
359 XawTextPosition toPos
;
361 XawTextPosition
*resPos
;
364 *resWidth
= *resHeight
= 0;
368 /* Function Name: Resolve
369 * Description: Resloves a location to a position.
370 * Arguments: w - the TextSink Object.
371 * pos - a reference Position.
372 * fromx - a reference Location.
373 * width - width to move.
374 * resPos - the resulting position.
380 Resolve (w
, pos
, fromx
, width
, resPos
)
384 XawTextPosition
*resPos
;
389 /* Function Name: MaxLines
390 * Description: Finds the Maximum number of lines that will fit in
392 * Arguments: w - the TextSink Object.
393 * height - height to fit lines into.
394 * Returns: the number of lines that will fit.
403 TextSinkObject sink
= (TextSinkObject
) w
;
406 font_height
= sink
->text_sink
.font
->ascent
+ sink
->text_sink
.font
->descent
;
407 return( ((int) height
) / font_height
);
410 /* Function Name: MaxHeight
411 * Description: Finds the Minium height that will contain a given number
413 * Arguments: w - the TextSink Object.
414 * lines - the number of lines.
415 * Returns: the height.
424 TextSinkObject sink
= (TextSinkObject
) w
;
426 return(lines
* (sink
->text_sink
.font
->ascent
+
427 sink
->text_sink
.font
->descent
));
430 /* Function Name: SetTabs
431 * Description: Sets the Tab stops.
432 * Arguments: w - the TextSink Object.
433 * tab_count - the number of tabs in the list.
434 * tabs - the text positions of the tabs.
439 SetTabs(w
, tab_count
, tabs
)
444 TextSinkObject sink
= (TextSinkObject
) w
;
446 Atom XA_FIGURE_WIDTH
;
447 unsigned long figure_width
= 0;
448 XFontStruct
*font
= sink
->text_sink
.font
;
451 * Find the figure width of the current font.
454 XA_FIGURE_WIDTH
= XInternAtom(XtDisplayOfObject(w
), "FIGURE_WIDTH", FALSE
);
455 if ( (XA_FIGURE_WIDTH
!= NULL
) &&
456 ( (!XGetFontProperty(font
, XA_FIGURE_WIDTH
, &figure_width
)) ||
457 (figure_width
== 0)) )
458 if (font
->per_char
&& font
->min_char_or_byte2
<= '$' &&
459 font
->max_char_or_byte2
>= '$')
460 figure_width
= font
->per_char
['$' - font
->min_char_or_byte2
].width
;
462 figure_width
= font
->max_bounds
.width
;
464 if (tab_count
> sink
->text_sink
.tab_count
) {
465 sink
->text_sink
.tabs
= (Position
*) XtRealloc((caddr_t
)sink
->text_sink
.tabs
,
466 (Cardinal
) (tab_count
* sizeof(Position
)));
467 sink
->text_sink
.char_tabs
= (short *) XtRealloc(
468 (caddr_t
) sink
->text_sink
.char_tabs
,
469 (Cardinal
) (tab_count
* sizeof(short)));
472 for ( i
= 0 ; i
< tab_count
; i
++ ) {
473 sink
->text_sink
.tabs
[i
] = tabs
[i
] * figure_width
;
474 sink
->text_sink
.char_tabs
[i
] = tabs
[i
];
477 sink
->text_sink
.tab_count
= tab_count
;
480 /* Function Name: GetCursorBounds
481 * Description: Finds the bounding box for the insert curor (caret).
482 * Arguments: w - the TextSinkObject.
483 * rect - an X rectance containing the cursor bounds.
484 * Returns: none (fills in rect).
489 GetCursorBounds(w
, rect
)
493 rect
->x
= rect
->y
= rect
->width
= rect
->height
= 0;
495 /************************************************************
499 ************************************************************/
502 /* Function Name: XawTextSinkDisplayText
503 * Description: Stub function that in subclasses will display text.
504 * Arguments: w - the TextSink Object.
505 * x, y - location to start drawing text.
506 * pos1, pos2 - location of starting and ending points
507 * in the text buffer.
508 * highlight - hightlight this text?
511 * This function doesn't actually display anything, it is only a place
517 XawTextSinkDisplayText(w
, x
, y
, pos1
, pos2
, highlight
)
521 XawTextPosition pos1
, pos2
;
523 TextSinkObjectClass
class = (TextSinkObjectClass
) w
->core
.widget_class
;
525 (*class->text_sink_class
.DisplayText
)(w
, x
, y
, pos1
, pos2
, highlight
);
528 /* Function Name: XawTextSinkInsertCursor
529 * Description: Places the InsertCursor.
530 * Arguments: w - the TextSink Object.
531 * x, y - location for the cursor.
532 * staye - whether to turn the cursor on, or off.
535 * This function doesn't actually display anything, it is only a place
541 XawTextSinkInsertCursor(w
, x
, y
, state
)
544 XawTextInsertState state
;
546 TextSinkObjectClass
class = (TextSinkObjectClass
) w
->core
.widget_class
;
548 (*class->text_sink_class
.InsertCursor
)(w
, x
, y
, state
);
552 /* Function Name: XawTextSinkClearToBackground
553 * Description: Clears a region of the sink to the background color.
554 * Arguments: w - the TextSink Object.
555 * x, y - location of area to clear.
556 * width, height - size of area to clear
559 * This function doesn't actually display anything, it is only a place
565 XawTextSinkClearToBackground (w
, x
, y
, width
, height
)
568 Dimension width
, height
;
570 TextSinkObjectClass
class = (TextSinkObjectClass
) w
->core
.widget_class
;
572 (*class->text_sink_class
.ClearToBackground
)(w
, x
, y
, width
, height
);
575 /* Function Name: XawTextSinkFindPosition
576 * Description: Finds a position in the text.
577 * Arguments: w - the TextSink Object.
578 * fromPos - reference position.
579 * fromX - reference location.
580 * width, - width of section to paint text.
581 * stopAtWordBreak - returned position is a word break?
582 * resPos - Position to return. *** RETURNED ***
583 * resWidth - Width actually used. *** RETURNED ***
584 * resHeight - Height actually used. *** RETURNED ***
585 * Returns: none (see above).
590 XawTextSinkFindPosition(w
, fromPos
, fromx
, width
, stopAtWordBreak
,
591 resPos
, resWidth
, resHeight
)
593 XawTextPosition fromPos
;
595 Boolean stopAtWordBreak
;
596 XawTextPosition
*resPos
;
597 int *resWidth
, *resHeight
;
599 TextSinkObjectClass
class = (TextSinkObjectClass
) w
->core
.widget_class
;
601 (*class->text_sink_class
.FindPosition
)(w
, fromPos
, fromx
, width
,
603 resPos
, resWidth
, resHeight
);
606 /* Function Name: XawTextSinkFindDistance
607 * Description: Find the Pixel Distance between two text Positions.
608 * Arguments: w - the TextSink Object.
609 * fromPos - starting Position.
610 * fromX - x location of starting Position.
611 * toPos - end Position.
612 * resWidth - Distance between fromPos and toPos.
613 * resPos - Acutal toPos used.
614 * resHeight - Height required by this text.
620 XawTextSinkFindDistance (w
, fromPos
, fromx
, toPos
, resWidth
, resPos
, resHeight
)
622 XawTextPosition fromPos
, toPos
, *resPos
;
623 int fromx
, *resWidth
, *resHeight
;
625 TextSinkObjectClass
class = (TextSinkObjectClass
) w
->core
.widget_class
;
627 (*class->text_sink_class
.FindDistance
)(w
, fromPos
, fromx
, toPos
,
628 resWidth
, resPos
, resHeight
);
631 /* Function Name: XawTextSinkResolve
632 * Description: Resloves a location to a position.
633 * Arguments: w - the TextSink Object.
634 * pos - a reference Position.
635 * fromx - a reference Location.
636 * width - width to move.
637 * resPos - the resulting position.
643 XawTextSinkResolve(w
, pos
, fromx
, width
, resPos
)
647 XawTextPosition
*resPos
;
649 TextSinkObjectClass
class = (TextSinkObjectClass
) w
->core
.widget_class
;
651 (*class->text_sink_class
.Resolve
)(w
, pos
, fromx
, width
, resPos
);
654 /* Function Name: XawTextSinkMaxLines
655 * Description: Finds the Maximum number of lines that will fit in
657 * Arguments: w - the TextSink Object.
658 * height - height to fit lines into.
659 * Returns: the number of lines that will fit.
664 XawTextSinkMaxLines(w
, height
)
668 TextSinkObjectClass
class = (TextSinkObjectClass
) w
->core
.widget_class
;
670 return((*class->text_sink_class
.MaxLines
)(w
, height
));
673 /* Function Name: XawTextSinkMaxHeight
674 * Description: Finds the Minium height that will contain a given number
676 * Arguments: w - the TextSink Object.
677 * lines - the number of lines.
678 * Returns: the height.
683 XawTextSinkMaxHeight(w
, lines
)
687 TextSinkObjectClass
class = (TextSinkObjectClass
) w
->core
.widget_class
;
689 return((*class->text_sink_class
.MaxHeight
)(w
, lines
));
692 /* Function Name: XawTextSinkSetTabs
693 * Description: Sets the Tab stops.
694 * Arguments: w - the TextSink Object.
695 * tab_count - the number of tabs in the list.
696 * tabs - the text positions of the tabs.
701 XawTextSinkSetTabs(w
, tab_count
, tabs
)
703 int tab_count
, *tabs
;
706 TextSinkObjectClass
class = (TextSinkObjectClass
) w
->core
.widget_class
;
707 short *char_tabs
= (short*)XtMalloc( (unsigned)tab_count
*sizeof(short) );
711 for (i
= tab_count
, tab
= char_tabs
; i
; i
--) *tab
++ = (short)*tabs
++;
713 (*class->text_sink_class
.SetTabs
)(w
, tab_count
, char_tabs
);
714 XtFree((XtPointer
)char_tabs
);
718 /* Function Name: XawTextSinkGetCursorBounds
719 * Description: Finds the bounding box for the insert curor (caret).
720 * Arguments: w - the TextSinkObject.
721 * rect - an X rectance containing the cursor bounds.
722 * Returns: none (fills in rect).
727 XawTextSinkGetCursorBounds(w
, rect
)
731 TextSinkObjectClass
class = (TextSinkObjectClass
) w
->core
.widget_class
;
733 (*class->text_sink_class
.GetCursorBounds
)(w
, rect
);