1 /*************************************<+>*************************************
2  *****************************************************************************
3  **
4  **   File:        Display.c
5  **
6  **   Project:     X Widgets
7  **
8  **   Description: Code for TextEdit widget ascii sink
9  **
10  *****************************************************************************
11  **
12  **   Copyright (c) 1988 by Hewlett-Packard Company
13  **   Copyright (c) 1987, 1988 by Digital Equipment Corporation, Maynard,
14  **             Massachusetts, and the Massachusetts Institute of Technology,
15  **             Cambridge, Massachusetts
16  **
17  **   Permission to use, copy, modify, and distribute this software
18  **   and its documentation for any purpose and without fee is hereby
19  **   granted, provided that the above copyright notice appear in all
20  **   copies and that both that copyright notice and this permission
21  **   notice appear in supporting documentation, and that the names of
22  **   Hewlett-Packard, Digital or  M.I.T.  not be used in advertising or
23  **   publicity pertaining to distribution of the software without
24  **   written prior permission.
25  **
26  **   DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
27  **   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
28  **   DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
29  **   ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
30  **   WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
31  **   ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
32  **   SOFTWARE.
33  **
34  *****************************************************************************
35  *************************************<+>*************************************/
36 
37 
38 #include <X11/Xlib.h>
39 #include <X11/Xutil.h>
40 #include <X11/Xatom.h>
41 #include <X11/Intrinsic.h>
42 #include <X11/IntrinsicP.h>
43 #include <X11/StringDefs.h>
44 #include <Xw/Xw.h>
45 #include <Xw/XwP.h>
46 
47 #include <Xw/TextEditP.h>
48 
49 #ifdef DEBUG
50 #include <stdio.h>
51 #endif
52 
53 
54 #define GETLASTPOS (*(source->scan))(source, 0, XwstLast, XwsdRight, 1, TRUE)
55 /* Private Ascii TextSink Definitions */
56 
57 static unsigned bufferSize = 200;
58 
59 typedef struct _AsciiSinkData {
60     Pixel foreground;
61     GC normgc, invgc, xorgc;
62     XFontStruct *font;
63     int tabwidth;
64     Pixmap insertCursorOn;
65     XwInsertState laststate;
66 } AsciiSinkData, *AsciiSinkPtr;
67 
68 static unsigned char *buf;
69 
70 /* XXX foreground default should be XtDefaultFGPixel. How do i do that?? */
71 
72 static XtResource SinkResources[] = {
73     {XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
74         XtOffset(AsciiSinkPtr, font), XtRString, "Fixed"},
75     {XtNforeground, XtCForeground, XtRPixel, sizeof (int),
76         XtOffset(AsciiSinkPtr, foreground), XtRString, "XtDefaultForeground"},
77 };
78 
79 /* Utilities */
80 
81 /*--------------------------------------------------------------------------+*/
CharWidth(data,x,margin,c)82 static int CharWidth (data, x, margin, c)
83 /*--------------------------------------------------------------------------+*/
84   AsciiSinkData *data;
85   int x;
86   int margin ;
87   unsigned char c;
88 {
89     int     width, nonPrinting;
90     XFontStruct *font = data->font;
91 
92     if (c == '\t')
93         /* This is totally bogus!! need to know tab settings etc.. */
94 	return data->tabwidth - ((x-margin) % data->tabwidth);
95     if (c == LF)
96 	c = SP;
97     nonPrinting = (c < SP);
98     if (nonPrinting) c += '@';
99 
100     if (font->per_char &&
101 	    (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2))
102 	width = font->per_char[c - font->min_char_or_byte2].width;
103     else
104 	width = font->min_bounds.width;
105 
106     if (nonPrinting)
107 	width += CharWidth(data, x, margin, '^');
108 
109     return width;
110 }
111 
112 /* Sink Object Functions */
113 
114 #define LBEARING(x) \
115     ((font->per_char != NULL && \
116       ((x) >= font->min_char_or_byte2 && (x) <= font->max_char_or_byte2)) \
117 	? font->per_char[(x) - font->min_char_or_byte2].lbearing \
118 	: font->min_bounds.lbearing)
119 
120 /*--------------------------------------------------------------------------+*/
AsciiDisplayText(w,x,y,pos1,pos2,highlight)121 static int AsciiDisplayText (w, x, y, pos1, pos2, highlight)
122 /*--------------------------------------------------------------------------+*/
123   Widget w;
124   Position x, y;
125   int highlight;
126   XwTextPosition pos1, pos2;
127 {
128     XwTextSink *sink = ((XwTextEditWidget)w)->text.sink;
129     XwTextSource *source = ((XwTextEditWidget)w)->text.source;
130     AsciiSinkData *data = (AsciiSinkData *) sink->data ;
131     int margin = ((XwTextEditWidget)w)->text.leftmargin ;
132 
133     XFontStruct *font = data->font;
134     int     j, k;
135     Dimension width;
136     XwTextBlock blk;
137     GC gc = highlight ? data->invgc : data->normgc;
138     GC invgc = highlight ? data->normgc : data->invgc;
139 
140     y += font->ascent;
141     j = 0;
142     while (pos1 < pos2) {
143 	pos1 = (*(source->read))(source, pos1, &blk, pos2 - pos1);
144 	for (k = 0; k < blk.length; k++) {
145 	    if (j >= bufferSize - 5) {
146 		bufferSize *= 2;
147 		buf = (unsigned char *) XtRealloc(buf, bufferSize);
148 	    }
149 	    buf[j] = blk.ptr[k];
150 	    if (buf[j] == LF)
151 		buf[j] = ' ';
152 	    else if (buf[j] == '\t') {
153 	        XDrawImageString(XtDisplay(w), XtWindow(w),
154 			gc, x - LBEARING(*buf), y, buf, j);
155 		buf[j] = 0;
156 		x += XTextWidth(data->font, buf, j);
157 		width = CharWidth(data, x, margin, '\t');
158 		XFillRectangle(XtDisplay(w), XtWindow(w), invgc, x,
159 			       y - font->ascent, width,
160 			       (Dimension) (data->font->ascent +
161 					    data->font->descent));
162 		x += width;
163 		j = -1;
164 	    }
165 	    else
166 		if (buf[j] < ' ') {
167 		    buf[j + 1] = buf[j] + '@';
168 		    buf[j] = '^';
169 		    j++;
170 		}
171 	    j++;
172 	}
173     }
174     XDrawImageString(XtDisplay(w), XtWindow(w), gc, x - LBEARING(*buf), y,
175 		     buf, j);
176 }
177 
178 
179 #   define insertCursor_width 6
180 #   define insertCursor_height 3
181 static char insertCursor_bits[] = {0x0c, 0x1e, 0x33};
182 
183 /*--------------------------------------------------------------------------+*/
CreateInsertCursor(s)184 static Pixmap CreateInsertCursor(s)
185 /*--------------------------------------------------------------------------+*/
186 Screen *s;
187 {
188 
189     return (XCreateBitmapFromData (DisplayOfScreen(s), RootWindowOfScreen(s),
190         insertCursor_bits, insertCursor_width, insertCursor_height));
191 }
192 
193 /*
194  * The following procedure manages the "insert" cursor.
195  */
196 
197 /*--------------------------------------------------------------------------+*/
AsciiInsertCursor(w,x,y,state)198 static AsciiInsertCursor (w, x, y, state)
199 /*--------------------------------------------------------------------------+*/
200   Widget w;
201   Position x, y;
202   XwInsertState state;
203 {
204     XwTextSink *sink = ((XwTextEditWidget)w)->text.sink;
205     AsciiSinkData *data = (AsciiSinkData *) sink->data;
206 
207 /*
208     XCopyArea(sink->dpy,
209 	      (state == XwisOn) ? data->insertCursorOn : data->insertCursorOff, w,
210 	      data->normgc, 0, 0, insertCursor_width, insertCursor_height,
211 	      x - (insertCursor_width >> 1), y - (insertCursor_height));
212 
213     if (state != data->laststate && XtIsRealized(w))
214 	XCopyPlane(XtDisplay(w),
215 		  data->insertCursorOn, XtWindow(w),
216 		  data->xorgc, 0, 0, insertCursor_width, insertCursor_height,
217 		  x - (insertCursor_width >> 1), y - (insertCursor_height), 1);
218 */
219 /* This change goes with the cursor hack for the broken server */
220     XCopyArea (XtDisplay(w), data->insertCursorOn, XtWindow (w),
221 	       data->xorgc, 0, 0, insertCursor_width, insertCursor_height,
222 	       x - (insertCursor_width >> 1), y - (insertCursor_height));
223 
224     data->laststate = state;
225 }
226 
227 /*
228  * Clear the passed region to the background color.
229  */
230 
231 /*--------------------------------------------------------------------------+*/
AsciiClearToBackground(w,x,y,width,height)232 static AsciiClearToBackground (w, x, y, width, height)
233 /*--------------------------------------------------------------------------+*/
234   Widget w;
235   Position x, y;
236   Dimension width, height;
237 {
238     XwTextSink *sink = ((XwTextEditWidget)w)->text.sink;
239     AsciiSinkData *data = (AsciiSinkData *) sink->data;
240     XFillRectangle(XtDisplay(w), XtWindow(w), data->invgc, x, y, width, height);
241 }
242 
243 /*
244  * Given two positions, find the distance between them.
245  */
246 
247 /*--------------------------------------------------------------------------+*/
AsciiFindDistance(w,fromPos,fromx,toPos,resWidth,resPos,resHeight)248 static AsciiFindDistance (w, fromPos, fromx, toPos,
249 			  resWidth, resPos, resHeight)
250 /*--------------------------------------------------------------------------+*/
251   Widget w;
252   XwTextPosition fromPos;	/* First position. */
253   int fromx;			/* Horizontal location of first position. */
254   XwTextPosition toPos;		/* Second position. */
255   int *resWidth;		/* Distance between fromPos and resPos. */
256   int *resPos;			/* Actual second position used. */
257   int *resHeight;		/* Height required. */
258 {
259     XwTextSink *sink = ((XwTextEditWidget)w)->text.sink;
260     XwTextSource *source = ((XwTextEditWidget)w)->text.source;
261     int margin = ((XwTextEditWidget)w)->text.leftmargin ;
262 
263     AsciiSinkData *data;
264     register    XwTextPosition index, lastPos;
265     register unsigned char   c;
266     XwTextBlock blk;
267 
268     data = (AsciiSinkData *) sink->data;
269     /* we may not need this */
270     lastPos = GETLASTPOS;
271     (*(source->read))(source, fromPos, &blk, toPos - fromPos);
272     *resWidth = 0;
273     for (index = fromPos; index != toPos && index < lastPos; index++) {
274 	if (index - blk.firstPos >= blk.length)
275 	    (*(source->read))(source, index, &blk, toPos - fromPos);
276 	c = blk.ptr[index - blk.firstPos];
277 	if (c == LF) {
278 	    *resWidth += CharWidth(data, fromx + *resWidth, margin, SP);
279 	    index++;
280 	    break;
281 	}
282 	*resWidth += CharWidth(data, fromx + *resWidth, margin, c);
283     }
284     *resPos = index;
285     *resHeight = data->font->ascent + data->font->descent;
286 }
287 
288 
289 /*--------------------------------------------------------------------------+*/
AsciiTextFit(w,fromPos,fromx,width,wrap,wrapWhiteSpace,fitPos,drawPos,nextPos,resWidth,resHeight)290 static TextFit AsciiTextFit (w, fromPos, fromx, width, wrap, wrapWhiteSpace,
291 			     fitPos, drawPos, nextPos, resWidth, resHeight)
292 /*--------------------------------------------------------------------------+*/
293   Widget w;
294   XwTextPosition fromPos; 	/* Starting position. */
295   int fromx;			/* Horizontal location of starting position. */
296   int width;			/* Desired width. */
297   int wrap;			/* Whether line should wrap at all */
298   int wrapWhiteSpace;		/* Whether line should wrap at white space */
299 
300   XwTextPosition *fitPos ;	/* pos of last char which fits in specified
301 				   width */
302   XwTextPosition *drawPos ;	/* pos of last char to draw in specified
303 				   width based on wrap model */
304   XwTextPosition *nextPos ;	/* pos of next char to draw outside specified
305 				   width based on wrap model */
306   int *resWidth;		/* Actual width used. */
307   int *resHeight;		/* Height required. */
308 {
309     XwTextSink *sink = ((XwTextEditWidget)w)->text.sink;
310     XwTextSource *source = ((XwTextEditWidget)w)->text.source;
311     int margin = ((XwTextEditWidget)w)->text.leftmargin ;
312     AsciiSinkData *data;
313     XwTextPosition lastPos, pos, whiteSpacePosition;
314     XwTextPosition fitL, drawL ;
315     		/* local equivalents of fitPos, drawPos, nextPos */
316     int     lastWidth, whiteSpaceWidth, whiteSpaceSeen ;
317     int useAll ;
318     TextFit fit ;
319     unsigned char    c;
320     XwTextBlock blk;
321 
322     data = (AsciiSinkData *) sink->data;
323     lastPos = GETLASTPOS;
324 
325     *resWidth = 0;
326     *fitPos = fromPos ;
327     *drawPos = -1 ;
328     c = 0;
329     useAll = whiteSpaceSeen = FALSE ;
330 
331     pos = fromPos ;
332     fitL = pos - 1 ;
333     (*(source->read))(source, fromPos, &blk, bufferSize);
334 
335     while (*resWidth <= width)
336       {	lastWidth = *resWidth;
337 	fitL = pos - 1 ;
338 	if (pos >= lastPos)
339 	  { pos = lastPos ;
340 	    fit = tfEndText ;
341 	    useAll = TRUE ;
342 	    break ;
343 	  } ;
344 	if (pos - blk.firstPos >= blk.length)
345 	  (*(source->read))(source, pos, &blk, bufferSize);
346 	c = blk.ptr[pos - blk.firstPos];
347 
348 	if (isNewline(c))
349 	  { fit = tfNewline ;
350 	    useAll = TRUE ;
351 	    break ;
352 	  }
353 
354 	if (wrapWhiteSpace && isWhiteSpace(c))
355 	  { whiteSpaceSeen = TRUE ;
356 	    drawL = pos - 1 ;
357 	    whiteSpaceWidth = *resWidth;
358 	  } ;
359 
360 	*resWidth += CharWidth(data, fromx + *resWidth, margin, c);
361 	pos++ ;
362     } /* end while */
363 
364     *fitPos = fitL ;
365     *drawPos = fitL ;
366     if (useAll)
367       {
368 	*nextPos = pos + 1 ;
369 	*resWidth = lastWidth ;
370       }
371     else if (wrapWhiteSpace && whiteSpaceSeen)
372       { *drawPos = drawL ;
373 	*nextPos = drawL + 2 ;
374 	*resWidth = whiteSpaceWidth ;
375 	fit = tfWrapWhiteSpace ;
376       }
377     else if (wrap)
378       {
379 	*nextPos = fitL + 1 ;
380 	*resWidth = lastWidth ;
381 	fit = tfWrapAny ;
382       }
383     else
384       {
385 	/* scan source for newline or end */
386 	*nextPos =
387 	  (*(source->scan)) (source, pos, XwstEOL, XwsdRight, 1, TRUE) + 1 ;
388 	*resWidth = lastWidth ;
389 	fit = tfNoFit ;
390       }
391     *resHeight = data->font->ascent + data->font->descent;
392     return (fit) ;
393 }
394 
395 /*--------------------------------------------------------------------------+*/
AsciiFindPosition(w,fromPos,fromx,width,stopAtWordBreak,resPos,resWidth,resHeight)396 static AsciiFindPosition(w, fromPos, fromx, width, stopAtWordBreak,
397 			 resPos, resWidth, resHeight)
398 /*--------------------------------------------------------------------------+*/
399   Widget w;
400   XwTextPosition fromPos; 	/* Starting position. */
401   int fromx;			/* Horizontal location of starting position. */
402   int width;			/* Desired width. */
403   int stopAtWordBreak;		/* Whether the resulting position should be at
404 				   a word break. */
405   XwTextPosition *resPos;	/* Resulting position. */
406   int *resWidth;		/* Actual width used. */
407   int *resHeight;		/* Height required. */
408 {
409     XwTextSink *sink = ((XwTextEditWidget)w)->text.sink;
410     XwTextSource *source = ((XwTextEditWidget)w)->text.source;
411     int margin = ((XwTextEditWidget)w)->text.leftmargin ;
412     AsciiSinkData *data;
413     XwTextPosition lastPos, index, whiteSpacePosition;
414     int     lastWidth, whiteSpaceWidth;
415     Boolean whiteSpaceSeen;
416     unsigned char c;
417     XwTextBlock blk;
418     data = (AsciiSinkData *) sink->data;
419     lastPos = GETLASTPOS;
420 
421     (*(source->read))(source, fromPos, &blk, bufferSize);
422     *resWidth = 0;
423     whiteSpaceSeen = FALSE;
424     c = 0;
425     for (index = fromPos; *resWidth <= width && index < lastPos; index++) {
426 	lastWidth = *resWidth;
427 	if (index - blk.firstPos >= blk.length)
428 	    (*(source->read))(source, index, &blk, bufferSize);
429 	c = blk.ptr[index - blk.firstPos];
430 	if (c == LF) {
431 	    *resWidth += CharWidth(data, fromx + *resWidth, margin, SP);
432 	    index++;
433 	    break;
434 	}
435 	*resWidth += CharWidth(data, fromx + *resWidth, margin, c);
436 	if ((c == SP || c == TAB) && *resWidth <= width) {
437 	    whiteSpaceSeen = TRUE;
438 	    whiteSpacePosition = index;
439 	    whiteSpaceWidth = *resWidth;
440 	}
441     }
442     if (*resWidth > width && index > fromPos) {
443 	*resWidth = lastWidth;
444 	index--;
445 	if (stopAtWordBreak && whiteSpaceSeen) {
446 	    index = whiteSpacePosition + 1;
447 	    *resWidth = whiteSpaceWidth;
448 	}
449     }
450     if (index == lastPos && c != LF) index = lastPos + 1;
451     *resPos = index;
452     *resHeight = data->font->ascent + data->font->descent;
453 }
454 
455 
456 /*--------------------------------------------------------------------------+*/
AsciiResolveToPosition(w,pos,fromx,width,leftPos,rightPos)457 static int AsciiResolveToPosition (w, pos, fromx, width,
458 				   leftPos, rightPos)
459 /*--------------------------------------------------------------------------+*/
460   Widget w;
461   XwTextPosition pos;
462   int fromx,width;
463   XwTextPosition *leftPos, *rightPos;
464 {
465     int     resWidth, resHeight;
466     XwTextSink *sink = ((XwTextEditWidget)w)->text.sink;
467     XwTextSource *source = ((XwTextEditWidget)w)->text.source;
468 
469     AsciiFindPosition(w, pos, fromx, width, FALSE,
470 	    leftPos, &resWidth, &resHeight);
471     if (*leftPos > GETLASTPOS)
472 	*leftPos = GETLASTPOS;
473     *rightPos = *leftPos;
474 }
475 
476 
477 /*--------------------------------------------------------------------------+*/
AsciiMaxLinesForHeight(w)478 static int AsciiMaxLinesForHeight (w)
479 /*--------------------------------------------------------------------------+*/
480   Widget w;
481 {
482     AsciiSinkData *data;
483     XwTextSink *sink = ((XwTextEditWidget)w)->text.sink;
484 
485     data = (AsciiSinkData *) sink->data;
486     return (int) ((w->core.height
487 		   - ((XwTextEditWidget) w)->text.topmargin
488 		   - ((XwTextEditWidget) w)->text.bottommargin
489 		   )
490 		  / (data->font->ascent + data->font->descent)
491 		  );
492 }
493 
494 
495 /*--------------------------------------------------------------------------+*/
AsciiMaxHeightForLines(w,lines)496 static int AsciiMaxHeightForLines (w, lines)
497 /*--------------------------------------------------------------------------+*/
498   Widget w;
499   int lines;
500 {
501     AsciiSinkData *data;
502     XwTextSink *sink = ((XwTextEditWidget)w)->text.sink;
503 
504     data = (AsciiSinkData *) sink->data;
505     return(lines * (data->font->ascent + data->font->descent));
506 }
507 
508 
509 /***** Public routines *****/
510 
511 static Boolean initialized = FALSE;
512 static XContext asciiSinkContext;
513 
514 /*--------------------------------------------------------------------------+*/
AsciiSinkInitialize()515 void AsciiSinkInitialize()
516 /*--------------------------------------------------------------------------+*/
517 {
518     if (initialized)
519     	return;
520     initialized = TRUE;
521 
522     asciiSinkContext = XUniqueContext();
523 
524     buf = (unsigned char *) XtMalloc(bufferSize);
525 }
526 
527 /*--------------------------------------------------------------------------+*/
XwAsciiSinkCheckData(self)528 static Boolean XwAsciiSinkCheckData(self)
529 /*--------------------------------------------------------------------------+*/
530   XwTextSink *self ;
531 {
532   XwTextEditWidget tew = self->parent ;
533 
534   /* make sure margins are big enough to keep traversal highlight
535      from obscuring text or cursor.
536      */
537   { int minBorder ;
538     minBorder = (tew->primitive.traversal_type == XwHIGHLIGHT_OFF)
539                   ? RequiredCursorMargin
540 		  : RequiredCursorMargin + tew->primitive.highlight_thickness ;
541 
542     if (tew->text.topmargin < minBorder)
543       tew->text.topmargin = minBorder ;
544     if (tew->text.bottommargin < minBorder)
545       tew->text.bottommargin = minBorder ;
546     if (tew->text.rightmargin < minBorder)
547       tew->text.rightmargin = minBorder ;
548     if (tew->text.leftmargin < minBorder)
549       tew->text.leftmargin = minBorder ;
550   }
551 
552   if ((*(self->maxLines))(tew) < 1)
553     XtWarning("TextEdit window too small to display a single line of text.");
554 
555 }
556 
557 /*--------------------------------------------------------------------------+*/
XwAsciiSinkDestroy(sink)558 void XwAsciiSinkDestroy (sink)
559 /*--------------------------------------------------------------------------+*/
560     XwTextSink *sink;
561 {
562     AsciiSinkData *data;
563     data = (AsciiSinkData *) sink->data;
564     XtFree((char *) data);
565     XtFree((char *) sink);
566 }
567 
568 /*--------------------------------------------------------------------------+*/
XwAsciiSinkCreate(w,args,num_args)569 XwTextSink *XwAsciiSinkCreate (w, args, num_args)
570 /*--------------------------------------------------------------------------+*/
571     Widget w;
572     ArgList 	args;
573     Cardinal 	num_args;
574 {
575     XwTextSink *sink;
576     AsciiSinkData *data;
577     unsigned long valuemask = (GCFont | GCGraphicsExposures |
578 			       GCForeground | GCBackground | GCFunction);
579     XGCValues values;
580     unsigned long wid;
581     XFontStruct *font;
582 
583     if (!initialized)
584     	AsciiSinkInitialize();
585 
586     sink                    = XtNew(XwTextSink);
587     sink->parent            = (XwTextEditWidget) w ;
588     sink->parent->text.sink = sink ;		/* disgusting */
589     sink->display           = AsciiDisplayText;
590     sink->insertCursor      = AsciiInsertCursor;
591     sink->clearToBackground = AsciiClearToBackground;
592     sink->findPosition      = AsciiFindPosition;
593     sink->textFitFn         = AsciiTextFit;
594     sink->findDistance      = AsciiFindDistance;
595     sink->resolve           = AsciiResolveToPosition;
596     sink->maxLines          = AsciiMaxLinesForHeight;
597     sink->maxHeight         = AsciiMaxHeightForLines;
598     sink->resources         = SinkResources;
599     sink->resource_num      = XtNumber(SinkResources);
600     sink->check_data        = XwAsciiSinkCheckData;
601     sink->destroy           = XwAsciiSinkDestroy;
602     sink->LineLastWidth	    = 0 ;
603     sink->LineLastPosition  = 0 ;
604     data                    = XtNew(AsciiSinkData);
605     sink->data              = (int *)data;
606 
607     XtGetSubresources (w, (caddr_t)data, "display", "Display",
608 		       SinkResources, XtNumber(SinkResources),
609 		       args, num_args);
610 
611 /* XXX do i have to XLoadQueryFont or does the resource guy do it for me */
612 
613     font = data->font;
614     values.function = GXcopy;
615     values.font = font->fid;
616     values.graphics_exposures = (Bool) FALSE;
617     values.foreground = data->foreground;
618     values.background = w->core.background_pixel;
619     data->normgc = XtGetGC(w, valuemask, &values);
620     values.foreground = w->core.background_pixel;
621     values.background = data->foreground;
622     data->invgc = XtGetGC(w, valuemask, &values);
623     values.function = GXxor;
624     values.foreground = data->foreground ^ w->core.background_pixel;
625     values.background = 0;
626     data->xorgc = XtGetGC(w, valuemask, &values);
627 
628     wid = -1;
629     if ((!XGetFontProperty(font, XA_QUAD_WIDTH, &wid)) || wid <= 0) {
630 	if (font->per_char && font->min_char_or_byte2 <= '0' &&
631 	    		      font->max_char_or_byte2 >= '0')
632 	    wid = font->per_char['0' - font->min_char_or_byte2].width;
633 	else
634 	    wid = font->max_bounds.width;
635     }
636     if (wid <= 0) wid = 1;
637     data->tabwidth = 8 * wid;
638     data->font = font;
639 
640 /*    data->insertCursorOn = CreateInsertCursor(XtScreen(w)); */
641 
642     {/* Correction from AsciiSink.c on R2 tape */
643       Screen *screen = XtScreen(w);
644       Display *dpy = XtDisplay(w);
645       Window root = RootWindowOfScreen(screen);
646       Pixmap bitmap = XCreateBitmapFromData(dpy, root, insertCursor_bits,
647 					    insertCursor_width,
648 					    insertCursor_height);
649       Pixmap pixmap = XCreatePixmap(dpy, root,insertCursor_width,
650 				    insertCursor_height,
651 				    DefaultDepthOfScreen(screen));
652       XGCValues gcv;
653       GC gc;
654 
655       gcv.function = GXcopy;
656       gcv.foreground = data->foreground ^ w->core.background_pixel;
657       gcv.background = 0;
658       gcv.graphics_exposures = False;
659       gc = XtGetGC(w, (GCFunction | GCForeground | GCBackground |
660 		       GCGraphicsExposures), &gcv);
661       XCopyPlane(dpy, bitmap, pixmap, gc, 0, 0, insertCursor_width,
662 		 insertCursor_height, 0, 0, 1);
663       XtDestroyGC(gc);
664       data->insertCursorOn = pixmap;
665     }
666 
667     data->laststate = XwisOff;
668     (*(sink->check_data))(sink);
669 
670     return sink;
671 }
672 
673