1 /*
2 * Copyright 1991 by OMRON Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of OMRON not be used in advertising
9 * or publicity pertaining to distribution of the software without specific,
10 * written prior permission. OMRON makes no representations about the
11 * suitability of this software for any purpose. It is provided "as is"
12 * without express or implied warranty.
13 *
14 * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL OMRON BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 *
22 * Author: Li Yuhong OMRON Corporation
23 */
24
25 /***********************************************************
26
27 Copyright (c) 1987, 1988, 1994 X Consortium
28
29 Permission is hereby granted, free of charge, to any person obtaining a copy
30 of this software and associated documentation files (the "Software"), to deal
31 in the Software without restriction, including without limitation the rights
32 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
33 copies of the Software, and to permit persons to whom the Software is
34 furnished to do so, subject to the following conditions:
35
36 The above copyright notice and this permission notice shall be included in
37 all copies or substantial portions of the Software.
38
39 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
42 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
43 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
44 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
45
46 Except as contained in this notice, the name of the X Consortium shall not be
47 used in advertising or otherwise to promote the sale, use or other dealings
48 in this Software without prior written authorization from the X Consortium.
49
50
51 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
52
53 All Rights Reserved
54
55 Permission to use, copy, modify, and distribute this software and its
56 documentation for any purpose and without fee is hereby granted,
57 provided that the above copyright notice appear in all copies and that
58 both that copyright notice and this permission notice appear in
59 supporting documentation, and that the name of Digital not be
60 used in advertising or publicity pertaining to distribution of the
61 software without specific, written prior permission.
62
63 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
64 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
65 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
66 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
67 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
68 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
69 SOFTWARE.
70
71 ******************************************************************/
72
73 #ifdef HAVE_CONFIG_H
74 #include "config.h"
75 #endif
76 #include <X11/IntrinsicP.h>
77 #include <X11/StringDefs.h>
78 #include <X11/Xatom.h>
79 #include <X11/Xaw3dxft/XawInit.h>
80 #include <X11/Xaw3dxft/MultiSinkP.h>
81 #include <X11/Xaw3dxft/MultiSrcP.h>
82 #include <X11/Xaw3dxft/TextP.h>
83 #include "XawI18n.h"
84 #include <stdio.h>
85 #include <stdlib.h>
86 #include <ctype.h>
87
88 #ifdef GETLASTPOS
89 #undef GETLASTPOS /* We will use our own GETLASTPOS. */
90 #endif
91
92 #define GETLASTPOS XawTextSourceScan(source, (XawTextPosition) 0, XawstAll, XawsdRight, 1, TRUE)
93
94 static void Initialize(Widget, Widget, ArgList, Cardinal *);
95 static void Destroy(Widget);
96 static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *);
97 static int MaxLines(Widget, Dimension);
98 static int MaxHeight(Widget, int);
99 static void SetTabs(Widget, int, short *);
100
101 static void DisplayText(Widget, Position, Position, XawTextPosition,
102 XawTextPosition, Boolean);
103 static void InsertCursor(Widget, Position, Position, XawTextInsertState);
104 static void FindPosition(Widget, XawTextPosition, int, int, Boolean,
105 XawTextPosition *, int *, int *);
106 static void FindDistance(Widget, XawTextPosition, int, XawTextPosition,
107 int *, XawTextPosition *, int *);
108 static void Resolve(Widget, XawTextPosition, int, int, XawTextPosition *);
109 static void GetCursorBounds(Widget, XRectangle *);
110
111 #define offset(field) XtOffsetOf(MultiSinkRec, multi_sink.field)
112
113 static XtResource resources[] = {
114 {XtNfontSet, XtCFontSet, XtRFontSet, sizeof (XFontSet),
115 offset(fontset), XtRString, XtDefaultFontSet},
116 {XtNecho, XtCOutput, XtRBoolean, sizeof(Boolean),
117 offset(echo), XtRImmediate, (XtPointer) True},
118 {XtNdisplayNonprinting, XtCOutput, XtRBoolean, sizeof(Boolean),
119 offset(display_nonprinting), XtRImmediate, (XtPointer) True},
120 };
121 #undef offset
122
123 #define SuperClass (&textSinkClassRec)
124 MultiSinkClassRec multiSinkClassRec = {
125 { /* core_class fields */
126 /* superclass */ (WidgetClass) SuperClass,
127 /* class_name */ "MultiSink",
128 /* widget_size */ sizeof(MultiSinkRec),
129 /* class_initialize */ XawInitializeWidgetSet,
130 /* class_part_initialize */ NULL,
131 /* class_inited */ FALSE,
132 /* initialize */ Initialize,
133 /* initialize_hook */ NULL,
134 /* obj1 */ NULL,
135 /* obj2 */ NULL,
136 /* obj3 */ 0,
137 /* resources */ resources,
138 /* num_resources */ XtNumber(resources),
139 /* xrm_class */ NULLQUARK,
140 /* obj4 */ FALSE,
141 /* obj5 */ FALSE,
142 /* obj6 */ FALSE,
143 /* obj7 */ FALSE,
144 /* destroy */ Destroy,
145 /* obj8 */ NULL,
146 /* obj9 */ NULL,
147 /* set_values */ SetValues,
148 /* set_values_hook */ NULL,
149 /* obj10 */ NULL,
150 /* get_values_hook */ NULL,
151 /* obj11 */ NULL,
152 /* version */ XtVersion,
153 /* callback_private */ NULL,
154 /* obj12 */ NULL,
155 /* obj13 */ NULL,
156 /* obj14 */ NULL,
157 /* extension */ NULL
158 },
159 { /* text_sink_class fields */
160 /* DisplayText */ DisplayText,
161 /* InsertCursor */ InsertCursor,
162 /* ClearToBackground */ XtInheritClearToBackground,
163 /* FindPosition */ FindPosition,
164 /* FindDistance */ FindDistance,
165 /* Resolve */ Resolve,
166 /* MaxLines */ MaxLines,
167 /* MaxHeight */ MaxHeight,
168 /* SetTabs */ SetTabs,
169 /* GetCursorBounds */ GetCursorBounds
170 },
171 { /* multi_sink_class fields */
172 /* unused */ 0
173 }
174 };
175
176 WidgetClass multiSinkObjectClass = (WidgetClass)&multiSinkClassRec;
177
178 /* Utilities */
179
180 static int
CharWidth(Widget w,int x,wchar_t c)181 CharWidth (
182 Widget w,
183 int x,
184 wchar_t c)
185 {
186 int i, width;
187 MultiSinkObject sink = (MultiSinkObject) w;
188 XFontSet fontset = sink->multi_sink.fontset;
189 Position *tab;
190
191 if ( c == _Xaw_atowc(XawLF) ) return(0);
192
193 if (c == _Xaw_atowc(XawTAB)) {
194 /* Adjust for Left Margin. */
195 x -= ((TextWidget) XtParent(w))->text.margin.left;
196
197 if (x >= (int)XtParent(w)->core.width) return 0;
198 for (i = 0, tab = sink->text_sink.tabs ;
199 i < sink->text_sink.tab_count ; i++, tab++) {
200 if (x < *tab) {
201 if (*tab < (int)XtParent(w)->core.width)
202 return *tab - x;
203 else
204 return 0;
205 }
206 }
207 return 0;
208 }
209
210 if (XwcTextEscapement (fontset, &c, 1) == 0) {
211 if (sink->multi_sink.display_nonprinting)
212 c = _Xaw_atowc('@');
213 else {
214 c = _Xaw_atowc(XawSP);
215 }
216 }
217
218 /*
219 * if more efficiency(suppose one column is one ASCII char)
220
221 width = XwcGetColumn(fontset->font_charset, fontset->num_of_fonts, c) *
222 fontset->font_struct_list[0]->min_bounds.width;
223 *
224 * WARNING: Very Slower!!!
225 *
226 * Li Yuhong.
227 */
228
229 width = XwcTextEscapement(fontset, &c, 1);
230
231 return width;
232 }
233
234 /* Function Name: PaintText
235 * Description: Actually paints the text into the windoe.
236 * Arguments: w - the text widget.
237 * gc - gc to paint text with.
238 * x, y - location to paint the text.
239 * buf, len - buffer and length of text to paint.
240 * Returns: the width of the text painted, or 0.
241 *
242 * NOTE: If this string attempts to paint past the end of the window
243 * then this function will return zero.
244 */
245
246 static Dimension
PaintText(Widget w,GC gc,Position x,Position y,wchar_t * buf,int len)247 PaintText(Widget w, GC gc, Position x, Position y, wchar_t* buf, int len)
248 {
249 MultiSinkObject sink = (MultiSinkObject) w;
250 TextWidget ctx = (TextWidget) XtParent(w);
251
252 XFontSet fontset = sink->multi_sink.fontset;
253 Position max_x;
254 Dimension width = XwcTextEscapement(fontset, buf, len);
255 XFontSetExtents *ext = XExtentsOfFontSet(fontset);
256 max_x = (Position) ctx->core.width;
257
258 if ( ((int) width) <= -x) /* Don't draw if we can't see it. */
259 return(width);
260
261 XwcDrawImageString(XtDisplay(ctx), XtWindow(ctx), fontset, gc,
262 (int) x, (int) y, buf, len);
263 if ( (((Position) width + x) > max_x) && (ctx->text.margin.right != 0) ) {
264 x = ctx->core.width - ctx->text.margin.right;
265 width = ctx->text.margin.right;
266 XFillRectangle(XtDisplay((Widget) ctx), XtWindow( (Widget) ctx),
267 sink->multi_sink.normgc, (int) x,
268 (int) y - abs(ext->max_logical_extent.y),
269 (unsigned int) width,
270 (unsigned int) ext->max_logical_extent.height);
271 return(0);
272 }
273 return(width);
274 }
275
276 /* Sink Object Functions */
277
278 /*
279 * This function does not know about drawing more than one line of text.
280 */
281
282 static void
DisplayText(Widget w,Position x,Position y,XawTextPosition pos1,XawTextPosition pos2,Boolean highlight)283 DisplayText(Widget w, Position x, Position y, XawTextPosition pos1,
284 XawTextPosition pos2, Boolean highlight)
285 {
286 MultiSinkObject sink = (MultiSinkObject) w;
287 Widget source = XawTextGetSource(XtParent(w));
288 wchar_t buf[BUFSIZ];
289 XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset);
290
291 int j, k;
292 XawTextBlock blk;
293 GC gc = highlight ? sink->multi_sink.invgc : sink->multi_sink.normgc;
294 GC invgc = highlight ? sink->multi_sink.normgc : sink->multi_sink.invgc;
295
296 if (!sink->multi_sink.echo) return;
297
298 y += abs(ext->max_logical_extent.y);
299 for ( j = 0 ; pos1 < pos2 ; ) {
300 pos1 = XawTextSourceRead(source, pos1, &blk, (int) pos2 - pos1);
301 for (k = 0; k < blk.length; k++) {
302 if (j >= BUFSIZ) { /* buffer full, dump the text. */
303 x += PaintText(w, gc, x, y, buf, j);
304 j = 0;
305 }
306 buf[j] = ((wchar_t *)blk.ptr)[k];
307 if (buf[j] == _Xaw_atowc(XawLF))
308 continue;
309
310 else if (buf[j] == _Xaw_atowc(XawTAB)) {
311 Position temp = 0;
312 Dimension width;
313
314 if ((j != 0) && ((temp = PaintText(w, gc, x, y, buf, j)) == 0))
315 return;
316
317 x += temp;
318 width = CharWidth(w, x, _Xaw_atowc(XawTAB));
319 XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
320 invgc, (int) x,
321 (int) y - abs(ext->max_logical_extent.y),
322 (unsigned int)width,
323 (unsigned int)ext->max_logical_extent.height);
324 x += width;
325 j = -1;
326 }
327 else if (XwcTextEscapement (sink->multi_sink.fontset, &buf[j], 1) == 0) {
328 if (sink->multi_sink.display_nonprinting)
329 buf[j] = _Xaw_atowc('@');
330 else
331 buf[j] = _Xaw_atowc(' ');
332 }
333 j++;
334 }
335 }
336 if (j > 0)
337 (void) PaintText(w, gc, x, y, buf, j);
338 }
339
340 #define insertCursor_width 6
341 #define insertCursor_height 3
342 static char insertCursor_bits[] = {0x0c, 0x1e, 0x33};
343
344 static Pixmap
CreateInsertCursor(Screen * s)345 CreateInsertCursor(Screen *s)
346 {
347 return (XCreateBitmapFromData (DisplayOfScreen(s), RootWindowOfScreen(s),
348 insertCursor_bits, insertCursor_width, insertCursor_height));
349 }
350
351 /* Function Name: GetCursorBounds
352 * Description: Returns the size and location of the cursor.
353 * Arguments: w - the text object.
354 * RETURNED rect - an X rectangle to return the cursor bounds in.
355 * Returns: none.
356 */
357
358 static void
GetCursorBounds(Widget w,XRectangle * rect)359 GetCursorBounds(Widget w, XRectangle * rect)
360 {
361 MultiSinkObject sink = (MultiSinkObject) w;
362
363 rect->width = (unsigned short) insertCursor_width;
364 rect->height = (unsigned short) insertCursor_height;
365 rect->x = sink->multi_sink.cursor_x - (short) (rect->width / 2);
366 rect->y = sink->multi_sink.cursor_y - (short) rect->height;
367 }
368
369 /*
370 * The following procedure manages the "insert" cursor.
371 */
372
373 static void
InsertCursor(Widget w,Position x,Position y,XawTextInsertState state)374 InsertCursor (Widget w, Position x, Position y, XawTextInsertState state)
375 {
376 MultiSinkObject sink = (MultiSinkObject) w;
377 Widget text_widget = XtParent(w);
378 XRectangle rect;
379
380 sink->multi_sink.cursor_x = x;
381 sink->multi_sink.cursor_y = y;
382
383 GetCursorBounds(w, &rect);
384 if (state != sink->multi_sink.laststate && XtIsRealized(text_widget))
385 XCopyPlane(XtDisplay(text_widget),
386 sink->multi_sink.insertCursorOn,
387 XtWindow(text_widget), sink->multi_sink.xorgc,
388 0, 0, (unsigned int) rect.width, (unsigned int) rect.height,
389 (int) rect.x, (int) rect.y, 1);
390 sink->multi_sink.laststate = state;
391 }
392
393 /*
394 * Given two positions, find the distance between them.
395 */
396
397 static void
FindDistance(Widget w,XawTextPosition fromPos,int fromx,XawTextPosition toPos,int * resWidth,XawTextPosition * resPos,int * resHeight)398 FindDistance (Widget w, XawTextPosition fromPos, int fromx, XawTextPosition toPos,
399 int *resWidth, XawTextPosition *resPos, int *resHeight)
400 {
401 MultiSinkObject sink = (MultiSinkObject) w;
402 Widget source = XawTextGetSource(XtParent(w));
403
404 XawTextPosition index, lastPos;
405 wchar_t c;
406 XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset);
407 XawTextBlock blk;
408
409 /* we may not need this */
410 lastPos = GETLASTPOS;
411 XawTextSourceRead(source, fromPos, &blk, (int) toPos - fromPos);
412 *resWidth = 0;
413 for (index = fromPos; index != toPos && index < lastPos; index++) {
414 if (index - blk.firstPos >= blk.length)
415 XawTextSourceRead(source, index, &blk, (int) toPos - fromPos);
416 c = ((wchar_t *)blk.ptr)[index - blk.firstPos];
417 *resWidth += CharWidth(w, fromx + *resWidth, c);
418 if (c == _Xaw_atowc(XawLF)) {
419 index++;
420 break;
421 }
422 }
423 *resPos = index;
424 *resHeight = ext->max_logical_extent.height;
425 }
426
427
428 static void
FindPosition(Widget w,XawTextPosition fromPos,int fromx,int width,Boolean stopAtWordBreak,XawTextPosition * resPos,int * resWidth,int * resHeight)429 FindPosition(Widget w, XawTextPosition fromPos, int fromx, int width,
430 Boolean stopAtWordBreak, XawTextPosition *resPos, int *resWidth,
431 int *resHeight)
432 {
433 MultiSinkObject sink = (MultiSinkObject) w;
434 Widget source = XawTextGetSource(XtParent(w));
435
436 XawTextPosition lastPos, index, whiteSpacePosition = 0;
437 int lastWidth = 0, whiteSpaceWidth = 0;
438 Boolean whiteSpaceSeen;
439 wchar_t c;
440 XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset);
441 XawTextBlock blk;
442
443 lastPos = GETLASTPOS;
444
445 XawTextSourceRead(source, fromPos, &blk, BUFSIZ);
446 *resWidth = 0;
447 whiteSpaceSeen = FALSE;
448 c = 0;
449 for (index = fromPos; *resWidth <= width && index < lastPos; index++) {
450 lastWidth = *resWidth;
451 if (index - blk.firstPos >= blk.length)
452 XawTextSourceRead(source, index, &blk, BUFSIZ);
453 c = ((wchar_t *)blk.ptr)[index - blk.firstPos];
454 *resWidth += CharWidth(w, fromx + *resWidth, c);
455
456 if ((c == _Xaw_atowc(XawSP) || c == _Xaw_atowc(XawTAB)) &&
457 *resWidth <= width) {
458 whiteSpaceSeen = TRUE;
459 whiteSpacePosition = index;
460 whiteSpaceWidth = *resWidth;
461 }
462 if (c == _Xaw_atowc(XawLF)) {
463 index++;
464 break;
465 }
466 }
467 if (*resWidth > width && index > fromPos) {
468 *resWidth = lastWidth;
469 index--;
470 if (stopAtWordBreak && whiteSpaceSeen) {
471 index = whiteSpacePosition + 1;
472 *resWidth = whiteSpaceWidth;
473 }
474 }
475 if (index == lastPos && c != _Xaw_atowc(XawLF)) index = lastPos + 1;
476 *resPos = index;
477 *resHeight = ext->max_logical_extent.height;
478 }
479
480 static void
Resolve(Widget w,XawTextPosition pos,int fromx,int width,XawTextPosition * resPos)481 Resolve (Widget w, XawTextPosition pos, int fromx, int width,
482 XawTextPosition *resPos)
483 {
484 int resWidth, resHeight;
485 Widget source = XawTextGetSource(XtParent(w));
486
487 FindPosition(w, pos, fromx, width, FALSE, resPos, &resWidth, &resHeight);
488 if (*resPos > GETLASTPOS)
489 *resPos = GETLASTPOS;
490 }
491
492 static void
GetGC(MultiSinkObject sink)493 GetGC(MultiSinkObject sink)
494 {
495 XtGCMask valuemask = (GCGraphicsExposures | GCForeground | GCBackground );
496 XGCValues values;
497
498 values.graphics_exposures = (Bool) FALSE;
499
500 values.foreground = sink->text_sink.foreground;
501 values.background = sink->text_sink.background;
502
503 sink->multi_sink.normgc = XtAllocateGC( (Widget)sink, 0, valuemask, &values, GCFont, 0 );
504
505 values.foreground = sink->text_sink.background;
506 values.background = sink->text_sink.foreground;
507 sink->multi_sink.invgc = XtAllocateGC( (Widget)sink, 0, valuemask, &values, GCFont, 0 );
508
509 values.function = GXxor;
510 values.background = (unsigned long) 0L; /* (pix ^ 0) = pix */
511 values.foreground = (sink->text_sink.background ^
512 sink->text_sink.foreground);
513 valuemask = GCGraphicsExposures | GCFunction | GCForeground | GCBackground;
514
515 /* if this GC is not used for fontset rendering then AllocateGC aint needed. Dont hurt tho.*/
516 sink->multi_sink.xorgc = XtAllocateGC( (Widget)sink, 0, valuemask, &values, GCFont, 0 );
517 }
518
519
520 /***** Public routines *****/
521
522 /* Function Name: Initialize
523 * Description: Initializes the TextSink Object.
524 * Arguments: request, new - the requested and new values for the object
525 * instance.
526 * Returns: none.
527 *
528 */
529
530 /* ARGSUSED */
531 static void
Initialize(Widget request,Widget new,ArgList args,Cardinal * num_args)532 Initialize(Widget request, Widget new, ArgList args, Cardinal *num_args)
533 {
534 MultiSinkObject sink = (MultiSinkObject) new;
535
536 GetGC(sink);
537
538 sink->multi_sink.insertCursorOn= CreateInsertCursor(XtScreenOfObject(new));
539 sink->multi_sink.laststate = XawisOff;
540 sink->multi_sink.cursor_x = sink->multi_sink.cursor_y = 0;
541 }
542
543 /* Function Name: Destroy
544 * Description: This function cleans up when the object is
545 * destroyed.
546 * Arguments: w - the MultiSink Object.
547 * Returns: none.
548 */
549
550 static void
Destroy(Widget w)551 Destroy(Widget w)
552 {
553 MultiSinkObject sink = (MultiSinkObject) w;
554
555 XtReleaseGC(w, sink->multi_sink.normgc);
556 XtReleaseGC(w, sink->multi_sink.invgc);
557 XtReleaseGC(w, sink->multi_sink.xorgc);
558
559 XFreePixmap(XtDisplayOfObject(w), sink->multi_sink.insertCursorOn);
560 }
561
562 /* Function Name: SetValues
563 * Description: Sets the values for the MultiSink
564 * Arguments: current - current state of the object.
565 * request - what was requested.
566 * new - what the object will become.
567 * Returns: True if redisplay is needed.
568 */
569
570 /* ARGSUSED */
571 static Boolean
SetValues(Widget current,Widget request,Widget new,ArgList args,Cardinal * num_args)572 SetValues(Widget current, Widget request, Widget new, ArgList args, Cardinal *num_args)
573 {
574 MultiSinkObject w = (MultiSinkObject) new;
575 MultiSinkObject old_w = (MultiSinkObject) current;
576
577 /* Font set is not in the GC! Do not make a new GC when font set changes! */
578
579 if ( w->multi_sink.fontset != old_w->multi_sink.fontset ) {
580 ((TextWidget)XtParent(new))->text.redisplay_needed = True;
581 #ifndef NO_TAB_FIX
582 SetTabs((Widget) w, w->text_sink.tab_count, w->text_sink.char_tabs );
583 #endif
584 }
585
586 if ( w->text_sink.background != old_w->text_sink.background ||
587 w->text_sink.foreground != old_w->text_sink.foreground ) {
588
589 XtReleaseGC((Widget)w, w->multi_sink.normgc);
590 XtReleaseGC((Widget)w, w->multi_sink.invgc);
591 XtReleaseGC((Widget)w, w->multi_sink.xorgc);
592 GetGC(w);
593 ((TextWidget)XtParent(new))->text.redisplay_needed = True;
594 } else {
595 if ( (w->multi_sink.echo != old_w->multi_sink.echo) ||
596 (w->multi_sink.display_nonprinting !=
597 old_w->multi_sink.display_nonprinting) )
598 ((TextWidget)XtParent(new))->text.redisplay_needed = True;
599 }
600
601 return False;
602 }
603
604 /* Function Name: MaxLines
605 * Description: Finds the Maximum number of lines that will fit in
606 * a given height.
607 * Arguments: w - the MultiSink Object.
608 * height - height to fit lines into.
609 * Returns: the number of lines that will fit.
610 */
611
612 /* ARGSUSED */
613 static int
MaxLines(Widget w,Dimension height)614 MaxLines(Widget w, Dimension height)
615 {
616 MultiSinkObject sink = (MultiSinkObject) w;
617 int font_height;
618 XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset);
619
620 font_height = ext->max_logical_extent.height;
621 return( ((int) height) / font_height );
622 }
623
624 /* Function Name: MaxHeight
625 * Description: Finds the Minium height that will contain a given number
626 * lines.
627 * Arguments: w - the MultiSink Object.
628 * lines - the number of lines.
629 * Returns: the height.
630 */
631
632 /* ARGSUSED */
633 static int
MaxHeight(Widget w,int lines)634 MaxHeight(
635 Widget w,
636 int lines )
637 {
638 MultiSinkObject sink = (MultiSinkObject) w;
639 XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset);
640
641 return(lines * ext->max_logical_extent.height);
642 }
643
644 /* Function Name: SetTabs
645 * Description: Sets the Tab stops.
646 * Arguments: w - the MultiSink Object.
647 * tab_count - the number of tabs in the list.
648 * tabs - the text positions of the tabs.
649 * Returns: none
650 */
651
652 static void
SetTabs(Widget w,int tab_count,short * tabs)653 SetTabs(
654 Widget w,
655 int tab_count,
656 short* tabs )
657 {
658 MultiSinkObject sink = (MultiSinkObject) w;
659 int i;
660 Atom XA_FIGURE_WIDTH;
661 unsigned long figure_width = 0;
662 XFontStruct *font;
663
664 /*
665 * Bug:
666 * Suppose the first font of fontset stores the unit of column.
667 *
668 * By Li Yuhong, Mar. 14, 1991
669 */
670 { XFontStruct **f_list;
671 char **f_name;
672
673 (void) XFontsOfFontSet(sink->multi_sink.fontset, &f_list, &f_name);
674 font = f_list[0];
675 }
676
677 /*
678 * Find the figure width of the current font.
679 */
680
681 XA_FIGURE_WIDTH = XInternAtom(XtDisplayOfObject(w), "FIGURE_WIDTH", FALSE);
682 if ( (XA_FIGURE_WIDTH != None) &&
683 ( (!XGetFontProperty(font, XA_FIGURE_WIDTH, &figure_width)) ||
684 (figure_width == 0)) ) {
685 if (font->per_char && font->min_char_or_byte2 <= '$' &&
686 font->max_char_or_byte2 >= '$')
687 figure_width = font->per_char['$' - font->min_char_or_byte2].width;
688 else
689 figure_width = font->max_bounds.width;
690 }
691
692 if (tab_count > sink->text_sink.tab_count) {
693 sink->text_sink.tabs = (Position *)
694 XtRealloc((char *) sink->text_sink.tabs,
695 (Cardinal) (tab_count * sizeof(Position)));
696 sink->text_sink.char_tabs = (short *)
697 XtRealloc((char *) sink->text_sink.char_tabs,
698 (Cardinal) (tab_count * sizeof(short)));
699 }
700
701 for ( i = 0 ; i < tab_count ; i++ ) {
702 sink->text_sink.tabs[i] = tabs[i] * figure_width;
703 sink->text_sink.char_tabs[i] = tabs[i];
704 }
705
706 sink->text_sink.tab_count = tab_count;
707
708 #ifndef NO_TAB_FIX
709 ((TextWidget)XtParent(w))->text.redisplay_needed = True;
710 #endif
711 }
712
713 void
_XawMultiSinkPosToXY(Widget w,XawTextPosition pos,Position * x,Position * y)714 _XawMultiSinkPosToXY(
715 Widget w,
716 XawTextPosition pos,
717 Position *x,
718 Position *y )
719 {
720 MultiSinkObject sink = (MultiSinkObject) ((TextWidget)w)->text.sink;
721 XFontSetExtents *ext = XExtentsOfFontSet( sink->multi_sink.fontset );
722
723 _XawTextPosToXY( w, pos, x, y );
724 *y += abs( ext->max_logical_extent.y );
725 }
726