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