1 /*
2  * Motif
3  *
4  * Copyright (c) 1987-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22 */
23 /*
24  * HISTORY
25 */
26 #ifdef REV_INFO
27 #ifndef lint
28 static char rcsid[] = "$TOG: TextOut.c /main/41 1999/08/12 11:37:30 vipin $"
29 #endif
30 #endif
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34 
35 #include <stdio.h>
36 #include <limits.h>
37 #include <Xm/XmosP.h>
38 #include <X11/Shell.h>
39 #include <X11/Vendor.h>
40 #include <X11/Xatom.h>
41 #include <Xm/AccColorT.h>
42 #include <Xm/AtomMgr.h>
43 #include <Xm/Display.h>
44 #include <Xm/DrawP.h>
45 #include <Xm/NavigatorT.h>
46 #include <Xm/ScrollBar.h>
47 #include <Xm/ScrollFrameT.h>
48 #include <Xm/ScrolledWP.h>
49 #include <Xm/TextStrSoP.h>
50 #include <Xm/TraitP.h>
51 #include "BaseClassI.h"
52 #include "ImageCachI.h"
53 #include "MessagesI.h"
54 #include "ScreenI.h"
55 #include "ScrollFramTI.h"
56 #include "TextI.h"
57 #include "TextInI.h"
58 #include "TextOutI.h"
59 #include "TraversalI.h"
60 #include "XmI.h"
61 #ifdef PRINTING_SUPPORTED
62 #include <Xm/PrintSP.h>         /* for XmIsPrintShell */
63 #endif
64 #ifdef USE_XFT
65 #include "XmRenderTI.h"
66 #endif
67 #include <Xm/XmP.h>
68 
69 
70 #define MSG1	_XmMMsgTextOut_0000
71 #define MSG2	_XmMMsgTextF_0001
72 #define MSG3	_XmMMsgTextF_0002
73 #define MSG4	_XmMMsgTextF_0003
74 
75 #define XmDYNAMIC_BOOL        ((Boolean) (255))
76 
77 /********    Static Function Declarations    ********/
78 
79 
80 static void SliderMove(Widget w,
81 		       XtPointer closure,
82 		       XtPointer call_data);
83 static void _XmTextDrawShadow(XmTextWidget tw);
84 static void SetFullGC(XmTextWidget tw,
85                         GC gc);
86 static void GetRect(XmTextWidget tw,
87 		    XRectangle *rect);
88 static void SetMarginGC(XmTextWidget tw,
89 			  GC gc);
90 static void SetNormGC(XmTextWidget tw,
91                         GC gc,
92 #if NeedWidePrototypes
93                         int change_stipple,
94                         int stipple);
95 #else
96                         Boolean change_stipple,
97                         Boolean stipple);
98 #endif /* NeedWidePrototypes */
99 
100 #ifdef FIX_1381
101 static void SetShadowGC(XmTextWidget tw,
102 		       GC gc);
103 #endif
104 static void InvertImageGC(XmTextWidget tw);
105 static void SetInvGC(XmTextWidget tw,
106 		       GC gc);
107 static int _FontStructFindWidth(XmTextWidget tw,
108 				int x,
109 				XmTextBlock block,
110 				int from,
111 				int to);
112 static int FindWidth(XmTextWidget tw,
113 		     int x,
114 		     XmTextBlock block,
115 		     int from,
116 		     int to);
117 static XmTextPosition XYToPos(XmTextWidget tw,
118 #if NeedWidePrototypes
119 			      int x,
120 			      int y);
121 #else
122                               Position x,
123                               Position y);
124 #endif /* NeedWidePrototypes */
125 static Boolean PosToXY(XmTextWidget tw,
126 		       XmTextPosition position,
127 		       Position *x,
128 		       Position *y);
129 static XtGeometryResult TryResize(XmTextWidget tw,
130 #if NeedWidePrototypes
131 				  int width,
132 				  int height);
133 #else
134                                   Dimension width,
135                                   Dimension height);
136 #endif /* NeedWidePrototypes */
137 static int CountLines(XmTextWidget tw,
138 		      XmTextPosition start,
139 		      XmTextPosition end);
140 static void TextFindNewWidth(XmTextWidget tw,
141 			     Dimension *widthRtn);
142 static void TextFindNewHeight(XmTextWidget tw,
143 			      XmTextPosition position,
144 			      Dimension *heightRtn);
145 static void CheckForNewSize(XmTextWidget tw,
146 			    XmTextPosition position);
147 static XtPointer OutputBaseProc(Widget tw,
148 				XtPointer client_data);
149 static Boolean MeasureLine(XmTextWidget tw,
150 			   LineNum line,
151 			   XmTextPosition position,
152 			   XmTextPosition *nextpos,
153 			   LineTableExtra *extra);
154 static void Draw(XmTextWidget tw,
155 		 LineNum line,
156 		 XmTextPosition start,
157 		 XmTextPosition end,
158 		 XmHighlightMode highlight);
159 static OnOrOff CurrentCursorState(XmTextWidget tw);
160 static void PaintCursor(XmTextWidget tw);
161 static void ChangeHOffset(XmTextWidget tw,
162 			  int newhoffset,
163 #if NeedWidePrototypes
164 			  int redisplay_hbar);
165 #else
166                           Boolean redisplay_hbar);
167 #endif /* NeedWidePrototypes */
168 static void ChangeVOffset(XmTextWidget tw,
169                           int newvoffset,
170 #if NeedWidePrototypes
171                           int redisplay_vbar);
172 #else
173                           Boolean redisplay_vbar);
174 #endif /* NeedWidePrototypes */
175 static void DrawInsertionPoint(XmTextWidget tw,
176 			       XmTextPosition position,
177 			       OnOrOff onoroff);
178 static void MakePositionVisible(XmTextWidget tw,
179 				XmTextPosition position);
180 static void BlinkInsertionPoint(XmTextWidget tw);
181 static Boolean MoveLines(XmTextWidget tw,
182 			 LineNum fromline,
183 			 LineNum toline,
184 			 LineNum destline);
185 static void OutputInvalidate(XmTextWidget tw,
186 			     XmTextPosition position,
187 			     XmTextPosition topos,
188 			     long delta);
189 static void RefigureDependentInfo(XmTextWidget tw);
190 static void SizeFromRowsCols(XmTextWidget tw,
191 			     Dimension *width,
192 			     Dimension *height);
193 static Boolean LoadFontMetrics(XmTextWidget tw);
194 static void LoadGCs(XmTextWidget tw,
195 		    Pixel background,
196 		    Pixel foreground);
197 static void MakeIBeamOffArea(XmTextWidget tw,
198 #if NeedWidePrototypes
199 			     int width,
200 			     int height);
201 #else
202                         Dimension width,
203                         Dimension height);
204 #endif /* NeedWidePrototypes */
205 static Pixmap FindPixmap(Screen *screen,
206 			 char *image_name,
207 			 Pixel foreground,
208 			 Pixel background,
209 			 int depth);
210 static void MakeIBeamStencil(XmTextWidget tw,
211 			     int line_width);
212 static void MakeAddModeCursor(XmTextWidget tw,
213 			      int line_width);
214 static void MakeCursors(XmTextWidget tw);
215 static void OutputGetValues(Widget wid,
216 			    ArgList args,
217 			    Cardinal num_args);
218 static Boolean CKCols(ArgList args,
219 		      Cardinal num_args);
220 static Boolean CKRows(ArgList args,
221 		      Cardinal num_args);
222 static Boolean OutputSetValues(Widget oldw,
223 			       Widget reqw,
224 			       Widget new_w,
225 			       ArgList args,
226 			       Cardinal *num_args);
227 static void NotifyResized(Widget w,
228 #if NeedWidePrototypes
229 			  int o_create);
230 #else
231                           Boolean o_create);
232 #endif /* NeedWidePrototypes */
233 static void HandleTimer(XtPointer closure,
234                         XtIntervalId *id);
235 static void HandleFocusEvents(Widget w,
236 			      XtPointer closure,
237 			      XEvent *event,
238 			      Boolean *cont);
239 static void HandleGraphicsExposure(Widget w,
240 				   XtPointer closure,
241 				   XEvent *event,
242 				   Boolean *cont);
243 static void OutputRealize(Widget w,
244 			  XtValueMask *valueMask,
245 			  XSetWindowAttributes *attributes);
246 static void OutputDestroy(Widget w);
247 static void RedrawRegion(XmTextWidget tw,
248 			 int x,
249 			 int y,
250 			 int width,
251 			 int height);
252 static void OutputExpose(Widget w,
253 			 XEvent *event,
254 			 Region region);
255 static void GetPreferredSize(Widget widget,
256 			     Dimension *width,
257 			     Dimension *height);
258 static void HandleVBarButtonRelease(Widget w,
259 				    XtPointer closure,
260 				    XEvent *event,
261 				    Boolean *cont);
262 static void HandleHBarButtonRelease(Widget w,
263 				    XtPointer closure,
264 				    XEvent *event,
265 				    Boolean *cont);
266 static int _FontStructFindHeight(XmTextWidget tw,
267 				 int x,
268 				 XmTextBlock block,
269 				 int from,
270 				 int to);
271 static int FindHeight(XmTextWidget tw,
272 		      int x,
273 		      XmTextBlock block,
274 		      int from,
275 		      int to);
276 static Boolean _FontStructPerCharExtents(XmTextWidget tw,
277 				     char *str,
278 				     int length,
279 				     XCharStruct *overall);
280 static Boolean SetXOCOrientation(XmTextWidget tw,
281 				 XOC om,
282 				 XOrientation orientation);
283 
284 static void CursorPosVisDefault(
285                         Widget widget,
286                         int offset,
287                         XrmValue *value) ;
288 
289 /********    End Static Function Declarations    ********/
290 
291 #define EraseInsertionPoint(tw)\
292 (*tw->text.output->DrawInsertionPoint)(tw,\
293 					   tw->text.cursor_position, off)
294 
295 #define TextDrawInsertionPoint(tw)\
296 (*tw->text.output->DrawInsertionPoint)(tw,\
297 					   tw->text.cursor_position, on)
298 
299 static XmTextWidget posToXYCachedWidget = NULL;
300 static XmTextPosition posToXYCachedPosition;
301 static Position posToXYCachedX;
302 static Position posToXYCachedY;
303 
304 static XtResource output_resources[] =
305 {
306     {
307       XmNfontList, XmCFontList, XmRFontList, sizeof(XmFontList),
308       XtOffsetOf(OutputDataRec, fontlist),
309       XmRImmediate, (XtPointer)NULL
310     },
311 
312     {
313       XmNrenderTable, XmCRenderTable, XmRRenderTable, sizeof(XmRenderTable),
314       XtOffsetOf(OutputDataRec, rendertable),
315       XmRImmediate, (XtPointer)NULL
316     },
317 
318     {
319       XmNwordWrap, XmCWordWrap, XmRBoolean, sizeof(Boolean),
320       XtOffsetOf(struct _OutputDataRec, wordwrap),
321       XmRImmediate, (XtPointer) False
322     },
323 
324     {
325       XmNblinkRate, XmCBlinkRate, XmRInt, sizeof(int),
326       XtOffsetOf(struct _OutputDataRec, blinkrate),
327       XmRImmediate, (XtPointer) 500
328     },
329 
330     {
331       XmNcolumns, XmCColumns, XmRShort, sizeof(short),
332       XtOffsetOf(struct _OutputDataRec, columns),
333       XmRImmediate, (XtPointer) 0
334     },
335 
336     {
337       XmNrows, XmCRows, XmRShort, sizeof(short),
338       XtOffsetOf(struct _OutputDataRec, rows),
339       XmRImmediate, (XtPointer) 0
340     },
341 
342     {
343       XmNresizeWidth, XmCResizeWidth, XmRBoolean, sizeof(Boolean),
344       XtOffsetOf(struct _OutputDataRec, resizewidth),
345       XmRImmediate, (XtPointer) False
346     },
347 
348     {
349       XmNresizeHeight, XmCResizeHeight, XmRBoolean, sizeof(Boolean),
350       XtOffsetOf(struct _OutputDataRec, resizeheight),
351       XmRImmediate, (XtPointer) False
352     },
353 
354     {
355       XmNscrollVertical, XmCScroll, XmRBoolean, sizeof(Boolean),
356       XtOffsetOf(struct _OutputDataRec, scrollvertical),
357       XmRImmediate,(XtPointer) True
358     },
359 
360     {
361       XmNscrollHorizontal, XmCScroll, XmRBoolean, sizeof(Boolean),
362       XtOffsetOf(struct _OutputDataRec, scrollhorizontal),
363       XmRImmediate, (XtPointer) True
364     },
365 
366     {
367       XmNscrollLeftSide, XmCScrollSide, XmRBoolean, sizeof(Boolean),
368       XtOffsetOf(struct _OutputDataRec, scrollleftside),
369       XmRImmediate,(XtPointer) XmDYNAMIC_BOOL
370     },
371 
372     {
373       XmNscrollTopSide, XmCScrollSide, XmRBoolean, sizeof(Boolean),
374       XtOffsetOf(struct _OutputDataRec, scrolltopside),
375       XmRImmediate, (XtPointer) False
376     },
377 
378     {
379       XmNcursorPositionVisible, XmCCursorPositionVisible, XmRBoolean,
380       sizeof(Boolean),
381       XtOffsetOf(struct _OutputDataRec, cursor_position_visible),
382       XmRCallProc, (XtPointer) CursorPosVisDefault
383 
384     },
385 
386 };
387 
388 /*********************************************************************
389  *
390  * CursorPosVisDefault
391  *
392  *
393  *********************************************************************/
394 /*ARGSUSED*/
395 static void
CursorPosVisDefault(Widget widget,int offset,XrmValue * value)396 CursorPosVisDefault(
397         Widget widget,
398         int offset,		/* unused */
399         XrmValue *value )
400 {
401       static Boolean cursor_pos_vis ;
402       Widget print_shell ;
403 
404       value->addr = (XPointer) &cursor_pos_vis;
405 
406       print_shell = widget ;
407       while(print_shell && !XmIsPrintShell(print_shell))
408 	  print_shell = XtParent(print_shell);
409 
410       if (print_shell) cursor_pos_vis = False ;
411       else             cursor_pos_vis = True ;
412 }
413 
414 
415 /*ARGSUSED*/
416 void
_XmTextFreeContextData(Widget w,XtPointer clientData,XtPointer callData)417 _XmTextFreeContextData(Widget w,		/* unused */
418 		       XtPointer clientData,
419 		       XtPointer callData)	/* unused */
420 {
421   XmTextContextData ctx_data = (XmTextContextData) clientData;
422   Display *display = DisplayOfScreen(ctx_data->screen);
423   XtPointer data_ptr;
424 
425   if (XFindContext(display, (Window) ctx_data->screen,
426 		   ctx_data->context, (char **) &data_ptr)) {
427 
428     if (ctx_data->type != '\0') {
429       if (data_ptr)
430 	XtFree((char *) data_ptr);
431     }
432 
433     XDeleteContext (display, (Window) ctx_data->screen, ctx_data->context);
434   }
435 
436   XtFree ((char *) ctx_data);
437 }
438 
439 
440 /*****************************************************************************
441  * To make TextOut a true "Object" this function should be a class function. *
442  *****************************************************************************/
443 static void
_XmTextDrawShadow(XmTextWidget tw)444 _XmTextDrawShadow(XmTextWidget tw)
445 {
446   if (XtIsRealized((Widget)tw)) {
447     if (tw->primitive.shadow_thickness > 0)
448       XmeDrawShadows (XtDisplay (tw), XtWindow (tw),
449 		      tw->primitive.bottom_shadow_GC,
450 		      tw->primitive.top_shadow_GC,
451 		      tw->primitive.highlight_thickness,
452 		      tw->primitive.highlight_thickness,
453 		      tw->core.width -
454 		      2 * tw->primitive.highlight_thickness,
455 		      tw->core.height -
456 		      2 * tw->primitive.highlight_thickness,
457 		      tw->primitive.shadow_thickness,
458 		      XmSHADOW_OUT);
459 
460 
461     if (tw->primitive.highlighted) {
462       (*(((XmPrimitiveWidgetClass) XtClass((Widget)tw))
463 	 ->primitive_class.border_highlight))((Widget)tw);
464     } else {
465       (*(((XmPrimitiveWidgetClass) XtClass((Widget)tw))
466 	 ->primitive_class.border_unhighlight))((Widget)tw);
467     }
468   }
469 }
470 
471 /* ARGSUSED */
472 void
_XmTextResetClipOrigin(XmTextWidget tw,XmTextPosition position,int clip_mask_reset)473 _XmTextResetClipOrigin(XmTextWidget tw,
474 		       XmTextPosition position,
475 #if NeedWidePrototypes
476 		       int clip_mask_reset)
477 #else
478                        Boolean clip_mask_reset)
479 #endif /* NeedWidePrototypes */
480 {
481   OutputData data = tw->text.output->data;
482   int x, y;
483   Position x_pos, y_pos;
484 
485   if (!XtIsRealized((Widget)tw)) return;
486 
487   if (!PosToXY(tw, tw->text.cursor_position, &x_pos, &y_pos)) return;
488 
489   x = (int) x_pos; y = (int) y_pos;
490 
491   x -=(data->cursorwidth >> 1) + 1;
492   y = (y + data->font_descent) - data->cursorheight;
493 
494   XSetTSOrigin(XtDisplay((Widget)tw), data->imagegc, x, y);
495 }
496 
497 static void
SetFullGC(XmTextWidget tw,GC gc)498 SetFullGC(XmTextWidget tw,
499 	    GC gc)
500 {
501   XRectangle ClipRect;
502 
503   ClipRect.x = tw->primitive.highlight_thickness +
504     tw->primitive.shadow_thickness;
505   ClipRect.y = tw->primitive.highlight_thickness +
506     tw->primitive.shadow_thickness;
507   ClipRect.width = tw->core.width - (2 *(tw->primitive.highlight_thickness +
508 					 tw->primitive.shadow_thickness));
509   ClipRect.height = tw->core.height - (2 *(tw->primitive.highlight_thickness +
510 					   tw->primitive.shadow_thickness));
511 
512   XSetClipRectangles(XtDisplay(tw), gc, 0, 0,
513 		     &ClipRect, 1, Unsorted);
514 }
515 
516 static void
GetRect(XmTextWidget tw,XRectangle * rect)517 GetRect(XmTextWidget tw,
518         XRectangle *rect)
519 {
520   Dimension margin_width = tw->text.margin_width +
521     tw->primitive.shadow_thickness +
522       tw->primitive.highlight_thickness;
523   Dimension margin_height = tw->text.margin_height +
524     tw->primitive.shadow_thickness +
525       tw->primitive.highlight_thickness;
526 
527   if (margin_width < tw->core.width)
528     rect->x = margin_width;
529   else
530     rect->x = tw->core.width;
531 
532   if (margin_height < tw->core.height)
533     rect->y = margin_height;
534   else
535     rect->y = tw->core.height;
536 
537   if ((int) (2 * margin_width) < (int) tw->core.width)
538     rect->width = (int) tw->core.width - (2 * margin_width);
539   else
540     rect->width = 0;
541 
542   if ((int) (2 * margin_height) < (int) tw->core.height)
543     rect->height = (int) tw->core.height - (2 * margin_height);
544   else
545     rect->height = 0;
546 }
547 
548 static void
SetMarginGC(XmTextWidget tw,GC gc)549 SetMarginGC(XmTextWidget tw,
550 	      GC gc)
551 {
552   XRectangle ClipRect;
553 
554   GetRect(tw, &ClipRect);
555 #ifdef USE_XFT
556   if (tw->text.output->data->use_xft)
557     _XmXftSetClipRectangles(XtDisplay(tw), XtWindow(tw), 0, 0, &ClipRect, 1);
558 #endif
559   XSetClipRectangles(XtDisplay(tw), gc, 0, 0, &ClipRect, 1,
560                      Unsorted);
561 }
562 
563 
564 /*****************************************************************************
565  * To make TextOut a true "Object" this function should be a class function. *
566  *****************************************************************************/
567 /*
568  * Set new clipping rectangle for text widget.  This is
569  * done on each focus in event since the text widgets
570  * share the same GC.
571  */
572 void
_XmTextAdjustGC(XmTextWidget tw)573 _XmTextAdjustGC(XmTextWidget tw)
574 {
575   OutputData data = tw->text.output->data;
576   unsigned long valueMask = (GCForeground | GCBackground);
577   XGCValues values;
578 
579   if (!XtIsRealized((Widget)tw)) return;
580 
581   SetMarginGC(tw, data->gc);
582 
583   /* Restore cached text gc to state correct for this instantiation */
584 
585   if (data->gc) {
586     values.foreground = tw->primitive.foreground ^ tw->core.background_pixel;
587     values.background = 0;
588     XChangeGC(XtDisplay(tw), data->gc, valueMask, &values);
589   }
590 }
591 
592 
593 static void
SetNormGC(XmTextWidget tw,GC gc,int change_stipple,int stipple)594 SetNormGC(XmTextWidget tw,
595 	    GC gc,
596 #if NeedWidePrototypes
597 	    int change_stipple,
598 	    int stipple)
599 #else
600             Boolean change_stipple,
601 	    Boolean stipple)
602 #endif /* NeedWidePrototypes */
603 {
604   unsigned long valueMask = (GCForeground | GCBackground);
605   XGCValues values;
606   OutputData data = tw->text.output->data;
607 
608   values.foreground = tw->primitive.foreground;
609   values.background = tw->core.background_pixel;
610   if (change_stipple) {
611     valueMask |= GCFillStyle;
612     if (stipple) {
613 #ifdef FIX_1381
614 		/*generally gray insensitive foreground (instead stipple)*/
615 		values.foreground = _XmAssignInsensitiveColor((Widget)tw);
616 	    values.fill_style = FillSolid;
617 #else
618       values.fill_style = FillStippled;
619       valueMask |= GCStipple;
620       values.stipple = data->stipple_tile;
621 #endif
622 
623     } else
624       values.fill_style = FillSolid;
625   }
626 
627   XChangeGC(XtDisplay(tw), gc, valueMask, &values);
628 }
629 
630 #ifdef FIX_1381
631 static void
SetShadowGC(XmTextWidget tf,GC gc)632 SetShadowGC(XmTextWidget tf, GC gc)
633 {
634   unsigned long valueMask = (GCForeground | GCBackground);
635   XGCValues values;
636 
637   /*generally light gray insensitive foreground (instead stipple)*/
638   values.foreground = tf->primitive.top_shadow_color;
639   values.background = tf->core.background_pixel;
640 
641   values.fill_style = FillSolid;
642 
643   XChangeGC(XtDisplay(tf), gc, valueMask, &values);
644 }
645 #endif
646 
647 
648 
649 static void
InvertImageGC(XmTextWidget tw)650 InvertImageGC(XmTextWidget tw)
651 {
652   OutputData data = tw->text.output->data;
653 
654   data->have_inverted_image_gc = !data->have_inverted_image_gc;
655 }
656 
657 static void
SetInvGC(XmTextWidget tw,GC gc)658 SetInvGC(XmTextWidget tw,
659 	   GC gc)
660 {
661   unsigned long valueMask = (GCForeground | GCBackground);
662   XGCValues values;
663 
664   values.foreground = tw->core.background_pixel;
665   values.background = tw->primitive.foreground;
666 
667   XChangeGC(XtDisplay(tw), gc, valueMask, &values);
668 }
669 
670 
671 static int
_FontStructFindWidth(XmTextWidget tw,int x,XmTextBlock block,int from,int to)672 _FontStructFindWidth(XmTextWidget tw,
673 		     int x,    /* Starting position (needed for tabs) */
674 		     XmTextBlock block,
675 		     int from, /* How many bytes in to start measuring */
676 		     int to)   /* How many bytes in to stop measuring */
677 {
678   OutputData data = tw->text.output->data;
679   XFontStruct *font = data->font;
680   char *ptr;
681   unsigned char c;
682   int i, csize;
683   int result = 0;
684 
685   if (tw->text.char_size != 1) {
686     int dummy;
687     XCharStruct overall;
688 
689     for (i = from, ptr = block->ptr + from; i < to; i +=csize, ptr += csize) {
690 #ifndef NO_MULTIBYTE
691       csize = mblen(ptr, tw->text.char_size);
692 #else
693       csize = *ptr ? 1 : 0;
694 #endif
695       if (csize <= 0) break;
696       c = (unsigned char) *ptr;
697       if (csize == 1) {
698 	if (c == '\t') {
699 	  result += (data->tabwidth -
700 		     ((x + result - data->leftmargin) % data->tabwidth));
701 	} else {
702 	  if (font->per_char && (c >= font->min_char_or_byte2 &&
703 				 c <= font->max_char_or_byte2))
704 	    result += font->per_char[c - font->min_char_or_byte2].width;
705 	  else
706 	    result += font->min_bounds.width;
707 	}
708       } else {
709         if (_XmIsISO10646(XtDisplay(tw), data->font)) {
710           size_t ucsstr_len = 0;
711           XChar2b *ucsstr = _XmUtf8ToUcs2(ptr, csize, &ucsstr_len);
712           XTextExtents16(data->font, ucsstr, ucsstr_len,
713 			&dummy, &dummy, &dummy, &overall);
714           XFree(ucsstr);
715         } else
716 	  XTextExtents(data->font, ptr, csize, &dummy, &dummy, &dummy,
717 		     &overall);
718 	result += overall.width;
719       }
720     }
721   } else {
722     for (i=from, ptr = block->ptr + from; i<to; i++, ptr++) {
723       c = (unsigned char) *ptr;
724       if (c == '\t')
725 	result += (data->tabwidth -
726 		   ((x + result - data->leftmargin) % data->tabwidth));
727       /* %%% Do something for non-printing? */
728       else {
729 	if (font->per_char) {
730 	  if (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2)
731 	    result += font->per_char[c - font->min_char_or_byte2].width;
732 	  else if (font->default_char >= font->min_char_or_byte2 &&
733 		   font->default_char <= font->max_char_or_byte2)
734 	    result += font->per_char[font->default_char -
735 				     font->min_char_or_byte2].width;
736 	  else
737 	    result += font->min_bounds.width;
738 	} else
739 	  result += font->min_bounds.width;
740       }
741     }
742   }
743   return result;
744 }
745 
746 static int
FindWidth(XmTextWidget tw,int x,XmTextBlock block,int from,int to)747 FindWidth(XmTextWidget tw,
748 	  int x,                  /* Starting position (needed for tabs) */
749 	  XmTextBlock block,
750 	  int from,               /* How many bytes in to start measuring */
751 	  int to)                 /* How many bytes in to stop measuring */
752 {
753   OutputData data = tw->text.output->data;
754   char *ptr;
755   unsigned char c;
756   int result = 0;
757   int tmp;
758   int csize = 1;
759   int i;
760 
761 #if USE_XFT
762   if (!data->use_fontset && !data->use_xft)
763 #else
764   if (!data->use_fontset)
765 #endif
766     return _FontStructFindWidth(tw, x, block, from, to);
767 
768   if (to > block->length)
769     to = block->length;
770   if (from > to) {
771     tmp = to;
772     to = from;
773     from = tmp;
774   }
775 
776   if (to == from || to == 0) return 0;
777 
778   if (tw->text.char_size != 1) {
779     for (i = from, ptr = block->ptr + from; i < to; i +=csize, ptr += csize) {
780 #ifndef NO_MULTIBYTE
781       csize = mblen(ptr, tw->text.char_size);
782 #else
783       csize = *ptr ? 1 : 0;
784 #endif
785       if (csize <= 0) break;
786       c = (unsigned char) *ptr;
787       if (csize == 1 && c == '\t')
788 	result += (data->tabwidth -
789 		   ((x + result - data->leftmargin) % data->tabwidth));
790       else
791 #ifdef USE_XFT
792         if (data->use_xft) {
793 	  XGlyphInfo	ext;
794 	  XftTextExtentsUtf8(XtDisplay(tw), ((XftFont*)data->font),
795 	                  (FcChar8*)ptr, csize, &ext);
796 	  result += ext.xOff;
797 	} else
798 #endif
799 	result += XmbTextEscapement((XFontSet)data->font, ptr, csize);
800     }
801 
802   } else { /* no need to pay for mblen if we know all chars are 1 byte */
803     for (i = from, ptr = block->ptr + from; i < to; i++, ptr++) {
804       c = (unsigned char) *ptr;
805       if (c == '\t')
806 	result += (data->tabwidth -
807 		   ((x + result - data->leftmargin) % data->tabwidth));
808       else
809 #ifdef USE_XFT
810         if (data->use_xft) {
811 	  XGlyphInfo	ext;
812 	  XftTextExtentsUtf8(XtDisplay(tw), ((XftFont*)data->font),
813 	                  (FcChar8*)ptr, 1, &ext);
814 	  result += ext.xOff;
815 	} else
816 #endif
817 	result += XmbTextEscapement((XFontSet)data->font, ptr, 1);
818     }
819   }
820   return result;
821 }
822 
823 
824 static int
_FontStructFindHeight(XmTextWidget tw,int y,XmTextBlock block,int from,int to)825 _FontStructFindHeight(XmTextWidget tw,
826 		     int y,    /* Starting position (needed for tabs) */
827 		     XmTextBlock block,
828 		     int from, /* How many bytes in to start measuring */
829 		     int to)   /* How many bytes in to stop measuring */
830 {
831   OutputData data = tw->text.output->data;
832   XFontStruct *font = data->font;
833   char *ptr = NULL;
834   unsigned char c;
835   int i = 0, csize = 0;
836   int result = 0;
837   XCharStruct overall;
838 
839   if (tw->text.char_size != 1) {
840     for (i = from, ptr = block->ptr + from; i < to; i +=csize, ptr += csize) {
841       csize = mblen(ptr, tw->text.char_size);
842       if (csize <= 0) break;
843       if (csize == 1 && (unsigned char)*ptr == '\t') {
844 	  result += (data->tabheight -
845 		     ((y + result - data->topmargin) % data->tabheight));
846       } else {
847 	_FontStructPerCharExtents(tw, ptr, csize, &overall);
848 	result += overall.ascent + overall.descent;
849       }
850     }
851   } else {
852     for (i=from, ptr = block->ptr + from; i<to; i++, ptr++) {
853       c = (unsigned char) *ptr;
854       if ((unsigned char) *ptr == '\t') {
855 	result += (data->tabheight -
856 		   ((y + result - data->topmargin) % data->tabheight));
857       } else {
858 	_FontStructPerCharExtents(tw, ptr, 1, &overall);
859 	result += overall.ascent + overall.descent;
860       }
861     }
862   }
863   return result;
864 }
865 
866 #ifdef USE_XFT
867 static int
_XftFindHeight(XmTextWidget tw,int y,XmTextBlock block,int from,int to)868 _XftFindHeight(XmTextWidget tw,
869 		     int y,    /* Starting position (needed for tabs) */
870 		     XmTextBlock block,
871 		     int from, /* How many bytes in to start measuring */
872 		     int to)   /* How many bytes in to stop measuring */
873 {
874   OutputData data = tw->text.output->data;
875   XftFont *font = (XftFont*)data->font;
876   char *ptr = NULL;
877   unsigned char c;
878   int i = 0, csize = 0;
879   int result = 0;
880   XGlyphInfo ext;
881 
882   if (tw->text.char_size != 1) {
883     for (i = from, ptr = block->ptr + from; i < to; i +=csize, ptr += csize) {
884       csize = mblen(ptr, tw->text.char_size);
885       if (csize <= 0) break;
886       if (csize == 1 && (unsigned char)*ptr == '\t') {
887 	  result += (data->tabheight -
888 		     ((y + result - data->topmargin) % data->tabheight));
889       } else {
890 	XftTextExtentsUtf8(XtDisplay(tw), font, (FcChar8*)ptr, csize, &ext);
891 	result += ext.yOff;
892       }
893     }
894   } else {
895     for (i=from, ptr = block->ptr + from; i<to; i++, ptr++) {
896       c = (unsigned char) *ptr;
897       if ((unsigned char) *ptr == '\t') {
898 	result += (data->tabheight -
899 		   ((y + result - data->topmargin) % data->tabheight));
900       } else {
901 	XftTextExtentsUtf8(XtDisplay(tw), font, (FcChar8*)ptr, 1, &ext);
902 	result += ext.yOff;
903       }
904     }
905   }
906   return result;
907 }
908 #endif
909 
910 static int
FindHeight(XmTextWidget tw,int y,XmTextBlock block,int from,int to)911 FindHeight(XmTextWidget tw,
912 	  int y,                  /* Starting position (needed for tabs) */
913 	  XmTextBlock block,
914 	  int from,               /* How many bytes in to start measuring */
915 	  int to)                 /* How many bytes in to stop measuring */
916 {
917   OutputData data = tw->text.output->data;
918   char *ptr = NULL;
919   unsigned char c;
920   int result = 0;
921   int tmp = 0;
922   int csize = 1;
923   int i = 0;
924   XOrientation orient;
925 
926 #ifdef USE_XFT
927   if (data->use_xft)
928     return _XftFindHeight(tw, y, block, from, to);
929 #endif
930 
931   if (!data->use_fontset)
932     return _FontStructFindHeight(tw, y, block, from, to);
933 
934   if (to > block->length)
935     to = block->length;
936   if (from > to) {
937     tmp = to;
938     to = from;
939     from = tmp;
940   }
941 
942   if (to == from || to == 0) return 0;
943 
944   if(data->use_fontset == True) {
945     XGetOCValues((XOC)data->font, XNOrientation, &orient, NULL);
946     SetXOCOrientation(tw, (XOC)data->font, XOMOrientation_TTB_RTL);
947   }
948   if (tw->text.char_size != 1) {
949     for (i = from, ptr = block->ptr + from; i < to; i +=csize, ptr += csize) {
950       csize = mblen(ptr, tw->text.char_size);
951       if (csize <= 0) break;
952       c = (unsigned char) *ptr;
953       if (csize == 1 && c == '\t')
954 	result += (data->tabheight -
955 		   ((y + result - data->topmargin) % data->tabheight));
956       else
957 	result += XmbTextEscapement((XFontSet)data->font, ptr, csize);
958     }
959 
960   } else { /* no need to pay for mblen if we know all chars are 1 byte */
961     for (i = from, ptr = block->ptr + from; i < to; i++, ptr++) {
962       c = (unsigned char) *ptr;
963       if (c == '\t')
964 	result += (data->tabheight -
965 		   ((y + result - data->topmargin) % data->tabheight));
966       else
967 	result += XmbTextEscapement((XFontSet)data->font, ptr, 1);
968     }
969   }
970   if(data->use_fontset == True) {
971     SetXOCOrientation(tw, (XOC)data->font, orient);
972   }
973   return result;
974 }
975 
976 
977 /* Semi-public routines. */
978 
979 static XmTextPosition
XYToPos(XmTextWidget tw,int x,int y)980 XYToPos(XmTextWidget tw,
981 #if NeedWidePrototypes
982         int x,
983         int y)
984 #else
985         Position x,
986         Position y)
987 #endif /* NeedWidePrototypes */
988 {
989   OutputData data = tw->text.output->data;
990   LineTableExtra extra = (LineTableExtra)NULL;
991   int i = 0, width = 0, lastwidth = 0, length = 0;
992   int height = 0, lastheight = 0;
993   int num_chars = 0;
994   int num_bytes = 0;
995   LineNum line = 0;
996   XmTextPosition start, end, laststart;
997   XmTextBlockRec block;
998   int delta = 0;
999 
1000   start = end = laststart = 0;
1001 
1002   if(XmDirectionMatch(XmPrim_layout_direction(tw),
1003 		      XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
1004     y += data->voffset;
1005     /* take care of negative x case */
1006     if (data->linewidth) {
1007       int rightedge = tw->text.inner_widget->core.width - data->rightmargin;
1008       if (x > rightedge) {
1009 	delta = ((int)(rightedge - x - 1)/ (int) data->linewidth) + 1;
1010 	x = rightedge;
1011       }
1012       line = (rightedge - x) / (int)(data->linewidth);
1013     }
1014     if (line > _XmTextNumLines(tw)) line = _XmTextNumLines(tw);
1015     _XmTextLineInfo(tw, line, &start, &extra);
1016     if (start == PASTENDPOS)
1017       return (*tw->text.source->Scan)(tw->text.source, 0,
1018 					XmSELECT_ALL, XmsdRight, 1, False);
1019     _XmTextLineInfo(tw, line+1, &end, &extra);
1020     end = (*tw->text.source->Scan)(tw->text.source, end,
1021 				     XmSELECT_POSITION, XmsdLeft, 1, True);
1022     height = lastheight = data->topmargin;
1023     if (start >= end && !delta) return start;
1024 
1025     /* if original y was negative, we need to find new laststart */
1026     if (delta && start > 0) {
1027       end = (*tw->text.source->Scan)(tw->text.source, start,
1028                                        XmSELECT_POSITION, XmsdLeft, 1, True);
1029       start = _XmTextFindScroll(tw, start, delta);
1030     }
1031 
1032     do {
1033       laststart = start;
1034       start = (*tw->text.source->ReadSource)(tw->text.source, start,
1035 					       end, &block);
1036       length = block.length;
1037       if ((int)tw->text.char_size > 1) {
1038 	for (i = num_chars = 0, num_bytes = mblen(block.ptr,
1039 						(int)tw->text.char_size);
1040 	     i < length && height < y && num_bytes >= 0;
1041 	     i += num_bytes, num_chars++,
1042 	     num_bytes = mblen(&block.ptr[i], (int)tw->text.char_size)) {
1043 	  lastheight = height;
1044 	  height += FindHeight(tw, height, &block, i, i + num_bytes);
1045 	}
1046 	i = num_chars;
1047       } else {
1048 	for (i=0; i<length && height < y; i++) {
1049 	  lastheight = height;
1050 	  height += FindHeight(tw, height, &block, i, i+1);
1051 	}
1052       }
1053     } while (height < y && start < end && laststart != end);
1054 
1055     if (abs(lastheight - y) < abs(height - y)) i--;
1056   } else {
1057 
1058   x += data->hoffset;
1059   y -= data->topmargin;
1060   /* take care of negative y case */
1061   if (data->lineheight) {
1062     if (y < 0) {
1063       delta = ((int)(y + 1)/ (int) data->lineheight) - 1;
1064       y = 0;
1065     }
1066     line = y / (int) data->lineheight;
1067   }
1068   if (line > _XmTextNumLines(tw)) line = _XmTextNumLines(tw);
1069   _XmTextLineInfo(tw, line, &start, &extra);
1070   if (start == PASTENDPOS)
1071     return (*tw->text.source->Scan)(tw->text.source, 0,
1072 					XmSELECT_ALL, XmsdRight, 1, False);
1073   _XmTextLineInfo(tw, line+1, &end, &extra);
1074   end = (*tw->text.source->Scan)(tw->text.source, end,
1075 				     XmSELECT_POSITION, XmsdLeft, 1, True);
1076   width = lastwidth = data->leftmargin;
1077   if (start >= end && !delta) return start;
1078 
1079   /* if original y was negative, we need to find new laststart */
1080   if (delta && start > 0) {
1081     end = (*tw->text.source->Scan)(tw->text.source, start,
1082                                        XmSELECT_POSITION, XmsdLeft, 1, True);
1083     start = _XmTextFindScroll(tw, start, delta);
1084   }
1085 
1086   do {
1087     laststart = start;
1088     start = (*tw->text.source->ReadSource)(tw->text.source, start,
1089 					       end, &block);
1090     length = block.length;
1091     if ((int)tw->text.char_size > 1) {
1092       for (i = num_chars = 0,
1093 #ifndef NO_MULTIBYTE
1094 	   num_bytes = mblen(block.ptr, (int)tw->text.char_size);
1095 #else
1096 	   num_bytes = *block.ptr ? 1 : 0;
1097 #endif
1098 	   i < length && width < x && num_bytes >= 0;
1099 	   i += num_bytes, num_chars++,
1100 #ifndef NO_MULTIBYTE
1101 	   num_bytes = mblen(&block.ptr[i], (int)tw->text.char_size)) {
1102 #else
1103 	   num_bytes = block.ptr[i] ? 1 : 0) {
1104 #endif
1105 	lastwidth = width;
1106 	width += FindWidth(tw, width, &block, i, i + num_bytes);
1107       }
1108       i = num_chars;
1109     } else {
1110       for (i=0; i<length && width < x; i++) {
1111 	lastwidth = width;
1112 	width += FindWidth(tw, width, &block, i, i+1);
1113       }
1114     }
1115   } while (width < x && start < end && laststart != end);
1116 
1117   if (abs(lastwidth - x) < abs(width - x)) i--;
1118   }
1119   return (*tw->text.source->Scan)(tw->text.source, laststart,
1120 				      XmSELECT_POSITION, (i < 0) ?
1121 				      XmsdLeft : XmsdRight, abs(i), True);
1122 }
1123 
1124 /*****************************************************************************
1125  * To make TextOut a true "Object" this function should be a class function. *
1126  *****************************************************************************/
1127 Boolean
1128 _XmTextShouldWordWrap(XmTextWidget tw)
1129 {
1130   OutputData data = tw->text.output->data;
1131   return (ShouldWordWrap(data, tw));
1132 }
1133 
1134 
1135 /*****************************************************************************
1136  * To make TextOut a true "Object" this function should be a class function. *
1137  *****************************************************************************/
1138 Boolean
1139 _XmTextScrollable(XmTextWidget tw)
1140 {
1141   OutputData data = tw->text.output->data;
1142   if(XmDirectionMatch(XmPrim_layout_direction(tw),
1143 		      XmTOP_TO_BOTTOM_RIGHT_TO_LEFT))
1144     return (data->scrollhorizontal && XmIsScrolledWindow(XtParent(tw)));
1145   else
1146     return (data->scrollvertical && XmIsScrolledWindow(XtParent(tw)));
1147 }
1148 
1149 static Boolean
1150 PosToXY(XmTextWidget tw,
1151         XmTextPosition position,
1152         Position *x,
1153         Position *y)
1154 {
1155   OutputData data = tw->text.output->data;
1156   LineNum line;
1157   XmTextPosition linestart;
1158   LineTableExtra extra;
1159   XmTextBlockRec block;
1160   Position local_x, local_y;
1161 
1162   if(XmDirectionMatch(XmPrim_layout_direction(tw),
1163 		      XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
1164   _XmProcessLock();
1165     if (tw == posToXYCachedWidget && position == posToXYCachedPosition) {
1166       *x = posToXYCachedX;
1167       *y = posToXYCachedY;
1168       _XmProcessUnlock();
1169       return True;
1170     }
1171   _XmProcessUnlock();
1172 
1173     line = _XmTextPosToLine(tw, position);
1174     if (line == NOLINE || line >= data->number_lines) return False;
1175     local_y = data->topmargin;
1176     local_x = tw->text.inner_widget->core.width -
1177 	 (data->rightmargin + line * data->linewidth +
1178 	  data->linewidth * 0.5);
1179     _XmTextLineInfo(tw, line, &linestart, &extra);
1180     while (linestart < position) {
1181       linestart = (*tw->text.source->ReadSource)(tw->text.source,
1182 						   linestart, position,
1183 						   &block);
1184       local_y += FindHeight(tw, local_y, &block, 0, block.length);
1185     }
1186     local_y -= data->voffset;
1187   } else {
1188 
1189   _XmProcessLock();
1190   if (tw == posToXYCachedWidget && position == posToXYCachedPosition) {
1191     *x = posToXYCachedX;
1192     *y = posToXYCachedY;
1193     _XmProcessUnlock();
1194     return True;
1195   }
1196   _XmProcessUnlock();
1197 
1198   line = _XmTextPosToLine(tw, position);
1199   if (line == NOLINE || line >= data->number_lines) return False;
1200   local_y = data->topmargin + line * data->lineheight + data->font_ascent;
1201   local_x = data->leftmargin;
1202   _XmTextLineInfo(tw, line, &linestart, &extra);
1203   while (linestart < position) {
1204     linestart = (*tw->text.source->ReadSource)(tw->text.source,
1205 						   linestart, position,
1206 						   &block);
1207     local_x += FindWidth(tw, local_x, &block, 0, block.length);
1208   }
1209   local_x -= data->hoffset;
1210   }
1211   _XmProcessLock();
1212   posToXYCachedWidget = tw;
1213   posToXYCachedPosition = position;
1214   posToXYCachedX = local_x;
1215   posToXYCachedY = local_y;
1216   *x = local_x;
1217   *y = local_y;
1218   _XmProcessUnlock();
1219   return True;
1220 }
1221 
1222 /*****************************************************************************
1223  * To make TextOut a true "Object" this function should be a class function. *
1224  *****************************************************************************/
1225 XmTextPosition
1226 _XmTextFindLineEnd(XmTextWidget tw,
1227 		   XmTextPosition position,
1228 		   LineTableExtra *extra)
1229 {
1230   OutputData data = tw->text.output->data;
1231   XmTextPosition lastChar, lineEnd, nextLeft, nextBreak, lastBreak, oldpos;
1232   XmTextPosition startpos = 0;
1233   XmTextBlockRec block;
1234   int x, lastX, goalwidth, length, i;
1235   int y, lastY, goalheight;
1236   int num_bytes = 0;
1237 
1238   lastChar = (*tw->text.source->Scan)(tw->text.source, position,
1239 					  XmSELECT_LINE, XmsdRight, 1, False);
1240   lastBreak = startpos = position;
1241 
1242   if(XmDirectionMatch(XmPrim_layout_direction(tw),
1243 		      XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
1244     y = lastY = data->topmargin;
1245     goalheight = tw->text.inner_widget->core.height - data->bottommargin;
1246     while (position < lastChar) {
1247       nextLeft = (*tw->text.source->Scan)(tw->text.source, position,
1248                                             XmSELECT_WHITESPACE, XmsdRight,
1249                                             1, False);
1250       nextBreak = (*tw->text.source->Scan)(tw->text.source, nextLeft,
1251 					     XmSELECT_WHITESPACE, XmsdRight,
1252 					     1, True);
1253       while (position < nextLeft) {
1254 	position = (*tw->text.source->ReadSource)(tw->text.source,
1255 						    position, nextLeft,
1256 						    &block);
1257 	length = block.length;
1258 	y += FindHeight(tw, y, &block, 0, block.length);
1259 	if (y > goalheight) {
1260 	  if (lastBreak > startpos) {
1261 	    if (lastY <= goalheight) /* word wrap is being performed */
1262 	      {
1263 		return lastBreak;
1264 	      }
1265 	    y = lastY;
1266 	    oldpos = position = lastBreak;
1267 	    while (y > goalheight && position > startpos) {
1268 	      oldpos = position;
1269 	      position = (*tw->text.source->Scan)
1270 	        (tw->text.source, position, XmSELECT_POSITION,
1271 	         XmsdLeft, 1, True);
1272 	      (void) (*tw->text.source->ReadSource)
1273 	        (tw->text.source, position, oldpos, &block);
1274 	      num_bytes = mblen(block.ptr,
1275 			        (int)tw->text.char_size);
1276 	      /* Pitiful error handling, but what else can you do? */
1277 	      if (num_bytes < 0) num_bytes = 1;
1278 	      y -= FindHeight(tw, y, &block, 0, num_bytes);
1279 	    }
1280 	    if (extra) {
1281 	      *extra = (LineTableExtra)
1282 	        XtMalloc((unsigned) sizeof(LineTableExtraRec));
1283 	      (*extra)->wrappedbychar = True;
1284 	      (*extra)->width = 0;
1285 	    }
1286 	    return oldpos; /* Allows one whitespace char to appear */
1287 	    /* partially off the edge. */
1288 	  }
1289 	  if (extra) {
1290 	    *extra = (LineTableExtra)
1291 	      XtMalloc((unsigned) sizeof(LineTableExtraRec));
1292 	    (*extra)->wrappedbychar = True;
1293 	    (*extra)->width = 0;
1294 	  }
1295 	  if ((int)tw->text.char_size == 1) {
1296 	    for (i=length - 1; i>=0 && y > goalheight; i--) {
1297 	      y -= FindHeight(tw, y, &block, i, i + 1);
1298 	      position =
1299 	        (*tw->text.source->Scan)(tw->text.source,
1300 					     position,
1301 					     XmSELECT_POSITION,
1302 					     XmsdLeft, 1, True);
1303 	    }
1304 	    return position;
1305 	  } else {
1306 	    char tmp_cache[200];
1307 	    wchar_t * tmp_wc;
1308 	    Cardinal tmp_wc_size;
1309 	    char tmp_char[MB_LEN_MAX];
1310 	    int num_chars = 0;
1311 	    XmTextBlockRec mini_block;
1312 
1313 	    /* If 16-bit data, convert the char* to wchar_t*... this
1314 	     * allows us to scan backwards through the text one
1315 	     * character at a time.  Without wchar_t, we would have
1316 	     * to continually scan from the start of the string to
1317 	     * find the byte offset of character n-1.
1318 	     */
1319 	    mini_block.ptr = tmp_char;
1320 	    num_chars = _XmTextCountCharacters(block.ptr, block.length);
1321 	    tmp_wc_size = (num_chars + 1) * sizeof(wchar_t);
1322 	    tmp_wc = (wchar_t *) XmStackAlloc(tmp_wc_size, tmp_cache);
1323 	    num_chars = mbstowcs(tmp_wc, block.ptr, num_chars);
1324 	    if (num_chars > 0) {
1325 	      for (i = num_chars - 1; i >= 0 && y > goalheight; i--) {
1326 		mini_block.length = wctomb(mini_block.ptr, tmp_wc[i]);
1327 		if (mini_block.length < 0) mini_block.length = 0;
1328 		y -= FindHeight(tw, y, &mini_block,
1329 			        0, mini_block.length);
1330 		position =
1331 		  (*tw->text.source->Scan)(tw->text.source,
1332 					       position,
1333 					       XmSELECT_POSITION,
1334 					       XmsdLeft, 1, True);
1335 	      }
1336 	    }
1337 	    XmStackFree((char*)tmp_wc, tmp_cache);
1338 	  } /* end multi-byte handling */
1339 	  return position;
1340         }
1341       }
1342       while (position < nextBreak) {
1343 	position = (*tw->text.source->ReadSource)(tw->text.source,
1344 						      position, nextBreak,
1345 						      &block);
1346 	length = block.length;
1347 	y += FindHeight(tw, y, &block, 0, block.length);
1348       }
1349       lastBreak = nextBreak;
1350       lastY = y;
1351     }
1352   } else {
1353 
1354   x = lastX = data->leftmargin;
1355   goalwidth = tw->text.inner_widget->core.width - data->rightmargin;
1356   while (position < lastChar) {
1357     nextLeft = (*tw->text.source->Scan)(tw->text.source, position,
1358                                             XmSELECT_WHITESPACE, XmsdRight,
1359                                             1, False);
1360     nextBreak = (*tw->text.source->Scan)(tw->text.source, nextLeft,
1361 					     XmSELECT_WHITESPACE, XmsdRight,
1362 					     1, True);
1363     while ((position < nextLeft) ||
1364 	   (nextBreak == lastChar && position < nextBreak)) {
1365       if (position < nextLeft)
1366         position = (*tw->text.source->ReadSource)(tw->text.source,
1367 						    position, nextLeft,
1368 						    &block);
1369       else
1370         position = (*tw->text.source->ReadSource)(tw->text.source,
1371 						    position, nextBreak,
1372 						    &block);
1373       length = block.length;
1374       x += FindWidth(tw, x, &block, 0, block.length);
1375       if (x > goalwidth) {
1376 	if (lastBreak > startpos) {
1377 	  if (lastX <= goalwidth) /* word wrap is being performed */
1378 	    {
1379 	      return lastBreak;
1380 	    }
1381 	  x = lastX;
1382 	  oldpos = position = lastBreak;
1383 	  while (x > goalwidth && position > startpos) {
1384 	    oldpos = position;
1385 	    position = (*tw->text.source->Scan)
1386 	      (tw->text.source, position, XmSELECT_POSITION,
1387 	       XmsdLeft, 1, True);
1388 	    (void) (*tw->text.source->ReadSource)
1389 	      (tw->text.source, position, oldpos, &block);
1390 #ifndef NO_MULTIBYTE
1391 	    num_bytes = mblen(block.ptr, (int)tw->text.char_size);
1392 #else
1393 	    num_bytes = *block.ptr ? 1 : 0;
1394 #endif
1395 	    /* Pitiful error handling, but what else can you do? */
1396 	    if (num_bytes < 0) num_bytes = 1;
1397 	    x -= FindWidth(tw, x, &block, 0, num_bytes);
1398 	  }
1399 	  if (extra) {
1400 	    *extra = (LineTableExtra)
1401 	      XtMalloc((unsigned) sizeof(LineTableExtraRec));
1402 	    (*extra)->wrappedbychar = True;
1403 	    (*extra)->width = 0;
1404 	  }
1405 	  return oldpos; /* Allows one whitespace char to appear */
1406 	  /* partially off the edge. */
1407 	}
1408 	if (extra) {
1409 	  *extra = (LineTableExtra)
1410 	    XtMalloc((unsigned) sizeof(LineTableExtraRec));
1411 	  (*extra)->wrappedbychar = True;
1412 	  (*extra)->width = 0;
1413 	}
1414 	if ((int)tw->text.char_size == 1) {
1415 	  for (i=length - 1; i>=0 && x > goalwidth; i--) {
1416 	    x -= FindWidth(tw, x, &block, i, i + 1);
1417 	    position =
1418 	      (*tw->text.source->Scan)(tw->text.source,
1419 					   position,
1420 					   XmSELECT_POSITION,
1421 					   XmsdLeft, 1, True);
1422 	  }
1423 	  return position;
1424 	} else {
1425 	  char tmp_cache[200];
1426 	  wchar_t * tmp_wc;
1427 	  Cardinal tmp_wc_size;
1428 	  char tmp_char[MB_LEN_MAX];
1429 	  int num_chars = 0;
1430 	  XmTextBlockRec mini_block;
1431 
1432 	  /* If 16-bit data, convert the char* to wchar_t*... this
1433 	   * allows us to scan backwards through the text one
1434 	   * character at a time.  Without wchar_t, we would have
1435 	   * to continually scan from the start of the string to
1436 	   * find the byte offset of character n-1.
1437 	   */
1438 	  mini_block.ptr = tmp_char;
1439 	  num_chars = _XmTextCountCharacters(block.ptr, block.length);
1440 	  tmp_wc_size = (num_chars + 1) * sizeof(wchar_t);
1441 	  tmp_wc = (wchar_t *) XmStackAlloc(tmp_wc_size, tmp_cache);
1442 	  num_chars = mbstowcs(tmp_wc, block.ptr, num_chars);
1443 	  if (num_chars > 0) {
1444 	    for (i = num_chars - 1; i >= 0 && x > goalwidth; i--) {
1445 	      mini_block.length = wctomb(mini_block.ptr, tmp_wc[i]);
1446 	      if (mini_block.length < 0) mini_block.length = 0;
1447               x -= FindWidth(tw, x, &mini_block,
1448 			     0, mini_block.length);
1449 	      position =
1450 		(*tw->text.source->Scan)(tw->text.source,
1451 					     position,
1452 					     XmSELECT_POSITION,
1453 					     XmsdLeft, 1, True);
1454 	    }
1455 	  }
1456 	  XmStackFree((char*)tmp_wc, tmp_cache);
1457 	} /* end multi-byte handling */
1458 	return position;
1459       }
1460     }
1461     while (position < nextBreak) {
1462       position = (*tw->text.source->ReadSource)(tw->text.source,
1463 						    position, nextBreak,
1464 						    &block);
1465       length = block.length;
1466       x += FindWidth(tw, x, &block, 0, block.length);
1467     }
1468     lastBreak = nextBreak;
1469     lastX = x;
1470   }
1471   }
1472   lineEnd = (*tw->text.source->Scan)(tw->text.source, lastChar,
1473 					 XmSELECT_LINE, XmsdRight, 1, True);
1474   if (lineEnd != lastChar) return lineEnd;
1475   else return PASTENDPOS;
1476 }
1477 
1478 static XtGeometryResult
1479 TryResize(XmTextWidget tw,
1480 #if NeedWidePrototypes
1481 	  int width,
1482 	  int height)
1483 #else
1484           Dimension width,
1485           Dimension height)
1486 #endif /* NeedWidePrototypes */
1487 {
1488   XtGeometryResult result;
1489   Dimension origwidth = tw->text.inner_widget->core.width;
1490   Dimension origheight = tw->text.inner_widget->core.height;
1491   XtWidgetGeometry request, reply;
1492 
1493   if (origwidth != width) {
1494     request.request_mode = CWWidth;
1495     request.width = width;
1496   } else
1497     request.request_mode = (XtGeometryMask)0;
1498 
1499   if (origheight != height) {
1500     request.request_mode |= CWHeight;
1501     request.height = height;
1502   }
1503 
1504   /* requesting current size */
1505   if (request.request_mode == (XtGeometryMask)0) return XtGeometryNo;
1506 
1507   result = XtMakeGeometryRequest(tw->text.inner_widget, &request, &reply);
1508 
1509   if (result == XtGeometryAlmost) {
1510     if (request.request_mode & CWWidth)
1511       request.width = reply.width;
1512     if (request.request_mode & CWHeight)
1513       request.height = reply.height;
1514 
1515     result = XtMakeGeometryRequest(tw->text.inner_widget, &request,
1516 				   &reply);
1517     if (result == XtGeometryYes) {
1518       result = XtGeometryNo;
1519       if (((request.request_mode & CWWidth) && reply.width != origwidth) ||
1520 	  ((request.request_mode & CWHeight) && reply.height != origheight))
1521 	result = XtGeometryYes;
1522     }
1523     return result;
1524   }
1525 
1526 
1527   if (result == XtGeometryYes) {
1528     /* Some brain damaged geometry managers return XtGeometryYes and
1529        don't change the widget's size. */
1530     if (((request.request_mode & CWWidth) &&
1531 	 tw->text.inner_widget->core.width != width) ||
1532 	((request.request_mode & CWHeight) &&
1533 	 tw->text.inner_widget->core.height != height) ||
1534 	((request.request_mode == (CWWidth & CWHeight)) &&
1535 	 (tw->text.inner_widget->core.width == origwidth &&
1536 	  tw->text.inner_widget->core.height == origheight)))
1537       result = XtGeometryNo;
1538   }
1539   return result;
1540 }
1541 
1542 void
1543 _XmRedisplayHBar(XmTextWidget tw)
1544 {
1545   OutputData data = tw->text.output->data;
1546   int value, sliderSize, maximum, new_sliderSize;
1547   XmNavigatorDataRec nav_data;
1548   XmNavigatorTrait nav_trait;
1549 
1550   if (!(data->scrollhorizontal && XmIsScrolledWindow(XtParent(tw))) ||
1551       data->suspend_hoffset || tw->text.disable_depth != 0 ||
1552       tw->core.being_destroyed || data->hbar == NULL)
1553     return;
1554 
1555   ChangeHOffset(tw, data->hoffset, False); /* Makes sure that hoffset is
1556 						  still reasonable. */
1557 
1558   new_sliderSize = tw->text.inner_widget->core.width
1559     - (data->leftmargin + data->rightmargin);
1560 
1561   if (new_sliderSize < 1) new_sliderSize = 1;
1562   if (new_sliderSize > data->scrollwidth) new_sliderSize = data->scrollwidth;
1563 
1564   nav_data.valueMask = NavValue|NavSliderSize|NavMaximum;
1565   nav_trait = (XmNavigatorTrait)
1566     XmeTraitGet((XtPointer)XtClass(data->hbar), XmQTnavigator);
1567   if (nav_trait) {
1568     nav_trait->getValue(data->hbar, &nav_data);
1569     maximum = nav_data.maximum.x;
1570     sliderSize = nav_data.slider_size.x;
1571     value = nav_data.value.x;
1572 
1573   } else
1574     return;
1575 
1576   if ((maximum != data->scrollwidth ||
1577        value != data->hoffset ||
1578        sliderSize != new_sliderSize) &&
1579       !(sliderSize == maximum && new_sliderSize == data->scrollwidth)) {
1580 
1581     data->ignorehbar = True;
1582 
1583     nav_data.value.x = data->hoffset;
1584     nav_data.minimum.x = 0;
1585     nav_data.maximum.x = data->scrollwidth;
1586     nav_data.slider_size.x = new_sliderSize;
1587     nav_data.increment.x = 0;   /* increments stay at current values */
1588     nav_data.page_increment.x = new_sliderSize;
1589 
1590     nav_data.dimMask = NavigDimensionX;
1591     nav_data.valueMask = NavValue|NavMinimum|NavMaximum|
1592       NavSliderSize|NavIncrement|NavPageIncrement;
1593     _XmSFUpdateNavigatorsValue(XtParent((Widget)tw), &nav_data, True);
1594 
1595     data->ignorehbar = False;
1596   }
1597 }
1598 
1599 
1600 void
1601 _XmRedisplayVBar(XmTextWidget tw)
1602 {
1603   OutputData data = tw->text.output->data;
1604   int value = 0, sliderSize = 0, maximum = 0, new_sliderSize = 0;
1605   XmNavigatorDataRec nav_data;
1606   XmNavigatorTrait nav_trait;
1607 
1608   if (!(data->scrollvertical && XmIsScrolledWindow(XtParent(tw))) ||
1609       data->suspend_voffset || tw->text.disable_depth != 0 ||
1610       tw->core.being_destroyed || data->vbar == NULL)
1611     return;
1612 
1613   ChangeVOffset(tw, data->voffset, False); /* Makes sure that voffset is
1614 						  still reasonable. */
1615 
1616   new_sliderSize = tw->text.inner_widget->core.height
1617     - (data->topmargin + data->bottommargin);
1618 
1619   if (new_sliderSize < 1) new_sliderSize = 1;
1620   if (new_sliderSize > data->scrollheight) new_sliderSize = data->scrollheight;
1621 
1622   nav_data.valueMask = NavValue|NavSliderSize|NavMaximum;
1623   nav_trait = (XmNavigatorTrait)
1624     XmeTraitGet((XtPointer)XtClass(data->vbar), XmQTnavigator);
1625   if (nav_trait) {
1626     nav_trait->getValue(data->vbar, &nav_data);
1627     maximum = nav_data.maximum.y;
1628     sliderSize = nav_data.slider_size.y;
1629     value = nav_data.value.y;
1630 
1631   } else
1632     return;
1633 
1634   if ((maximum != data->scrollheight ||
1635        value != data->voffset ||
1636        sliderSize != new_sliderSize) &&
1637       !(sliderSize == maximum && new_sliderSize == data->scrollheight)) {
1638 
1639     data->ignorehbar = True;
1640 
1641     nav_data.value.y = data->voffset;
1642     nav_data.minimum.y = 0;
1643     nav_data.maximum.y = data->scrollheight;
1644     nav_data.slider_size.y = new_sliderSize;
1645     nav_data.increment.y = 0;   /* increments stay at current values */
1646     nav_data.page_increment.y = new_sliderSize;
1647 
1648     nav_data.dimMask = NavigDimensionY;
1649     nav_data.valueMask = NavValue|NavMinimum|NavMaximum|
1650       NavSliderSize|NavIncrement|NavPageIncrement;
1651     _XmSFUpdateNavigatorsValue(XtParent((Widget)tw), &nav_data, True);
1652 
1653     data->ignorehbar = False;
1654   }
1655 }
1656 
1657 
1658 static int
1659 CountLines(XmTextWidget tw,
1660 	   XmTextPosition start,
1661 	   XmTextPosition end)
1662 {
1663   register XmTextLineTable line_table;
1664   register unsigned int t_index;
1665   register unsigned int max_index = 0;
1666   int numlines = 0;
1667 
1668   line_table = tw->text.line_table;
1669   t_index = tw->text.table_index;
1670 
1671   max_index = tw->text.total_lines - 1;
1672 
1673   /* look forward to find the current record */
1674   if (line_table[t_index].start_pos < (unsigned int) start) {
1675     while (t_index <= max_index &&
1676 	   line_table[t_index].start_pos < (unsigned int) start) t_index++;
1677   } else {
1678     /* look backward to find the current record */
1679     while (t_index &&
1680 	   line_table[t_index].start_pos > (unsigned int) start) t_index--;
1681   }
1682 
1683   while(line_table[t_index].start_pos < (unsigned int) end) {
1684     t_index++;
1685     numlines++;
1686   }
1687 
1688   return (numlines);
1689 }
1690 
1691 void
1692 _XmChangeVSB(XmTextWidget tw)
1693 {
1694   OutputData data = tw->text.output->data;
1695   int local_total;
1696   int new_size;
1697   XmNavigatorDataRec nav_data;
1698 
1699   if (tw->text.disable_depth != 0) return;
1700   if (tw->core.being_destroyed) return;
1701 
1702   if (!tw->text.top_character) tw->text.top_line = 0;
1703   else
1704     tw->text.top_line = _XmTextGetTableIndex(tw, tw->text.top_character);
1705 
1706   if (tw->text.top_line > tw->text.total_lines)
1707     tw->text.top_line = tw->text.total_lines;
1708 
1709   if (tw->text.top_line + tw->text.number_lines >
1710       tw->text.total_lines)
1711     local_total = tw->text.top_line + tw->text.number_lines;
1712   else
1713     local_total = tw->text.total_lines;
1714 
1715   if (data->vbar) {
1716 
1717     if (local_total >= tw->text.number_lines)
1718       new_size = tw->text.number_lines;
1719     else
1720       new_size = local_total;
1721     if (new_size + tw->text.top_line > local_total)
1722       new_size = local_total - tw->text.top_line;
1723 
1724     data->ignorevbar = True;
1725 
1726     nav_data.value.y = tw->text.top_line;
1727     nav_data.minimum.y = 0;
1728     nav_data.maximum.y = local_total;
1729     nav_data.slider_size.y = new_size;
1730     nav_data.increment.y = 0;   /* increments stay at current values */
1731     nav_data.page_increment.y = (data->number_lines > 1)?
1732       (data->number_lines - 1): 1;
1733 
1734     nav_data.dimMask = NavigDimensionY;
1735     nav_data.valueMask = NavValue|NavMinimum|NavMaximum|
1736       NavSliderSize|NavIncrement|NavPageIncrement;
1737     _XmSFUpdateNavigatorsValue(XtParent((Widget)tw), &nav_data, True);
1738 
1739     data->ignorevbar = False;
1740   }
1741 }
1742 
1743 
1744 void
1745 _XmChangeHSB(XmTextWidget tw)
1746 {
1747   OutputData data = tw->text.output->data;
1748   int local_total = 0;
1749   int new_size = 0;
1750   XmNavigatorDataRec nav_data;
1751   int offset = 0;
1752 
1753   if (tw->text.disable_depth != 0) return;
1754   if (tw->core.being_destroyed) return;
1755 
1756   if (!tw->text.top_character) tw->text.top_line = 0;
1757   else
1758     tw->text.top_line = _XmTextGetTableIndex(tw, tw->text.top_character);
1759 
1760   if (tw->text.top_line > tw->text.total_lines)
1761     tw->text.top_line = tw->text.total_lines;
1762 
1763   if (tw->text.top_line + tw->text.number_lines >
1764       tw->text.total_lines)
1765     local_total = tw->text.top_line + tw->text.number_lines;
1766   else
1767     local_total = tw->text.total_lines;
1768 
1769   if (data->hbar) {
1770 
1771     if (local_total >= tw->text.number_lines)
1772       new_size = tw->text.number_lines;
1773     else
1774       new_size = local_total;
1775 
1776     if (new_size + tw->text.top_line > local_total)
1777       new_size = local_total - tw->text.top_line;
1778 
1779     data->ignorehbar = True;
1780 
1781     offset = local_total - (tw->text.number_lines + tw->text.top_line);
1782     nav_data.value.x = tw->text.top_line;
1783     nav_data.minimum.x = 0;
1784     nav_data.maximum.x = local_total;
1785     nav_data.slider_size.x = new_size;
1786     nav_data.increment.x = 0;   /* increments stay at current values */
1787     nav_data.page_increment.x = (data->number_lines > 1)?
1788       (data->number_lines - 1): 1;
1789 
1790     nav_data.dimMask = NavigDimensionX;
1791     nav_data.valueMask = NavValue|NavMinimum|NavMaximum|
1792       NavSliderSize|NavIncrement|NavPageIncrement;
1793     _XmSFUpdateNavigatorsValue(XtParent((Widget)tw), &nav_data, True);
1794 
1795     data->ignorehbar = False;
1796   }
1797 }
1798 
1799 
1800 static void
1801 TextFindNewWidth(XmTextWidget tw,
1802 		 Dimension *widthRtn)
1803 {
1804   OutputData data = tw->text.output->data;
1805   XmTextPosition start;
1806   Dimension newwidth;
1807 
1808   newwidth = 0;
1809 
1810   if(XmDirectionMatch(XmPrim_layout_direction(tw),
1811 		      XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
1812     XmTextPosition first_position = 0;
1813     LineTableExtra extra;
1814 
1815     newwidth = (int)(tw->text.total_lines * data->linewidth) +
1816 		data->leftmargin + data->rightmargin;
1817 
1818     _XmTextLineInfo(tw, (LineNum) 0, &start, &extra);
1819 
1820     if (start > 0) {
1821       first_position = (*tw->text.source->Scan)
1822 	(tw->text.source, start,
1823 	 XmSELECT_ALL, XmsdLeft, 1, True);
1824       if (start > first_position) {
1825 	_XmTextSetTopCharacter((Widget)tw, start);
1826         return;
1827       }
1828     }
1829   } else {
1830 
1831   if (data->resizeheight && tw->text.total_lines > data->number_lines) {
1832     int i;
1833     XmTextPosition linestart, position;
1834     Dimension text_width;
1835     XmTextBlockRec block;
1836 
1837     i = _XmTextGetTableIndex(tw, tw->text.top_character);
1838     for (linestart = tw->text.top_character;
1839 	 i + 1 < tw->text.total_lines; i++) {
1840       text_width = data->leftmargin;
1841       position = tw->text.line_table[i + 1].start_pos - 1;
1842       while (linestart < position) {
1843 	linestart = (*tw->text.source->ReadSource)
1844 	  (tw->text.source, linestart, position, &block);
1845 	text_width += FindWidth(tw, text_width, &block, 0, block.length);
1846       }
1847       text_width += data->rightmargin;
1848       if (text_width > newwidth) newwidth = text_width;
1849     }
1850     text_width = data->leftmargin;
1851     position = tw->text.last_position;
1852     while (linestart < position) {
1853       linestart = (*tw->text.source->ReadSource)
1854 	(tw->text.source, linestart, position, &block);
1855       text_width += FindWidth(tw, text_width, &block, 0, block.length);
1856     }
1857     text_width += data->rightmargin;
1858     if (text_width > newwidth) newwidth = text_width;
1859   } else {
1860     LineNum l;
1861     LineTableExtra extra;
1862 
1863     for (l = 0; l < data->number_lines; l++) {
1864       _XmTextLineInfo(tw, l, &start, &extra);
1865       if (extra && newwidth < extra->width) newwidth = extra->width;
1866     }
1867   }
1868   }
1869 
1870   *widthRtn = newwidth;
1871 }
1872 
1873 
1874 /*ARGSUSED*/
1875 static void
1876 TextFindNewHeight(XmTextWidget tw,
1877 		  XmTextPosition position, /* unused */
1878 		  Dimension *heightRtn)
1879 {
1880   OutputData data = tw->text.output->data;
1881   XmTextPosition first_position, start;
1882   LineTableExtra extra;
1883 
1884   Dimension newheight = 0;
1885 
1886   if(XmDirectionMatch(XmPrim_layout_direction(tw),
1887 		      XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
1888     if (data->resizeheight && tw->text.total_lines > data->number_lines) {
1889       int i;
1890       XmTextPosition linestart, pos;
1891       Dimension text_height;
1892       XmTextBlockRec block;
1893 
1894       i = _XmTextGetTableIndex(tw, tw->text.top_character);
1895       for (linestart = tw->text.top_character;
1896 	   i + 1 < tw->text.total_lines; i++) {
1897 	text_height = data->topmargin;
1898 	pos = tw->text.line_table[i + 1].start_pos - 1;
1899 	while (linestart < pos) {
1900 	  linestart = (*tw->text.source->ReadSource)
1901 	    (tw->text.source, linestart, pos, &block);
1902 	  text_height += FindHeight(tw, text_height, &block, 0, block.length);
1903 	}
1904 	text_height += data->bottommargin;
1905 	if (text_height > newheight) newheight = text_height;
1906       }
1907       text_height = data->topmargin;
1908       pos = tw->text.last_position;
1909       while (linestart < pos) {
1910 	linestart = (*tw->text.source->ReadSource)
1911 	  (tw->text.source, linestart, pos, &block);
1912 	text_height += FindHeight(tw, text_height, &block, 0, block.length);
1913       }
1914       text_height += data->bottommargin;
1915       if (text_height > newheight) newheight = text_height;
1916     } else {
1917       LineNum l;
1918       LineTableExtra extra;
1919 
1920       for (l = 0; l < data->number_lines; l++) {
1921 	_XmTextLineInfo(tw, l, &start, &extra);
1922 	if (extra && newheight < extra->width) newheight = extra->width;
1923       }
1924     }
1925     *heightRtn = newheight;
1926   } else {
1927 
1928   *heightRtn = tw->text.total_lines * data->lineheight +
1929     data->topmargin + data->bottommargin;
1930 
1931   _XmTextLineInfo(tw, (LineNum) 0, &start, &extra);
1932 
1933   if (start > 0) {
1934     first_position = (*tw->text.source->Scan)
1935       (tw->text.source, start,
1936        XmSELECT_ALL, XmsdLeft, 1, True);
1937     if (start > first_position) {
1938       _XmTextSetTopCharacter((Widget)tw, start);
1939       return;
1940     }
1941   }
1942   }
1943 
1944 }
1945 
1946 
1947 static void
1948 CheckForNewSize(XmTextWidget tw,
1949 		XmTextPosition position)
1950 {
1951   OutputData data = tw->text.output->data;
1952   Dimension newwidth, newheight;
1953 
1954   if(XmDirectionMatch(XmPrim_layout_direction(tw),
1955 		      XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
1956     if (data->scrollhorizontal &&
1957 	XmIsScrolledWindow(XtParent(tw)) &&
1958 	!tw->text.hsbar_scrolling)
1959       _XmChangeHSB(tw);
1960   } else {
1961   if (data->scrollvertical &&
1962       XmIsScrolledWindow(XtParent(tw)) &&
1963       !tw->text.vsbar_scrolling)
1964     _XmChangeVSB(tw);
1965   }
1966 
1967 
1968   if (tw->text.in_resize || tw->text.in_expose) {
1969     if(XmDirectionMatch(XmPrim_layout_direction(tw),
1970 			XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
1971       if (data->scrollvertical &&
1972 	  XmIsScrolledWindow(XtParent(tw))) {
1973 	TextFindNewHeight(tw, position, &newheight);
1974 	newheight -= (data->bottommargin + data->topmargin);
1975 	if (newheight != data->scrollheight &&
1976 	    !data->suspend_voffset) {
1977 	  if (newheight) data->scrollheight = newheight;
1978 	  else data->scrollheight = 1;
1979 	  _XmRedisplayVBar(tw);
1980 	}
1981       }
1982     } else {
1983     if (data->scrollhorizontal &&
1984 	XmIsScrolledWindow(XtParent(tw))) {
1985       TextFindNewWidth(tw, &newwidth);
1986       newwidth -= (data->rightmargin + data->leftmargin);
1987       if (newwidth != data->scrollwidth &&
1988 	  !data->suspend_hoffset) {
1989 	if (newwidth) data->scrollwidth = newwidth;
1990 	else data->scrollwidth = 1;
1991 	_XmRedisplayHBar(tw);
1992       }
1993     }
1994     }
1995   } else {
1996     if(XmDirectionMatch(XmPrim_layout_direction(tw),
1997 			XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
1998       if (data->resizeheight  ||
1999 	  (data->scrollvertical &&
2000 	   XmIsScrolledWindow(XtParent(tw))))
2001 	{
2002 	  TextFindNewHeight(tw, position, &newheight);
2003 	  if (data->scrollvertical &&
2004 	      XmIsScrolledWindow(XtParent(tw)))
2005 	    {
2006 	      newheight -= (data->bottommargin + data->topmargin);
2007 	      if (newheight != data->scrollheight &&
2008 		  !data->suspend_voffset) {
2009 	        if (newheight) data->scrollheight = newheight;
2010 	        else data->scrollheight = 1;
2011 	        _XmRedisplayVBar(tw);
2012 	      }
2013 	      newheight = tw->text.inner_widget->core.height;
2014 	    } else if (newheight < data->minheight) newheight = data->minheight;
2015 	} else newheight = tw->text.inner_widget->core.height;
2016 
2017       newwidth = tw->text.inner_widget->core.width;
2018 
2019       if (data->resizewidth) {
2020 	TextFindNewWidth(tw, &newwidth);
2021 	if (newwidth < data->minwidth) newwidth = data->minwidth;
2022       }
2023     } else {
2024     if (data->resizewidth  ||
2025 	(data->scrollhorizontal &&
2026 	 XmIsScrolledWindow(XtParent(tw))))
2027       {
2028 	TextFindNewWidth(tw, &newwidth);
2029 	if (data->scrollhorizontal &&
2030 	    XmIsScrolledWindow(XtParent(tw)))
2031 	  {
2032 	    newwidth -= (data->rightmargin + data->leftmargin);
2033 	    if (newwidth != data->scrollwidth &&
2034 		!data->suspend_hoffset) {
2035 	      if (newwidth) data->scrollwidth = newwidth;
2036 	      else data->scrollwidth = 1;
2037 	      _XmRedisplayHBar(tw);
2038 	    }
2039 	    newwidth = tw->text.inner_widget->core.width;
2040 	  } else if (newwidth < data->minwidth) newwidth = data->minwidth;
2041       } else newwidth = tw->text.inner_widget->core.width;
2042 
2043     newheight = tw->text.inner_widget->core.height;
2044 
2045      if (data->resizeheight
2046        && !(data->scrollvertical &&
2047        XmIsScrolledWindow(XtParent((Widget)tw))) ) {
2048       TextFindNewHeight(tw, position, &newheight);
2049       if (newheight < data->minheight) newheight = data->minheight;
2050     }
2051     }
2052 
2053     if ((newwidth != tw->text.inner_widget->core.width ||
2054 	 newheight != tw->text.inner_widget->core.height)) {
2055       if (tw->text.in_setvalues) {
2056 	tw->core.width = newwidth;
2057 	tw->core.height = newheight;
2058       } else {
2059 	if (TryResize(tw, newwidth, newheight) == XtGeometryYes)
2060 	  NotifyResized((Widget) tw, False);
2061 	else
2062 	  tw->text.needs_refigure_lines = False;
2063       }
2064     }
2065   }
2066 }
2067 
2068 /* ARGSUSED */
2069 static XtPointer
2070 OutputBaseProc(Widget widget,
2071 	       XtPointer client_data)
2072 {
2073   XmTextWidget tw = (XmTextWidget) widget;
2074   XtPointer ret_val;
2075 
2076   _XmProcessLock();
2077   ret_val = (XtPointer) tw->text.output;
2078   _XmProcessUnlock();
2079   return ret_val;
2080 }
2081 
2082 
2083 /* ARGSUSED */
2084 void
2085 _XmTextOutputGetSecResData(XmSecondaryResourceData *secResDataRtn)
2086 {
2087   XmSecondaryResourceData secResData = XtNew(XmSecondaryResourceDataRec);
2088 
2089   _XmTransformSubResources(output_resources, XtNumber(output_resources),
2090 			   &(secResData->resources),
2091 			   &(secResData->num_resources));
2092 
2093   secResData->name = NULL;
2094   secResData->res_class = NULL;
2095   secResData->client_data = NULL;
2096   secResData->base_proc = OutputBaseProc;
2097   *secResDataRtn = secResData;
2098 }
2099 
2100 /*****************************************************************************
2101  * To make TextOut a true "Object" this function should be a class function. *
2102  *****************************************************************************/
2103 int
2104 _XmTextGetNumberLines(XmTextWidget tw)
2105 {
2106   OutputData data = tw->text.output->data;
2107   return (data->number_lines);
2108 }
2109 
2110 /*****************************************************************************
2111  * To make TextOut a true "Object" this function should be a class function. *
2112  *****************************************************************************/
2113 /* This routine is used to control foreground vs. background when moving
2114  * cursor position.  It ensures that when cursor position is changed
2115  * between "inside the selection" and "outside the selection", that the
2116  * correct foreground and background are used when "painting" the cursor
2117  * through the IBeam stencil.
2118  */
2119 void
2120 _XmTextMovingCursorPosition(XmTextWidget	tw,
2121 			    XmTextPosition	position)
2122 {
2123   OutputData data = tw->text.output->data;
2124   _XmHighlightRec 	*hl_list = tw->text.highlight.list;
2125   int			i;
2126 
2127   for (i = tw->text.highlight.number - 1; i >= 0; i--)
2128     if (position >= hl_list[i].position)
2129       break;
2130 
2131   if (position == hl_list[i].position) {
2132     if (data->have_inverted_image_gc)
2133       InvertImageGC(tw);
2134   } else if (hl_list[i].mode != XmHIGHLIGHT_SELECTED) {
2135     if (data->have_inverted_image_gc)
2136       InvertImageGC(tw);
2137   } else if (!data->have_inverted_image_gc) {
2138     InvertImageGC(tw);
2139   }
2140 }
2141 
2142 static Boolean
2143 MeasureLine(XmTextWidget tw,
2144 	    LineNum line,
2145 	    XmTextPosition position,
2146 	    XmTextPosition *nextpos,
2147 	    LineTableExtra *extra)
2148 {
2149   OutputData data = tw->text.output->data;
2150   XmTextPosition temp, last_position;
2151   XmTextBlockRec block;
2152   Dimension width = 0;
2153   Dimension height = 0;
2154 
2155   _XmProcessLock();
2156   posToXYCachedWidget = NULL;
2157   _XmProcessUnlock();
2158   if (extra) *extra = NULL;
2159   if (line >= data->number_lines) {
2160     if (data->resizewidth || data->resizeheight ||
2161 	((data->scrollvertical || data->scrollhorizontal) &&
2162 	 XmIsScrolledWindow(XtParent(tw)))) {
2163       CheckForNewSize(tw, position);
2164     }
2165     return(False);
2166   }
2167   if (nextpos) {
2168     if (position == PASTENDPOS) {
2169       *nextpos = last_position = PASTENDPOS;
2170     } else {
2171       if (ShouldWordWrap(data, tw)) {
2172 	*nextpos = _XmTextFindLineEnd(tw, position, extra);
2173       } else {
2174 	last_position = (*tw->text.source->Scan)
2175 	  (tw->text.source,
2176 	   position, XmSELECT_LINE,
2177 	   XmsdRight, 1, False);
2178 	*nextpos = (*tw->text.source->Scan)(tw->text.source,
2179 						last_position, XmSELECT_LINE,
2180 						XmsdRight, 1, True);
2181 	if (*nextpos == last_position)
2182 	  *nextpos = PASTENDPOS;
2183 
2184 	if(XmDirectionMatch(XmPrim_layout_direction(tw),
2185 			    XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
2186 	  if (extra && (data->resizeheight ||
2187 		        (data->scrollvertical &&
2188 		         XmIsScrolledWindow(XtParent(tw))))) {
2189 	    (*extra) = (LineTableExtra)
2190 	      XtMalloc((unsigned) sizeof(LineTableExtraRec));
2191 	    (*extra)->wrappedbychar = False;
2192 	    height = data->topmargin;
2193 	    temp = position;
2194 	    while (temp < last_position) {
2195 	      temp = (*tw->text.source->ReadSource)
2196 		(tw->text.source, temp, last_position, &block);
2197 	      height += FindHeight(tw, (Position) width, &block,
2198 			           0, block.length);
2199 	    }
2200 	    (*extra)->width = height + data->bottommargin;
2201 	  }
2202 	} else {
2203 	if (extra && (data->resizewidth ||
2204 		      (data->scrollhorizontal &&
2205 		       XmIsScrolledWindow(XtParent(tw))))) {
2206 	  (*extra) = (LineTableExtra)
2207 	    XtMalloc((unsigned) sizeof(LineTableExtraRec));
2208 	  (*extra)->wrappedbychar = False;
2209 	  width = data->leftmargin;
2210 	  temp = position;
2211 	  while (temp < last_position) {
2212 	    temp = (*tw->text.source->ReadSource)
2213 	      (tw->text.source, temp, last_position, &block);
2214 	    width += FindWidth(tw, (Position) width, &block,
2215 			       0, block.length);
2216 	  }
2217 	  (*extra)->width = width + data->rightmargin;
2218 	}
2219         }
2220       }
2221       if (*nextpos == position)
2222 	*nextpos = (*tw->text.source->Scan)(tw->text.source,
2223 						position, XmSELECT_POSITION,
2224 						XmsdRight, 1, True);
2225     }
2226   }
2227   return (True);
2228 }
2229 
2230 
2231 static Boolean
2232 _FontStructPerCharExtents(XmTextWidget tw,
2233 			  char *str,
2234 			  int length,
2235 			  XCharStruct *overall)
2236 {
2237   OutputData data = tw->text.output->data;
2238   XFontStruct *font = data->font;
2239   unsigned char c;
2240   int dummy;
2241 
2242   memset((char *)overall, 0x00, sizeof(XCharStruct));
2243 
2244   if(data->use_fontset)
2245     return False;
2246 
2247   if(length <= 0 || str == (char *) NULL)
2248     return True;
2249 
2250   if(tw->text.char_size != 1) {
2251     if(length == 1) {
2252       c = (unsigned char) *str;
2253       if(c == '\t') {
2254 	return True;
2255       } else {
2256 	if(font->per_char && (c >= font->min_char_or_byte2 &&
2257 			      c <= font->max_char_or_byte2)) {
2258 	  overall->lbearing =
2259 			font->per_char[c - font->min_char_or_byte2].lbearing;
2260 	  overall->rbearing =
2261 			font->per_char[c - font->min_char_or_byte2].rbearing;
2262 	  overall->width = font->per_char[c - font->min_char_or_byte2].width;
2263 	} else {
2264 	  overall->lbearing = font->min_bounds.lbearing;
2265 	  overall->rbearing = font->min_bounds.rbearing;
2266 	  overall->width = font->min_bounds.width;
2267 	}
2268 	overall->ascent = font->max_bounds.ascent;
2269 	overall->descent = font->max_bounds.descent;
2270       }
2271     } else {
2272       if (_XmIsISO10646(XtDisplay(tw), data->font)) {
2273         size_t ucsstr_len = 0;
2274         XChar2b *ucsstr = _XmUtf8ToUcs2(str, length, &ucsstr_len);
2275         XTextExtents16(data->font, ucsstr, ucsstr_len,
2276 			&dummy, &dummy, &dummy, overall);
2277         XFree(ucsstr);
2278       } else
2279         XTextExtents(data->font, str, length, &dummy, &dummy, &dummy, overall);
2280     }
2281   } else {
2282     c = (unsigned char) *str;
2283     if(c == '\t') {
2284       return True;
2285     } else {
2286       if(font->per_char) {
2287 	if(c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2) {
2288 	  overall->lbearing =
2289 			font->per_char[c - font->min_char_or_byte2].lbearing;
2290 	  overall->rbearing =
2291 			font->per_char[c - font->min_char_or_byte2].rbearing;
2292 	  overall->width = font->per_char[c - font->min_char_or_byte2].width;
2293 	} else if (font->default_char >= font->min_char_or_byte2 &&
2294 		 font->default_char <= font->max_char_or_byte2) {
2295 	  overall->lbearing = font->per_char[font->default_char -
2296 					     font->min_char_or_byte2].lbearing;
2297 	  overall->rbearing = font->per_char[font->default_char -
2298 					     font->min_char_or_byte2].rbearing;
2299 	  overall->width = font->per_char[font->default_char -
2300 					  font->min_char_or_byte2].width;
2301 	} else {
2302 	  overall->lbearing = font->min_bounds.lbearing;
2303 	  overall->rbearing = font->min_bounds.rbearing;
2304 	  overall->width = font->min_bounds.width;
2305 	}
2306       } else {
2307 	overall->lbearing = font->min_bounds.lbearing;
2308 	overall->rbearing = font->min_bounds.rbearing;
2309 	overall->width = font->min_bounds.width;
2310       }
2311       overall->ascent = font->max_bounds.ascent;
2312       overall->descent = font->max_bounds.descent;
2313     }
2314   }
2315   return True;;
2316 }
2317 
2318 
2319 static void
2320 Draw(XmTextWidget tw,
2321      LineNum line,
2322      XmTextPosition start,
2323      XmTextPosition end,
2324      XmHighlightMode highlight)
2325 {
2326   OutputData data = tw->text.output->data;
2327   XmTextPosition linestart, nextlinestart;
2328   LineTableExtra extra;
2329   XmTextBlockRec block;
2330   int x, y, length, newx, i;
2331   int num_bytes = 0;
2332   int text_border;
2333   int rightedge = (((int)tw->text.inner_widget->core.width) -
2334 		   data->rightmargin) + data->hoffset;
2335   Boolean stipple = False;
2336 
2337   int width, height;
2338   int rec_width = 0;
2339   int rec_height = 0;
2340   Boolean cleartoend, cleartobottom;
2341   XmHighlightMode endhighlight = highlight;
2342   int bottomedge = (((int)tw->text.inner_widget->core.height) -
2343 		     data->bottommargin) + data->voffset;
2344   int win_width = 0;
2345   int newy = 0;
2346   int charheight = data->font_ascent + data->font_descent;
2347 
2348   if (!XtIsRealized((Widget) tw)) return;
2349   _XmTextLineInfo(tw, line+1, &nextlinestart, &extra);
2350   _XmTextLineInfo(tw, line, &linestart, &extra);
2351 
2352   _XmTextAdjustGC(tw);
2353 
2354   if (!XtIsSensitive((Widget)tw)) stipple = True;
2355 
2356   if (linestart == PASTENDPOS) {
2357     start = end = nextlinestart = PASTENDPOS;
2358     cleartoend = cleartobottom = True;
2359   } else if (nextlinestart == PASTENDPOS) {
2360     nextlinestart = (*tw->text.source->Scan)(tw->text.source, 0,
2361 						 XmSELECT_ALL, XmsdRight, 1,
2362 						 False);
2363     cleartoend = cleartobottom = (end >= nextlinestart);
2364     if (start >= nextlinestart)
2365       endhighlight = highlight = XmHIGHLIGHT_NORMAL;
2366     else if (cleartoend)
2367       endhighlight = XmHIGHLIGHT_NORMAL;
2368   } else {
2369     cleartobottom = False;
2370     cleartoend = (end >= nextlinestart);
2371     if (cleartoend && (!extra || !extra->wrappedbychar))
2372       end = (*tw->text.source->Scan)(tw->text.source, nextlinestart,
2373 					 XmSELECT_POSITION, XmsdLeft, 1, True);
2374   }
2375   if (XmDirectionMatch(XmPrim_layout_direction(tw),
2376 		       XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
2377     y = data->topmargin;
2378     x = tw->text.inner_widget->core.width -
2379 	(data->rightmargin + line * data->linewidth +
2380 	 (int)(data->linewidth * 0.5));
2381     while (linestart < start && x <= rightedge) {
2382       linestart = (*tw->text.source->ReadSource)(tw->text.source,
2383 						 linestart, start, &block);
2384       y += FindHeight(tw, y, &block, 0, block.length);
2385     }
2386   } else {
2387     y = data->topmargin + line * data->lineheight + data->font_ascent;
2388     x = data->leftmargin;
2389     while (linestart < start && x <= rightedge) {
2390       linestart = (*tw->text.source->ReadSource)(tw->text.source,
2391 						   linestart, start, &block);
2392       x += FindWidth(tw, x, &block, 0, block.length);
2393     }
2394   }
2395 
2396   if(XmDirectionMatch(XmPrim_layout_direction(tw),
2397 		      XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
2398     XOrientation orient = 0;
2399     newy = y;
2400 
2401     if(data->use_fontset == True) {
2402       XGetOCValues((XOC)data->font, XNOrientation, &orient, NULL);
2403       SetXOCOrientation(tw, (XOC)data->font, XOMOrientation_TTB_RTL);
2404     }
2405     while (start < end && y <= bottomedge) {
2406       start = (*tw->text.source->ReadSource)(tw->text.source, start,
2407 					     end, &block);
2408       if ((int)tw->text.char_size == 1) num_bytes = 1;
2409       else {
2410 	num_bytes = mblen(block.ptr, (int)tw->text.char_size);
2411 	if (num_bytes < 1) num_bytes = 1;
2412       }
2413       while (block.length > 0) {
2414 	while (num_bytes == 1 && block.ptr[0] == '\t') {
2415 	  newy = y;
2416 	  while (block.length > 0 && num_bytes == 1 &&
2417 	         newy - data->voffset < data->topmargin) {
2418 	    height = FindHeight(tw, newy, &block, 0, 1);
2419 	    newy += height;
2420 
2421 	    if (newy - data->voffset < data->topmargin) {
2422 	      block.length--;
2423 	      block.ptr++;
2424 	      y = newy;
2425 	      if ((int)tw->text.char_size != 1) {
2426 		/* check if we've got mbyte char */
2427 		num_bytes = mblen(block.ptr,
2428 				  (int)tw->text.char_size);
2429 		if (num_bytes < 1) num_bytes = 1;
2430 	      }
2431 	    }
2432 	  }
2433 	  if (block.length <= 0 || num_bytes != 1 ||
2434 	      block.ptr[0] != '\t') break;
2435 
2436 	  height = FindHeight(tw, y, &block, 0, 1);
2437 
2438 	  if (highlight == XmHIGHLIGHT_SELECTED)
2439 	    SetNormGC(tw, data->gc, False, False);
2440 	  else
2441 	    SetInvGC(tw, data->gc);
2442 	  SetFullGC(tw, data->gc);
2443 
2444 	  if (((y - data->voffset) + height) >
2445 	      (int)(tw->text.inner_widget->core.height - data->bottommargin))
2446 	    rec_height = (tw->text.inner_widget->core.height -
2447 		          data->bottommargin) - (y - data->voffset);
2448 	  else
2449 	    rec_height = height;
2450 
2451 	  if (x - (int)(data->linewidth * 0.5) < data->leftmargin)
2452 	    rec_width = (tw->text.inner_widget->core.width -
2453 			 data->rightmargin) - x;
2454 	  else
2455 	    rec_width = data->linewidth;
2456 
2457 	  XFillRectangle(XtDisplay(tw),
2458 		         XtWindow(tw->text.inner_widget), data->gc,
2459 		         x - (data->linewidth * 0.5), y - data->voffset,
2460 		         rec_width, rec_height);
2461 
2462 	  SetMarginGC(tw, data->gc);
2463 	  if (highlight == XmHIGHLIGHT_SECONDARY_SELECTED) {
2464 
2465 	    if (highlight == XmHIGHLIGHT_SELECTED)
2466 	      SetInvGC(tw, data->gc);
2467 	    else
2468 	      SetNormGC(tw, data->gc, False, False);
2469 
2470 	    XDrawLine(XtDisplay(tw),
2471 		      XtWindow(tw->text.inner_widget), data->gc,
2472 		      x + (int)(data->linewidth * 0.5) - 1, y - data->voffset,
2473 		      (int)(x + data->linewidth * 0.5) - 1,
2474 		      ((y - data->voffset) + height) - 1);
2475 	  }
2476 	  y += height;
2477 
2478 
2479 	  block.length--;
2480 	  block.ptr++;
2481 	  if ((int)tw->text.char_size != 1) {
2482 	    num_bytes = mblen(block.ptr, (int)tw->text.char_size);
2483 	    /* crummy error handling, but ... */
2484 	    if (num_bytes < 0) num_bytes = 1;
2485 	  }
2486 	  if (block.length <= 0) break;
2487         }
2488         if ((int)tw->text.char_size == 1) {
2489 	  for (length = 0; length < block.length; length++) {
2490 	    if (block.ptr[length] == '\t') break;
2491 	  }
2492         } else {
2493 	  for (length = 0, num_bytes = mblen(block.ptr,
2494 					     (int)tw->text.char_size);
2495 	       length < block.length;
2496 	       num_bytes = mblen(&block.ptr[length],
2497 			         (int)tw->text.char_size)) {
2498 	    if ((num_bytes == 1) && block.ptr[length] == '\t') break;
2499 	    if (num_bytes == 0) break;
2500 	    if (num_bytes < 0) num_bytes = 1;
2501 	    length += num_bytes;
2502 	  }
2503         }
2504         if (length <= 0) break;
2505         newy = y;
2506         while (length > 0 && newy + charheight < data->topmargin) {
2507 	  newy += FindHeight(tw, newy, &block, 0, 1);
2508 	  if ((int)tw->text.char_size == 1) {
2509 	    if (newy + charheight < data->topmargin) {
2510 	      length--;
2511 	      block.length--;
2512 	      block.ptr++;
2513 	      y = newy;
2514 	    }
2515 	  } else {
2516 	    if (newy + charheight < data->topmargin) {
2517 	      num_bytes = mblen(block.ptr, (int)tw->text.char_size);
2518 	      if (num_bytes < 0) num_bytes = 1;
2519 	      length -= num_bytes;
2520 	      block.length -= num_bytes;
2521 	      block.ptr += num_bytes;
2522 	      y = newy;
2523 	    }
2524 	  }
2525         }
2526         if (length == 0) continue;
2527         newy = y + FindHeight(tw, y, &block, 0, length);
2528         if (newy > bottomedge) {
2529 	  newy = y;
2530 	  if ((int)tw->text.char_size == 1) {
2531 	    for (i=0; i < length && (newy - data->voffset) <= bottomedge; i++) {
2532 	      newy += FindHeight(tw, newy, &block, i, i+1);
2533 	    }
2534 	  } else {
2535 	    for (i=0, num_bytes = mblen(block.ptr, (int)tw->text.char_size);
2536 	         i < length && (newy - data->voffset) <= bottomedge &&
2537 		 num_bytes > 0;
2538 	         i += num_bytes, num_bytes = mblen(&block.ptr[i],
2539 						   (int)tw->text.char_size))
2540 	      newy += FindHeight(tw, newy, &block, i, i + num_bytes);
2541 	  }
2542 	  length = i;
2543 	  start = end; /* Force a break out of the outer loop. */
2544 	  block.length = length; /* ... and out of the inner loop. */
2545         }
2546         if (highlight == XmHIGHLIGHT_SELECTED) {
2547 	  /* Draw the inverse background, then draw the text over it */
2548 	  SetNormGC(tw, data->gc, False, False);
2549 	  SetFullGC(tw, data->gc);
2550 
2551 	  if (((y - data->voffset) + (newy - y)) >
2552 	      (int) tw->text.inner_widget->core.height - data->bottommargin)
2553 	    rec_height = tw->text.inner_widget->core.height -
2554 	      (y - data->voffset) - data->bottommargin;
2555 	  else
2556 	    rec_height = newy - y;
2557 
2558 	  if (x + (int)(data->linewidth * 0.5) < data->leftmargin)
2559 	    rec_width = x + (tw->text.inner_widget->core.width -
2560 			 data->rightmargin);
2561 	  else
2562 	    rec_width = data->linewidth;
2563 
2564 	  XFillRectangle(XtDisplay(tw),
2565 		         XtWindow(tw->text.inner_widget),
2566 		         data->gc, x - (int)(data->linewidth * 0.5),
2567 		         y - data->voffset, rec_width, rec_height);
2568 
2569 	  SetInvGC(tw, data->gc);
2570 	  SetMarginGC(tw, data->gc);
2571 	  if (data->use_fontset) {
2572 	    XmbDrawString(XtDisplay(tw),
2573 			  XtWindow(tw->text.inner_widget),
2574 			  (XFontSet) data->font, data->gc,
2575 			  x, y - data->voffset, block.ptr, length);
2576 #ifdef USE_XFT
2577 	  } else if (data->use_xft) {
2578 	    _XmXftDrawString2(XtDisplay(tw), XtWindow(tw->text.inner_widget),
2579 			      data->gc, (XftFont*) data->font, 1,
2580 			      x, y - data->voffset, block.ptr, length);
2581 #endif
2582 	  } else {
2583 	    int len = 0, csize = 0, wx = 0, orig_x = 0, orig_y = 0;
2584 	    char *p = NULL;
2585 	    XCharStruct overall;
2586 
2587 	    wx = x - data->hoffset;
2588 	    orig_y = y - data->voffset;
2589 	    for(len = length, p = block.ptr ; len > 0 && p ;
2590 		len-= csize, p += csize) {
2591 	      csize = mblen(p, (int)tw->text.char_size);
2592 
2593 	      _FontStructPerCharExtents(tw, p, csize, &overall);
2594 
2595 	      orig_x = wx - (int)((overall.rbearing - overall.lbearing) >> 1) -
2596 		       overall.lbearing;
2597 	      orig_y += overall.ascent;
2598 	      if (_XmIsISO10646(XtDisplay(tw), data->font)) {
2599 	        size_t ucsstr_len = 0;
2600 		XChar2b *ucsstr = _XmUtf8ToUcs2(p, csize, &ucsstr_len);
2601 		XDrawString16(XtDisplay(tw), XtWindow(tw->text.inner_widget),
2602 				data->gc, orig_x, orig_y, ucsstr, ucsstr_len);
2603 		XFree(ucsstr);
2604 	      } else
2605 		XDrawString(XtDisplay(tw),
2606 			  XtWindow(tw->text.inner_widget), data->gc,
2607 			  orig_x, orig_y, p, csize);
2608 
2609 	      orig_y += overall.descent;
2610 	    }
2611 	  }
2612         } else {
2613 	  SetInvGC(tw, data->gc);
2614 	  if (newy > y) {
2615 	    if (x + (int)(data->linewidth * 0.5) < data->leftmargin)
2616 	      rec_width = x + (tw->text.inner_widget->core.width -
2617 			       data->rightmargin);
2618 	    else
2619 	      rec_width = data->linewidth;
2620 
2621 	    XFillRectangle(XtDisplay(tw),
2622 			   XtWindow(tw->text.inner_widget),
2623 			   data->gc, x - (int)(data->linewidth * 0.5),
2624 			   y - data->voffset, rec_width, newy - y);
2625 	  }
2626 	  SetNormGC(tw, data->gc, True, stipple);
2627 	  if (data->use_fontset) {
2628 	    int wx, wy;
2629 
2630 	    wx = x - data->hoffset;
2631 #ifdef FIX_1381
2632 	    if (stipple)
2633 	      {
2634 	        /*Draw shadow for insensitive text*/
2635 	        SetShadowGC(tw, data->gc);
2636 	        XmbDrawString(XtDisplay(tw),
2637 	        XtWindow(tw->text.inner_widget),
2638 	        (XFontSet) data->font, data->gc,
2639 	        wx+1, y - data->voffset+1, block.ptr, length);
2640 	        SetNormGC(tw, data->gc, True, stipple);
2641 	      }
2642 #endif
2643 
2644 	    XmbDrawString(XtDisplay(tw),
2645 			  XtWindow(tw->text.inner_widget),
2646 			  (XFontSet) data->font, data->gc,
2647 			  wx, y - data->voffset, block.ptr, length);
2648 #ifdef USE_XFT
2649 	  } else if (data->use_xft) {
2650 #ifdef FIX_1381
2651 	    if (stipple)
2652 	      {
2653 	        /*Draw shadow for insensitive text*/
2654 	        SetShadowGC(tw, data->gc);
2655 	        _XmXftDrawString2(XtDisplay(tw), XtWindow(tw->text.inner_widget),
2656 			  data->gc, (XftFont*) data->font, 1,
2657 			  x - data->hoffset+1, y - data->voffset+1,
2658 			  block.ptr, length);
2659 	        SetNormGC(tw, data->gc, True, stipple);
2660 	      }
2661 #endif
2662 
2663 	    _XmXftDrawString2(XtDisplay(tw), XtWindow(tw->text.inner_widget),
2664 			      data->gc, (XftFont*) data->font, 1,
2665 			      x - data->hoffset, y - data->voffset,
2666 			      block.ptr, length);
2667 #endif
2668 	  } else {
2669 	    int len = 0, csize = 0, wx = 0, orig_x = 0, orig_y = 0;
2670 	    char *p = NULL;
2671 	    XCharStruct overall;
2672 	    wx = x - data->hoffset;
2673 	    orig_y = y - data->voffset;
2674 	    for(len = length, p = block.ptr ; len > 0 && p ;
2675 		len-= csize, p += csize) {
2676 	      csize = mblen(p, (int)tw->text.char_size);
2677 
2678 	      _FontStructPerCharExtents(tw, p, csize, &overall);
2679 	      orig_x = wx - (int)((overall.rbearing - overall.lbearing) >> 1) -
2680 		       overall.lbearing;
2681 	      orig_y += overall.ascent;
2682 	      if (_XmIsISO10646(XtDisplay(tw), data->font)) {
2683 	        size_t ucsstr_len = 0;
2684 		XChar2b *ucsstr = _XmUtf8ToUcs2(p, csize, &ucsstr_len);
2685 #ifdef FIX_1381
2686 		if (stipple)
2687 		{
2688 		  /*Draw shadow for insensitive text*/
2689 		  SetShadowGC(tw, data->gc);
2690 		  XDrawString16(XtDisplay(tw), XtWindow(tw->text.inner_widget),
2691 		  		data->gc, orig_x+1, orig_y+1, ucsstr, ucsstr_len);
2692 		  SetNormGC(tw, data->gc, True, stipple);
2693 		}
2694 #endif
2695 		XDrawString16(XtDisplay(tw), XtWindow(tw->text.inner_widget),
2696 				data->gc, orig_x, orig_y, ucsstr, ucsstr_len);
2697 		XFree(ucsstr);
2698 	      } else {
2699 #ifdef FIX_1381
2700 		if (stipple)
2701 		{
2702 		  /*Draw shadow for insensitive text*/
2703 		  SetShadowGC(tw, data->gc);
2704 		  XDrawString(XtDisplay(tw),
2705 		  		XtWindow(tw->text.inner_widget), data->gc,
2706 		  		orig_x+1, orig_y+1, p, csize);
2707 		  SetNormGC(tw, data->gc, True, stipple);
2708 		}
2709 #endif
2710 	      XDrawString(XtDisplay(tw),
2711 			  XtWindow(tw->text.inner_widget), data->gc,
2712 			  orig_x, orig_y, p, csize);
2713 	      }
2714 	      orig_y += overall.descent;
2715 	    }
2716 	  }
2717 	  if (stipple) SetNormGC(tw, data->gc, True, !stipple);
2718         }
2719         if (highlight == XmHIGHLIGHT_SECONDARY_SELECTED)
2720 	  XDrawLine(XtDisplay(tw), XtWindow(tw->text.inner_widget),
2721 		    data->gc, x + (int)(data->linewidth * 0.5) - 1,
2722 		    y - data->voffset,
2723 		    x + (int)(data->linewidth * 0.5) - 1,
2724 		    (newy - data->voffset) - 1);
2725         y = newy;
2726         block.length -= length;
2727         block.ptr += length;
2728         if ((int)tw->text.char_size != 1) {
2729 	  num_bytes = mblen(block.ptr, (int)tw->text.char_size);
2730 	  if (num_bytes < 1) num_bytes = 1;
2731         }
2732       }
2733     }
2734     if(data->use_fontset == True) {
2735       SetXOCOrientation(tw, (XOC)data->font, orient);
2736     }
2737   } else {
2738 
2739   newx = x;
2740   while (start < end && x <= rightedge) {
2741     start = (*tw->text.source->ReadSource)(tw->text.source, start,
2742 					       end, &block);
2743     if ((int)tw->text.char_size == 1) num_bytes = 1;
2744     else {
2745 #ifndef NO_MULTIBYTE
2746       num_bytes = mblen(block.ptr, (int)tw->text.char_size);
2747       if (num_bytes < 1) num_bytes = 1;
2748 #else
2749       num_bytes = 1;
2750 #endif
2751     }
2752     while (block.length > 0) {
2753       while (num_bytes == 1 && block.ptr[0] == '\t') {
2754 	newx = x;
2755 	while (block.length > 0 && num_bytes == 1 &&
2756 	       newx - data->hoffset < data->leftmargin) {
2757 	  width = FindWidth(tw, newx, &block, 0, 1);
2758 	  newx += width;
2759 
2760 	  if (newx - data->hoffset < data->leftmargin) {
2761 	    block.length--;
2762 	    block.ptr++;
2763 	    x = newx;
2764 	    if ((int)tw->text.char_size != 1) {
2765 	      /* check if we've got mbyte char */
2766 #ifndef NO_MULTIBYTE
2767 	      num_bytes = mblen(block.ptr, (int)tw->text.char_size);
2768 	      if (num_bytes < 1) num_bytes = 1;
2769 #else
2770 	      num_bytes = 1;
2771 #endif
2772 	    }
2773 	  }
2774 	}
2775 	if (block.length <= 0 || num_bytes != 1 ||
2776 	    block.ptr[0] != '\t') break;
2777 
2778 	width = FindWidth(tw, x, &block, 0, 1);
2779 
2780 	if (highlight == XmHIGHLIGHT_SELECTED)
2781 	  SetNormGC(tw, data->gc, False, False);
2782 	else
2783 	  SetInvGC(tw, data->gc);
2784 	SetFullGC(tw, data->gc);
2785 
2786 	if ((int) ((x - data->hoffset) + width) >
2787 	    (int) (tw->text.inner_widget->core.width - data->rightmargin))
2788 	  rec_width = (tw->text.inner_widget->core.width -
2789 		       data->rightmargin) - (x - data->hoffset);
2790 	else
2791 	  rec_width = width;
2792 
2793 	if ((int) (y + data->font_descent) >
2794 	    (int) (tw->text.inner_widget->core.height - data->bottommargin))
2795 	  rec_height = (tw->text.inner_widget->core.height -
2796 			data->bottommargin) - y;
2797 	else
2798 	  rec_height = data->font_ascent + data->font_descent;
2799 
2800 	XFillRectangle(XtDisplay(tw),
2801 		       XtWindow(tw->text.inner_widget), data->gc,
2802 		       x - data->hoffset, y - data->font_ascent,
2803 		       rec_width, rec_height);
2804 
2805 	SetMarginGC(tw, data->gc);
2806 	if (highlight == XmHIGHLIGHT_SECONDARY_SELECTED) {
2807 
2808 	  if (highlight == XmHIGHLIGHT_SELECTED)
2809 	    SetInvGC(tw, data->gc);
2810 	  else
2811 	    SetNormGC(tw, data->gc, False, False);
2812 
2813 	  XDrawLine(XtDisplay(tw),
2814 		    XtWindow(tw->text.inner_widget), data->gc,
2815 		    x - data->hoffset, y,
2816 		    ((x - data->hoffset) + width) - 1, y);
2817 	}
2818 	x += width;
2819 
2820 
2821 	block.length--;
2822 	block.ptr++;
2823 	if ((int)tw->text.char_size != 1) {
2824 #ifndef NO_MULTIBYTE
2825 	  num_bytes = mblen(block.ptr, (int)tw->text.char_size);
2826 	  /* crummy error handling, but ... */
2827 	  if (num_bytes < 0) num_bytes = 1;
2828 #else
2829 	  num_bytes = *block.ptr ? 1 : 0;
2830 #endif
2831 	}
2832 	if (block.length <= 0) break;
2833       }
2834       if ((int)tw->text.char_size == 1) {
2835 	for (length = 0; length < block.length; length++) {
2836 	  if (block.ptr[length] == '\t') break;
2837 	}
2838       } else {
2839 	for (length = 0,
2840 #ifndef NO_MULTIBYTE
2841              num_bytes = mblen(block.ptr, (int)tw->text.char_size);
2842 #else
2843 	     num_bytes = *block.ptr ? 1 : 0;
2844 #endif
2845 	     length < block.length;
2846 #ifndef NO_MULTIBYTE
2847 	     num_bytes = mblen(&block.ptr[length], (int)tw->text.char_size)) {
2848 #else
2849 	     num_bytes = block.ptr[length] ? 1 : 0) {
2850 #endif
2851 	  if ((num_bytes == 1) && block.ptr[length] == '\t') break;
2852 	  if (num_bytes == 0) break;
2853 	  if (num_bytes < 0) num_bytes = 1;
2854 	  length += num_bytes;
2855 	}
2856       }
2857       if (length <= 0) break;
2858       newx = x;
2859       while (length > 0 && newx - data->hoffset < data->leftmargin) {
2860 	newx += FindWidth(tw, newx, &block, 0, 1);
2861 	if ((int)tw->text.char_size == 1) {
2862 	  if (newx - data->hoffset < data->leftmargin) {
2863 	    length--;
2864 	    block.length--;
2865 	    block.ptr++;
2866 	    x = newx;
2867 	  }
2868 	} else {
2869 	  if (newx - data->hoffset < data->leftmargin) {
2870 #ifndef NO_MULTIBYTE
2871 	    num_bytes = mblen(block.ptr, (int)tw->text.char_size);
2872 	    if (num_bytes < 0) num_bytes = 1;
2873 #else
2874 	    num_bytes = *block.ptr ? 1 : 0;
2875 #endif
2876 	    length -= num_bytes;
2877 	    block.length -= num_bytes;
2878 	    block.ptr += num_bytes;
2879 	    x = newx;
2880 	  }
2881 	}
2882       }
2883       if (length == 0) continue;
2884       newx = x + FindWidth(tw, x, &block, 0, length);
2885       if (newx > rightedge) {
2886 	newx = x;
2887 	if ((int)tw->text.char_size == 1) {
2888 	  for (i=0; i < length && newx <= rightedge; i++) {
2889 	    newx += FindWidth(tw, newx, &block, i, i+1);
2890 	  }
2891 	} else {
2892 	  for (i=0,
2893 #ifndef NO_MULTIBYTE
2894 	       num_bytes = mblen(block.ptr, (int)tw->text.char_size);
2895 #else
2896 	       num_bytes = *block.ptr ? 1 : 0;
2897 #endif
2898 	       i < length && newx <= rightedge && num_bytes > 0;
2899 	       i += num_bytes,
2900 #ifndef NO_MULTIBYTE
2901 	       num_bytes = mblen(&block.ptr[i], (int)tw->text.char_size))
2902 #else
2903 	       num_bytes = block.ptr[i] ? 1 : 0)
2904 #endif
2905 	    newx += FindWidth(tw, newx, &block, i, i + num_bytes);
2906 	}
2907 	length = i;
2908 	start = end; /* Force a break out of the outer loop. */
2909 	block.length = length; /* ... and out of the inner loop. */
2910       }
2911       if (highlight == XmHIGHLIGHT_SELECTED) {
2912 	/* Draw the inverse background, then draw the text over it */
2913 	SetNormGC(tw, data->gc, False, False);
2914 	SetFullGC(tw, data->gc);
2915 
2916 	if ((int) ((x - data->hoffset) + (newx - x)) >
2917 	    (int) (tw->text.inner_widget->core.width - data->rightmargin))
2918 	  rec_width = tw->text.inner_widget->core.width -
2919 	    (x - data->hoffset) - data->rightmargin;
2920 	else
2921 	  rec_width = newx - x;
2922 
2923 	if ((int) (y + data->font_descent) >
2924 	    (int) (tw->text.inner_widget->core.height - data->bottommargin))
2925 	  rec_height = (tw->text.inner_widget->core.height -
2926 			data->bottommargin) - (y - data->font_ascent);
2927 	else
2928 	  rec_height = data->font_ascent + data->font_descent;
2929 
2930 	XFillRectangle(XtDisplay(tw),
2931 		       XtWindow(tw->text.inner_widget),
2932 		       data->gc, x - data->hoffset,
2933 		       y - data->font_ascent, rec_width, rec_height);
2934 
2935 	SetInvGC(tw, data->gc);
2936 	SetMarginGC(tw, data->gc);
2937 	if (data->use_fontset) {
2938 	  XmbDrawString(XtDisplay(tw),
2939 			XtWindow(tw->text.inner_widget),
2940 			(XFontSet) data->font, data->gc,
2941 			x - data->hoffset, y, block.ptr, length);
2942 #ifdef USE_XFT
2943 	} else if (data->use_xft) {
2944 	  _XmXftDrawString2(XtDisplay(tw), XtWindow(tw->text.inner_widget),
2945 			    data->gc, (XftFont*) data->font, 1,
2946 			    x - data->hoffset, y, block.ptr, length);
2947 #endif
2948 	} else {
2949 	  if (_XmIsISO10646(XtDisplay(tw), data->font)) {
2950 	    size_t ucsstr_len = 0;
2951 	    XChar2b *ucsstr = _XmUtf8ToUcs2(block.ptr, length, &ucsstr_len);
2952 	    XDrawString16(XtDisplay(tw), XtWindow(tw->text.inner_widget),
2953 				data->gc, x - data->hoffset, y, ucsstr,
2954 				ucsstr_len);
2955 	    XFree(ucsstr);
2956 	  } else
2957 	    XDrawString(XtDisplay(tw),
2958 		      XtWindow(tw->text.inner_widget),
2959 		      data->gc, x - data->hoffset, y,
2960 		      block.ptr, length);
2961 	}
2962       } else {
2963 	SetInvGC(tw, data->gc);
2964 	if (newx > x) {
2965 	  if ((int) (y + data->font_descent) >
2966 	      (int) (tw->text.inner_widget->core.height - data->bottommargin))
2967 	    rec_height = (tw->text.inner_widget->core.height -
2968 			  data->bottommargin) - (y - data->font_ascent);
2969 	  else
2970 	    rec_height = data->font_ascent + data->font_descent;
2971 
2972 	  XFillRectangle(XtDisplay(tw),
2973 			 XtWindow(tw->text.inner_widget),
2974 			 data->gc, x - data->hoffset,
2975 			 y - data->font_ascent, newx - x,
2976 			 rec_height);
2977 	}
2978 	SetNormGC(tw, data->gc, True, stipple);
2979 	if (data->use_fontset) {
2980 #ifdef FIX_1381
2981 	  if (stipple)
2982 	    {
2983 	      /*Draw shadow for insensitive text*/
2984 	      SetShadowGC(tw, data->gc);
2985 	      XmbDrawString(XtDisplay(tw),
2986 	      XtWindow(tw->text.inner_widget),
2987 	      (XFontSet) data->font, data->gc,
2988 	      x - data->hoffset+1, y+1, block.ptr, length);
2989 	      SetNormGC(tw, data->gc, True, stipple);
2990 	    }
2991 #endif
2992 	  XmbDrawString(XtDisplay(tw),
2993 			XtWindow(tw->text.inner_widget),
2994 			(XFontSet) data->font, data->gc,
2995 			x - data->hoffset, y, block.ptr, length);
2996 #ifdef USE_XFT
2997 	} else if (data->use_xft) {
2998 #ifdef FIX_1381
2999 	  if (stipple)
3000 	    {
3001 	      /*Draw shadow for insensitive text*/
3002 	      SetShadowGC(tw, data->gc);
3003 	      _XmXftDrawString2(XtDisplay(tw), XtWindow(tw->text.inner_widget),
3004 	      data->gc, (XftFont*) data->font, 1,
3005 	      x - data->hoffset+1, y+1, block.ptr, length);
3006 	      SetNormGC(tw, data->gc, True, stipple);
3007 	    }
3008 #endif
3009 	  _XmXftDrawString2(XtDisplay(tw), XtWindow(tw->text.inner_widget),
3010 			    data->gc, (XftFont*) data->font, 1,
3011 			    x - data->hoffset, y, block.ptr, length);
3012 #endif
3013 	} else {
3014 	  if (_XmIsISO10646(XtDisplay(tw), data->font)) {
3015 	    size_t ucsstr_len = 0;
3016 	    XChar2b *ucsstr = _XmUtf8ToUcs2(block.ptr, length, &ucsstr_len);
3017 #ifdef FIX_1381
3018 	    if (stipple)
3019 	      {
3020 	        /*Draw shadow for insensitive text*/
3021 	        SetShadowGC(tw, data->gc);
3022 	        XDrawString16(XtDisplay(tw), XtWindow(tw->text.inner_widget),
3023 	        data->gc, x - data->hoffset+1, y+1, ucsstr,
3024 	        ucsstr_len);
3025 	        SetNormGC(tw, data->gc, True, stipple);
3026 	      }
3027 #endif
3028 
3029 	    XDrawString16(XtDisplay(tw), XtWindow(tw->text.inner_widget),
3030 				data->gc, x - data->hoffset, y, ucsstr,
3031 				ucsstr_len);
3032 	    XFree(ucsstr);
3033 	  } else
3034 	  {
3035 #ifdef FIX_1381
3036 	    if (stipple)
3037 	      {
3038 	        /*Draw shadow for insensitive text*/
3039 	        SetShadowGC(tw, data->gc);
3040 	        XDrawString(XtDisplay(tw),
3041 	        XtWindow(tw->text.inner_widget), data->gc,
3042 	        x - data->hoffset+1, y+1, block.ptr, length);
3043 		SetNormGC(tw, data->gc, True, stipple);
3044 	      }
3045 #endif
3046 	  XDrawString(XtDisplay(tw),
3047 		      XtWindow(tw->text.inner_widget), data->gc,
3048 		      x - data->hoffset, y, block.ptr, length);
3049 	}
3050 	}
3051 	if (stipple) SetNormGC(tw, data->gc, True, !stipple);
3052       }
3053       if (highlight == XmHIGHLIGHT_SECONDARY_SELECTED)
3054 	XDrawLine(XtDisplay(tw), XtWindow(tw->text.inner_widget),
3055 		  data->gc, x - data->hoffset, y,
3056 		  (newx - data->hoffset) - 1, y);
3057       x = newx;
3058       block.length -= length;
3059       block.ptr += length;
3060       if ((int)tw->text.char_size != 1) {
3061 #ifndef NO_MULTIBYTE
3062 	num_bytes = mblen(block.ptr, (int)tw->text.char_size);
3063 	if (num_bytes < 1) num_bytes = 1;
3064 #else
3065         num_bytes = 1;
3066 #endif
3067       }
3068     }
3069   }
3070   }
3071 
3072     if(XmDirectionMatch(XmPrim_layout_direction(tw),
3073 			XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
3074   /* clear top margin */
3075     text_border = tw->primitive.shadow_thickness +
3076 		  tw->primitive.highlight_thickness;
3077     if (data->topmargin - text_border > 0 && x < rightedge + text_border)
3078       XClearArea(XtDisplay(tw), XtWindow(tw->text.inner_widget),
3079 		 x - (int) (data->linewidth * 0.5)-1, text_border,
3080 		 rightedge - x + (int) (data->linewidth * 0.5),
3081 		 data->topmargin - text_border, FALSE);
3082 
3083     if (cleartoend) {
3084       y -= data->voffset;
3085       if (y > ((int)tw->text.inner_widget->core.height)- data->bottommargin)
3086 	y = ((int)tw->text.inner_widget->core.height)- data->bottommargin;
3087       if (y < data->topmargin)
3088 	y = data->topmargin;
3089       height = ((int)tw->text.inner_widget->core.height) - y -
3090 	data->bottommargin;
3091       if (height > 0 && data->linewidth > 0) {
3092 	if (endhighlight == XmHIGHLIGHT_SELECTED)
3093 	  SetNormGC(tw, data->gc, False, False);
3094 	else
3095 	  SetInvGC(tw, data->gc);
3096 	SetFullGC(tw, data->gc);
3097 	if ((int) (x - (data->linewidth * 0.5)) < data->leftmargin)
3098 	  rec_width = x + (data->linewidth * 0.5) - data->leftmargin;
3099 	else
3100 	  rec_width = data->linewidth;
3101 
3102         XFillRectangle(XtDisplay(tw),
3103 		       XtWindow(tw->text.inner_widget), data->gc,
3104 		       x - (int)(data->linewidth * 0.5), y, rec_width, height);
3105 	SetMarginGC(tw, data->gc);
3106       }
3107     }
3108     if (cleartobottom) {
3109       y = data->topmargin;
3110       width = x - (data->linewidth * 0.5) - data->leftmargin;
3111       height = tw->text.inner_widget->core.height -
3112 	       (data->topmargin + data->bottommargin);
3113       if (width > 0 && height > 0)
3114 	XClearArea(XtDisplay(tw), XtWindow(tw->text.inner_widget),
3115 		   data->leftmargin, y, width, height, False);
3116     }
3117   } else {
3118   /* clear left margin */
3119   text_border = tw->primitive.shadow_thickness +
3120     tw->primitive.highlight_thickness;
3121   if (data->leftmargin - text_border > 0 && (int) (y + data->font_descent) > 0)
3122     XClearArea(XtDisplay(tw), XtWindow(tw->text.inner_widget),
3123 	       text_border, text_border, data->leftmargin - text_border,
3124 	       y + data->font_descent - text_border, False);
3125 
3126   if (cleartoend) {
3127     x -= data->hoffset;
3128     if (x > ((int)tw->text.inner_widget->core.width)- data->rightmargin)
3129       x = ((int)tw->text.inner_widget->core.width)- data->rightmargin;
3130     if (x < data->leftmargin)
3131       x = data->leftmargin;
3132     width = ((int)tw->text.inner_widget->core.width) - x -
3133       data->rightmargin;
3134     if (width > 0 && data->lineheight > 0) {
3135       if (endhighlight == XmHIGHLIGHT_SELECTED)
3136 	SetNormGC(tw, data->gc, False, False);
3137       else
3138 	SetInvGC(tw, data->gc);
3139       SetFullGC(tw, data->gc);
3140       if ((int) (y + data->font_descent) >
3141 	  (int) (tw->text.inner_widget->core.height - data->bottommargin))
3142 	rec_height = (tw->text.inner_widget->core.height -
3143 		      data->bottommargin) - (y - data->font_ascent);
3144       else
3145 	rec_height = data->font_ascent + data->font_descent;
3146 
3147       XFillRectangle(XtDisplay(tw),
3148 		     XtWindow(tw->text.inner_widget), data->gc, x,
3149 		     y - data->font_ascent, width, rec_height);
3150       SetMarginGC(tw, data->gc);
3151     }
3152   }
3153   if (cleartobottom) {
3154     x = data->leftmargin;
3155     width = tw->text.inner_widget->core.width -
3156       (data->rightmargin + data->leftmargin);
3157     height = tw->text.inner_widget->core.height -
3158       ((y + data->font_descent) + data->bottommargin);
3159     if (width > 0 && height > 0)
3160       XClearArea(XtDisplay(tw), XtWindow(tw->text.inner_widget),
3161 		 x, y + data->font_descent, width, height, False);
3162   }
3163   }
3164   /* Before exiting, force PaintCursor to refresh its save area */
3165   data->refresh_ibeam_off = True;
3166 }
3167 
3168 static OnOrOff
3169 CurrentCursorState(XmTextWidget tw)
3170 {
3171   OutputData data = tw->text.output->data;
3172   if (data->cursor_on < 0) return off;
3173   if (data->blinkstate == on || !XtIsSensitive((Widget)tw))
3174     return on;
3175   return off;
3176 }
3177 
3178 
3179 /*
3180  * All the info about the cursor has been figured; draw or erase it.
3181  */
3182 static void
3183 PaintCursor(XmTextWidget tw)
3184 {
3185   OutputData data = tw->text.output->data;
3186   Position x, y;
3187 
3188   if (!data->cursor_position_visible) return;
3189 
3190   _XmTextToggleCursorGC((Widget)tw);
3191 
3192   if (!tw->text.input->data->overstrike)
3193     x = data->insertx - (data->cursorwidth >> 1) - 1;
3194   else {
3195     int pxlen;
3196     XmTextBlockRec block;
3197     XmTextPosition cursor_pos = tw->text.cursor_position;
3198     x = data->insertx;
3199     (void) (*tw->text.source->ReadSource) (tw->text.source,
3200 					       cursor_pos, cursor_pos+1,
3201 					       &block);
3202     pxlen = FindWidth(tw, x, &block, 0, block.length);
3203     if (pxlen > (int) data->cursorwidth)
3204       x += (short) (pxlen - data->cursorwidth) >> 1;
3205   }
3206   y = data->inserty + data->font_descent - data->cursorheight;
3207 
3208   /* If time to paint the I Beam... first capture the IBeamOffArea, then draw
3209    * the I Beam. */
3210   if ((tw->text.top_character <= tw->text.cursor_position) &&
3211       (tw->text.cursor_position <= tw->text.bottom_position)) {
3212 	int cursor_width = data->cursorwidth;
3213 	int cursor_height = data->cursorheight;
3214     if (data->refresh_ibeam_off == True) { /* get area under IBeam first */
3215       /* Fill is needed to realign clip rectangle with gc */
3216       XFillRectangle(XtDisplay((Widget)tw), XtWindow((Widget)tw),
3217 		     data->save_gc, 0, 0, 0, 0);
3218       XCopyArea(XtDisplay((Widget)tw), XtWindow((Widget)tw),
3219 		data->ibeam_off, data->save_gc, x, y, data->cursorwidth,
3220 		data->cursorheight, 0, 0);
3221       data->refresh_ibeam_off = False;
3222     }
3223 
3224     /* redraw cursor, being very sure to keep it within the bounds of the
3225     ** text area, not spilling into the highlight area
3226     */
3227     if ((data->cursor_on >= 0) && (data->blinkstate == on)) {
3228 	  if (x + data->cursorwidth > tw->text.inner_widget->core.width -
3229 		tw->primitive.shadow_thickness -
3230 		tw->primitive.highlight_thickness)
3231 	     cursor_width = (tw->text.inner_widget->core.width -
3232 			(tw->primitive.shadow_thickness +
3233 			tw->primitive.highlight_thickness)) - x;
3234 #ifdef FIX_1501
3235 	  if ( cursor_width > 0 && cursor_height > 0 ) {
3236 	    if (!XtIsSensitive((Widget)tw)) {
3237 		SetShadowGC(tw, data->imagegc);
3238 		XFillRectangle(XtDisplay((Widget)tw), XtWindow((Widget)tw),
3239 					data->imagegc, x + 1, y + 1,
3240 					(unsigned int )cursor_width,
3241 					(unsigned int )cursor_height);
3242 	    }
3243 
3244 	    _XmTextToggleCursorGC((Widget)tw);
3245 #else
3246 	  if ( cursor_width > 0 && cursor_height > 0 )
3247 #endif
3248 		XFillRectangle(XtDisplay((Widget)tw), XtWindow((Widget)tw),
3249 			data->imagegc, x, y,
3250 			(unsigned int )cursor_width,
3251 			(unsigned int )cursor_height);
3252 #ifdef FIX_1501
3253 	  }
3254 #endif
3255     } else {
3256         Position src_x = 0;
3257         if (x + data->cursorwidth > tw->text.inner_widget->core.width -
3258                             tw->primitive.shadow_thickness -
3259                             tw->primitive.highlight_thickness) {
3260           cursor_width = (tw->text.inner_widget->core.width -
3261                                  (tw->primitive.shadow_thickness +
3262                                  tw->primitive.highlight_thickness)) - x;
3263         }
3264          else if (x < tw->primitive.highlight_thickness +
3265                                  tw->primitive.shadow_thickness) {
3266              cursor_width = data->cursorwidth -
3267                                  (tw->primitive.highlight_thickness +
3268                                  tw->primitive.shadow_thickness - x);
3269              src_x = data->cursorwidth - cursor_width;
3270              x = tw->primitive.highlight_thickness +
3271                                  tw->primitive.shadow_thickness;
3272          }
3273         if (y + data->cursorheight > tw->text.inner_widget->core.height -
3274                                  (tw->primitive.highlight_thickness +
3275                                  tw->primitive.shadow_thickness)) {
3276           cursor_height = data->cursorheight -
3277                                  ((y + data->cursorheight) -
3278                                  (tw->text.inner_widget->core.height -
3279                                  (tw->primitive.highlight_thickness +
3280                                  tw->primitive.shadow_thickness)));
3281         }
3282            if (cursor_width > 0 && cursor_height > 0)
3283            {
3284               XCopyArea(XtDisplay((Widget)tw), data->ibeam_off,
3285                      XtWindow((Widget)tw), data->save_gc, src_x, 0,
3286                      (unsigned int)cursor_width,
3287  		    (unsigned int)cursor_height, x, y);
3288            }
3289     }
3290   }
3291 }
3292 
3293 
3294 
3295 static void
3296 ChangeHOffset(XmTextWidget tw,
3297 	      int newhoffset,
3298 #if NeedWidePrototypes
3299 	      int redisplay_hbar)
3300 #else
3301               Boolean redisplay_hbar)
3302 #endif /* NeedWidePrototypes */
3303 {
3304   OutputData data = tw->text.output->data;
3305   int delta;
3306   int width = tw->text.inner_widget->core.width;
3307   int height = tw->text.inner_widget->core.height;
3308   int innerwidth = width - (data->leftmargin + data->rightmargin);
3309   int innerheight = height - (data->topmargin + data->bottommargin);
3310 
3311   if (ShouldWordWrap(data, tw) || data->suspend_hoffset) return;
3312 
3313   if ((data->scrollhorizontal &&
3314        XmIsScrolledWindow(XtParent(tw))) &&
3315       data->scrollwidth - innerwidth < newhoffset)
3316     newhoffset = data->scrollwidth - innerwidth;
3317 
3318   if (newhoffset < 0) newhoffset = 0;
3319   if (newhoffset == data->hoffset) return;
3320 
3321   delta = newhoffset - data->hoffset;
3322   data->hoffset = newhoffset;
3323 
3324   _XmProcessLock();
3325   posToXYCachedWidget = NULL;
3326   _XmProcessUnlock();
3327   if (XtIsRealized((Widget)tw)) {
3328     _XmTextAdjustGC(tw);
3329     SetNormGC(tw, data->gc, False, False);
3330     if (delta < 0) {
3331       if (width > 0 && innerheight > 0) {
3332 	XCopyArea(XtDisplay(tw), XtWindow(tw->text.inner_widget),
3333 		  XtWindow(tw->text.inner_widget), data->gc,
3334 		  data->leftmargin, data->topmargin, width, innerheight,
3335 		  data->leftmargin - delta, data->topmargin);
3336 	/* clear left margin + delta change */
3337 	if ((int) (data->leftmargin - delta -
3338 	     (tw->primitive.shadow_thickness +
3339 	      tw->primitive.highlight_thickness)) < innerwidth)
3340 	  XClearArea(XtDisplay(tw), XtWindow(tw),
3341 		     tw->primitive.shadow_thickness +
3342 		     tw->primitive.highlight_thickness,
3343 		     data->topmargin, data->leftmargin -
3344 		     (tw->primitive.shadow_thickness +
3345 		      tw->primitive.highlight_thickness) - delta,
3346 		     innerheight, False);
3347 	/* clear right margin */
3348 	if ((int) (data->rightmargin-
3349 	    (tw->primitive.shadow_thickness +
3350 	     tw->primitive.highlight_thickness)) > 0)
3351 	  XClearArea(XtDisplay(tw), XtWindow(tw),
3352 		     data->leftmargin + innerwidth, data->topmargin,
3353 		     data->rightmargin -
3354 		     (tw->primitive.shadow_thickness +
3355 		      tw->primitive.highlight_thickness),
3356 		     innerheight,
3357 		     False);
3358 	data->exposehscroll++;
3359       }
3360       RedrawRegion(tw, data->leftmargin, 0, -delta, height);
3361     } else {
3362       if (innerwidth - delta > 0 && innerheight > 0) {
3363 	XCopyArea(XtDisplay(tw), XtWindow(tw->text.inner_widget),
3364 		  XtWindow(tw->text.inner_widget), data->gc,
3365 		  data->leftmargin + delta, data->topmargin,
3366 		  innerwidth - delta, innerheight,
3367 		  data->leftmargin, data->topmargin);
3368 	/* clear right margin + delta change */
3369 	XClearArea(XtDisplay(tw), XtWindow(tw),
3370 		   data->leftmargin + innerwidth - delta, data->topmargin,
3371 		   delta + data->rightmargin -
3372 		   (tw->primitive.shadow_thickness +
3373 		    tw->primitive.highlight_thickness),
3374 		   innerheight, False);
3375 	/* clear left margin */
3376 	if (data->leftmargin - (int)(tw->primitive.shadow_thickness +
3377 				     tw->primitive.highlight_thickness)
3378 	    > 0)
3379 	  XClearArea(XtDisplay(tw), XtWindow(tw),
3380 		     tw->primitive.shadow_thickness +
3381 		     tw->primitive.highlight_thickness,
3382 		     data->topmargin, data->leftmargin -
3383 		     (tw->primitive.shadow_thickness +
3384 		      tw->primitive.highlight_thickness),
3385 		     innerheight, False);
3386 	data->exposehscroll++;
3387       } else {
3388 	/* clear all text */
3389 	XClearArea(XtDisplay(tw), XtWindow(tw),
3390 		   tw->primitive.shadow_thickness +
3391 		   tw->primitive.highlight_thickness,
3392 		   data->topmargin,
3393 		   width - 2 *(tw->primitive.shadow_thickness +
3394 			       tw->primitive.highlight_thickness),
3395 		   innerheight,
3396 		   False);
3397 	data->exposehscroll++;
3398       }
3399       RedrawRegion(tw, width - data->rightmargin - delta, 0,
3400 		   delta, height);
3401     }
3402   }
3403 
3404   if (redisplay_hbar) _XmRedisplayHBar(tw);
3405 }
3406 
3407 
3408 static void
3409 ChangeVOffset(XmTextWidget tw,
3410 	      int newvoffset,
3411 #if NeedWidePrototypes
3412 	      int redisplay_vbar)
3413 #else
3414               Boolean redisplay_vbar)
3415 #endif /* NeedWidePrototypes */
3416 {
3417   OutputData data = tw->text.output->data;
3418   int delta = 0;
3419   int width = tw->text.inner_widget->core.width;
3420   int height = tw->text.inner_widget->core.height;
3421   int innerwidth = width - (data->leftmargin + data->rightmargin);
3422   int innerheight = height - (data->topmargin + data->bottommargin);
3423 
3424   if (ShouldWordWrap(data, tw) || data->suspend_voffset) return;
3425 
3426   if ((data->scrollvertical &&
3427        XmIsScrolledWindow(XtParent(tw))) &&
3428       data->scrollheight - innerheight < newvoffset)
3429     newvoffset = data->scrollheight - innerheight;
3430 
3431   if (newvoffset < 0) newvoffset = 0;
3432   if (newvoffset == data->voffset) return;
3433 
3434   delta = newvoffset - data->voffset;
3435   data->voffset = newvoffset;
3436 
3437   _XmProcessLock();
3438   posToXYCachedWidget = NULL;
3439   _XmProcessUnlock();
3440   if (XtIsRealized((Widget)tw)) {
3441     _XmTextAdjustGC(tw);
3442     SetNormGC(tw, data->gc, False, False);
3443     if (delta < 0) {
3444       if (height > 0 && innerwidth > 0) {
3445 	XCopyArea(XtDisplay(tw), XtWindow(tw->text.inner_widget),
3446 		  XtWindow(tw->text.inner_widget), data->gc,
3447 		  data->leftmargin, data->topmargin, innerwidth, height,
3448 		  data->leftmargin, data->topmargin - delta);
3449 	/* clear top margin + delta change */
3450 	if ((int) (data->topmargin -
3451 	     (tw->primitive.shadow_thickness +
3452 	      tw->primitive.highlight_thickness) - delta) < innerheight)
3453 	  XClearArea(XtDisplay(tw), XtWindow(tw),
3454 		     data->leftmargin,
3455 		     tw->primitive.shadow_thickness +
3456 		     tw->primitive.highlight_thickness,
3457 		     innerwidth, data->topmargin -
3458 		     (tw->primitive.shadow_thickness +
3459 		     tw->primitive.highlight_thickness) - delta, False);
3460 	/* clear right margin */
3461 	if ((int) data->topmargin -
3462 	    (int) (tw->primitive.shadow_thickness +
3463 		   tw->primitive.highlight_thickness) > 0)
3464 	  XClearArea(XtDisplay(tw), XtWindow(tw),
3465 		     data->leftmargin, data->topmargin + innerheight,
3466 		     innerwidth, data->bottommargin -
3467 		     (tw->primitive.shadow_thickness +
3468 		     tw->primitive.highlight_thickness),
3469 		     False);
3470 	data->exposevscroll++;
3471       }
3472       RedrawRegion(tw, 0, data->topmargin, width, -delta);
3473     } else {
3474       if (innerheight - delta > 0 && innerwidth > 0) {
3475 	XCopyArea(XtDisplay(tw), XtWindow(tw->text.inner_widget),
3476 		  XtWindow(tw->text.inner_widget), data->gc,
3477 			   data->leftmargin, data->topmargin + delta,
3478 			   innerwidth, innerheight - delta,
3479 			   data->leftmargin, data->topmargin);
3480 	/* clear bottom margin + delta change */
3481 	XClearArea(XtDisplay(tw), XtWindow(tw),
3482 		   data->leftmargin,
3483 		   data->topmargin + innerheight - delta,
3484 		   innerwidth,
3485 		   delta + data->bottommargin -
3486 		   (tw->primitive.shadow_thickness +
3487 		   tw->primitive.highlight_thickness),
3488 		   False);
3489 	/* clear top margin */
3490 	if (data->topmargin - (int)(tw->primitive.shadow_thickness +
3491 				     tw->primitive.highlight_thickness)
3492 	    > 0)
3493 	  XClearArea(XtDisplay(tw), XtWindow(tw),
3494 		     data->leftmargin,
3495 		     tw->primitive.shadow_thickness +
3496 		     tw->primitive.highlight_thickness,
3497 		     innerwidth,
3498 		     data->topmargin -
3499 		     (tw->primitive.shadow_thickness +
3500 		     tw->primitive.highlight_thickness),
3501 		     False);
3502 	data->exposevscroll++;
3503       } else {
3504 	/* clear all text */
3505 	XClearArea(XtDisplay(tw), XtWindow(tw),
3506 		   data->leftmargin,
3507 		   tw->primitive.shadow_thickness +
3508 		   tw->primitive.highlight_thickness,
3509 		   innerwidth,
3510 		   height - 2 *(tw->primitive.shadow_thickness +
3511 		   tw->primitive.highlight_thickness),
3512 		   False);
3513 	data->exposevscroll++;
3514       }
3515       RedrawRegion(tw, 0, height - data->bottommargin - delta,
3516 		   width, delta);
3517     }
3518   }
3519 
3520   if (redisplay_vbar) _XmRedisplayVBar(tw);
3521 }
3522 
3523 
3524 static void
3525 DrawInsertionPoint(XmTextWidget tw,
3526 		   XmTextPosition position,
3527 		   OnOrOff onoroff)
3528 {
3529   OutputData data = tw->text.output->data;
3530 
3531   if (onoroff == on) {
3532     data->cursor_on +=1;
3533     if (data->blinkrate == 0 || !data->hasfocus)
3534       data->blinkstate = on;
3535   } else {
3536     if ((data->blinkstate == on) && data->cursor_on == 0)
3537       if (data->blinkstate == CurrentCursorState(tw) &&
3538 	  XtIsRealized((Widget)tw)) {
3539 	data->blinkstate = off;  /* Toggle blinkstate to off */
3540 	data->cursor_on -= 1; /* must be done before PaintCursor */
3541 	PaintCursor(tw);
3542       } else
3543 	data->cursor_on -= 1;
3544     else
3545       data->cursor_on -= 1;
3546   }
3547 
3548   if (data->cursor_on < 0 || !XtIsRealized((Widget)tw))
3549     return;
3550   if (PosToXY(tw, position, &data->insertx, &data->inserty))
3551     PaintCursor(tw);
3552 }
3553 
3554 static void
3555 MakePositionVisible(XmTextWidget tw,
3556 		    XmTextPosition position)
3557 {
3558   OutputData data = tw->text.output->data;
3559   Position x, y;
3560   LineNum line_num;
3561 
3562   if (!ShouldWordWrap(data, tw) && PosToXY(tw, position, &x, &y)) {
3563     if(XmDirectionMatch(XmPrim_layout_direction(tw),
3564 			XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
3565       if (y <= data->topmargin) {
3566 	if (tw->text.edit_mode == XmSINGLE_LINE_EDIT) {
3567 	  if (position == tw->text.bottom_position)
3568 	    position = MAX(position - data->rows/2, 0);
3569 	} else {
3570 	  line_num = _XmTextGetTableIndex(tw, position);
3571 	  if (position == tw->text.bottom_position ||
3572 	      (line_num < tw->text.total_lines &&
3573 	       position == tw->text.line_table[line_num+1].start_pos - 1))
3574 	    position =
3575 	      MAX(position - (int) data->rows/2,
3576 		  line_num ? (int) (tw->text.line_table[line_num].start_pos) :
3577 				    0);
3578 	}
3579 	(void)PosToXY(tw, position, &x, &y);
3580       }
3581 
3582       y += data->voffset;
3583       if (y - data->voffset < data->topmargin) {
3584 	ChangeVOffset(tw, y - data->topmargin, True);
3585       } else if (y - data->voffset >
3586 	         ((Position) (tw->text.inner_widget->core.height -
3587 			      data->bottommargin))) {
3588         ChangeVOffset(tw, (int) (y) -
3589 		      (int) (tw->text.inner_widget->core.height) +
3590 		      (int) (data->bottommargin), True);
3591       }
3592     } else {
3593     if (x <= data->leftmargin) {
3594       if (tw->text.edit_mode == XmSINGLE_LINE_EDIT) {
3595 	if (position == tw->text.bottom_position)
3596 	  position = MAX(position - data->columns/2, 0);
3597       } else {
3598 	line_num = _XmTextGetTableIndex(tw, position);
3599 	if (position == tw->text.bottom_position ||
3600 	    (line_num < tw->text.total_lines &&
3601 	     position == tw->text.line_table[line_num+1].start_pos - 1))
3602 	  position =
3603 	    MAX(position - data->columns/2,
3604                 line_num ? (int) (tw->text.line_table[line_num].start_pos) : 0);
3605       }
3606       (void)PosToXY(tw, position, &x, &y);
3607     }
3608 
3609     x += data->hoffset;
3610     if (x - data->hoffset < data->leftmargin) {
3611       ChangeHOffset(tw, x - data->leftmargin, True);
3612     } else if (x - data->hoffset >
3613 	       ((Position) (tw->text.inner_widget->core.width -
3614 			    data->rightmargin))) {
3615       ChangeHOffset(tw, (int) (x) -
3616 		    (int) (tw->text.inner_widget->core.width) +
3617 		    (int) (data->rightmargin), True);
3618     }
3619     }
3620   }
3621 }
3622 
3623 static void
3624 BlinkInsertionPoint(XmTextWidget tw)
3625 {
3626   OutputData data = tw->text.output->data;
3627 
3628   if ((data->cursor_on >=0) &&
3629       data->blinkstate == CurrentCursorState(tw) &&
3630       XtIsRealized((Widget)tw)) {
3631 
3632     /* Toggle blink state */
3633     if (data->blinkstate == on) data->blinkstate = off;
3634     else data->blinkstate = on;
3635 
3636     PaintCursor(tw);
3637 
3638   }
3639 }
3640 
3641 static Boolean
3642 MoveLines(XmTextWidget tw,
3643 	  LineNum fromline,
3644 	  LineNum toline,
3645 	  LineNum destline)
3646 {
3647   OutputData data = tw->text.output->data;
3648   if (!XtIsRealized((Widget) tw)) return False;
3649   _XmTextAdjustGC(tw);
3650   SetNormGC(tw, data->gc, False, False);
3651   SetFullGC(tw, data->gc);
3652   if(XmDirectionMatch(XmPrim_layout_direction(tw),
3653 		      XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
3654     XCopyArea(XtDisplay(tw), XtWindow(tw->text.inner_widget),
3655 	      XtWindow(tw->text.inner_widget), data->gc,
3656 	      tw->text.inner_widget->core.width - data->rightmargin -
3657 	      (Position)data->linewidth * (toline + 1),
3658 	      tw->primitive.shadow_thickness +
3659 	      tw->primitive.highlight_thickness,
3660 	      (Position)data->linewidth * (toline - fromline + 1),
3661 	      tw->text.inner_widget->core.height -
3662 	      2 * (tw->primitive.shadow_thickness +
3663 	           tw->primitive.highlight_thickness),
3664 	      tw->text.inner_widget->core.width - data->rightmargin -
3665 	      (Position)data->linewidth *
3666 	      (destline + toline - fromline + 1),
3667 	      tw->primitive.shadow_thickness +
3668 	      tw->primitive.highlight_thickness);
3669   } else {
3670   XCopyArea(XtDisplay(tw), XtWindow(tw->text.inner_widget),
3671 	    XtWindow(tw->text.inner_widget), data->gc,
3672 	    tw->primitive.shadow_thickness +
3673 	    tw->primitive.highlight_thickness,
3674 	    (Position) data->lineheight * fromline + data->topmargin,
3675 	    tw->text.inner_widget->core.width -
3676 	    2 * (tw->primitive.shadow_thickness +
3677 		 tw->primitive.highlight_thickness),
3678 	    data->lineheight * (toline - fromline + 1),
3679 	    tw->primitive.shadow_thickness +
3680 	    tw->primitive.highlight_thickness,
3681 	    (Position) data->lineheight * destline + data->topmargin);
3682   }
3683   SetMarginGC(tw, data->gc);
3684   if(XmDirectionMatch(XmPrim_layout_direction(tw),
3685                       XmTOP_TO_BOTTOM_RIGHT_TO_LEFT))
3686     data->exposehscroll++;
3687   else
3688   data->exposevscroll++;
3689   return True;
3690 }
3691 
3692 /* ARGSUSED */
3693 static void
3694 OutputInvalidate(XmTextWidget tw,
3695 		 XmTextPosition position,
3696 		 XmTextPosition topos,
3697 		 long delta)
3698 {
3699   _XmProcessLock();
3700   posToXYCachedWidget = NULL;
3701   _XmProcessUnlock();
3702 }
3703 
3704 static void
3705 RefigureDependentInfo(XmTextWidget tw)
3706 {
3707   OutputData data = tw->text.output->data;
3708 
3709   data->columns = data->number_lines;
3710   if(XmDirectionMatch(XmPrim_layout_direction(tw),
3711 		      XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
3712     data->rows = (short)(((int) tw->core.height -
3713 			   (data->topmargin + data->bottommargin))
3714 			  / (int) (data->font_ascent + data->font_descent));
3715 
3716     if (data->rows <= 0)
3717       data->rows = 1;
3718   } else {
3719   data->rows = data->number_lines;
3720   data->columns = (short)(((int) tw->core.width -
3721 			   (data->leftmargin + data->rightmargin))
3722 			  / (data->averagecharwidth));
3723 
3724   if (data->columns <= 0)
3725     data->columns = 1;
3726   }
3727 }
3728 
3729 static void
3730 SizeFromRowsCols(XmTextWidget tw,
3731 		 Dimension *width,
3732 		 Dimension *height)
3733 {
3734   OutputData data = tw->text.output->data;
3735   short lines = 0;
3736 
3737   if (tw->text.edit_mode == XmSINGLE_LINE_EDIT)
3738     lines = 1;
3739   else {
3740     if(XmDirectionMatch(XmPrim_layout_direction(tw),
3741 			XmTOP_TO_BOTTOM_RIGHT_TO_LEFT))
3742       lines = data->columns_set;
3743     else
3744       lines = data->rows_set;
3745   }
3746 
3747   if(XmDirectionMatch(XmPrim_layout_direction(tw),
3748 		      XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
3749     *width = (Dimension) ((lines * data->linewidth) +
3750 			  data->leftmargin + data->rightmargin);
3751 
3752     *height = (Dimension) ((data->rows_set *
3753 			    (data->font_ascent + data->font_descent)) +
3754 			   data->topmargin + data->bottommargin);
3755     if (tw->text.source->data->length > 0 && data->resizeheight)  {
3756       XmTextPosition nextpos;
3757       LineTableExtra extra = NULL;
3758       Boolean past_end = False;
3759       int i;
3760 
3761       for (i = 0; i < tw->text.number_lines && !past_end; i++) {
3762 	past_end = !MeasureLine(tw, i, tw->text.line[i].start,
3763 				&nextpos, &extra);
3764 	if (extra) {
3765 	  if (extra->width > *height)
3766 	    *height = extra->width;
3767 	  XtFree((char *)extra);
3768 	}
3769       }
3770     }
3771   } else {
3772   *width = (Dimension) ((data->columns_set * data->averagecharwidth) +
3773 			data->leftmargin + data->rightmargin);
3774   if (tw->text.source->data->length > 0 && data->resizewidth)  {
3775     XmTextPosition nextpos;
3776     LineTableExtra extra = NULL;
3777     Boolean past_end = False;
3778     int i;
3779 
3780     for (i = 0; i < tw->text.number_lines && !past_end; i++) {
3781       past_end = !MeasureLine(tw, i, tw->text.line[i].start,
3782 			      &nextpos, &extra);
3783       if (extra) {
3784 	if (extra->width > *width)
3785 	  *width = extra->width;
3786 	XtFree((char *)extra);
3787       }
3788     }
3789   }
3790 
3791   *height = (Dimension) ((lines * data->lineheight) +
3792                          data->topmargin + data->bottommargin);
3793 
3794   }
3795 }
3796 
3797 static Boolean
3798 LoadFontMetrics(XmTextWidget tw)
3799 {
3800   OutputData data = tw->text.output->data;
3801   XmFontContext context;
3802   XmFontListEntry next_entry;
3803   XmFontType type_return = XmFONT_IS_FONT;
3804   XtPointer tmp_font;
3805   Boolean have_font_struct = False;
3806   Boolean have_font_set = False;
3807 #ifdef USE_XFT
3808   Boolean have_xft_font = False;
3809 #endif
3810   XFontSetExtents *fs_extents;
3811   XFontStruct *font = NULL;
3812   unsigned long width = 0;
3813   char* font_tag = NULL;
3814 
3815   if (!XmFontListInitFontContext(&context, data->fontlist))
3816     XmeWarning((Widget) tw, MSG3);
3817 
3818   do {
3819     next_entry = XmFontListNextEntry(context);
3820     if (next_entry
3821       && (tmp_font = XmFontListEntryGetFont(next_entry, &type_return))) {
3822       if (type_return == XmFONT_IS_FONTSET) {
3823 	font_tag = XmFontListEntryGetTag(next_entry);
3824 	if (!have_font_set) { /* this saves the first fontset found, just in
3825 			      * case we don't find a default tag set.
3826 			      */
3827 	  data->use_fontset = True;
3828 #ifdef USE_XFT
3829 	  data->use_xft = False;
3830 #endif
3831 	  data->font = (XFontStruct *)tmp_font;
3832 	  have_font_struct = True; /* we have a font set, so no need to
3833 				    * consider future font structs */
3834 	  have_font_set = True;    /* we have a font set. */
3835 
3836 	  if (!strcmp(XmFONTLIST_DEFAULT_TAG, font_tag)) {
3837 	    if (font_tag) XtFree(font_tag);
3838 	    break; /* Break out!  We've found the one we want. */
3839 	  }
3840 	} else if (!strcmp(XmFONTLIST_DEFAULT_TAG, font_tag)) {
3841 	  data->font = (XFontStruct *)tmp_font;
3842 	  have_font_set = True;    /* we have a font set. */
3843 	  if (font_tag) XtFree(font_tag);
3844 	  break; /* Break out!  We've found the one we want. */
3845 	}
3846 	if (font_tag) XtFree(font_tag);
3847       } else if (type_return == XmFONT_IS_FONT && !have_font_struct) {
3848 	data->use_fontset = False;
3849 #ifdef USE_XFT
3850 	data->use_xft = False;
3851 #endif
3852 	/* save the first one in case no font set is found */
3853 	data->font = (XFontStruct*)tmp_font;
3854 	data->use_fontset = False;
3855 	have_font_struct = True;
3856 #ifdef USE_XFT
3857       } else if (type_return == XmFONT_IS_XFT && !have_xft_font) {
3858 	data->use_fontset = False;
3859 	data->use_xft = True;
3860 	have_xft_font = True;
3861 	data->font = (XFontStruct*)tmp_font;
3862 #endif
3863       }
3864     }
3865   } while(next_entry != NULL);
3866 
3867 #if USE_XFT
3868   if (!have_font_struct && !have_font_set && !have_xft_font) {
3869 #else
3870   if (!have_font_struct && !have_font_set) {
3871 #endif
3872     XmeWarning ((Widget)tw, MSG4); /* fontlist without font null entry cause
3873 				  core dump */
3874     return False;
3875   }
3876 
3877   XmFontListFreeFontContext(context);
3878 
3879   if(data->use_fontset) {
3880     fs_extents = XExtentsOfFontSet((XFontSet)data->font);
3881     if (XmDirectionMatch(XmPrim_layout_direction(tw),
3882 			 XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
3883       width = (unsigned long)fs_extents->max_ink_extent.width;
3884     } else {
3885       width = (unsigned long)fs_extents->max_logical_extent.width;
3886     }
3887     /* max_logical_extent.y is number of pixels from origin to top of
3888      * rectangle (i.e. y is negative) */
3889     data->font_ascent = -fs_extents->max_logical_extent.y;
3890     data->font_descent = fs_extents->max_logical_extent.height +
3891       fs_extents->max_logical_extent.y;
3892 #ifdef USE_XFT
3893   } else if (data->use_xft) {
3894     width = ((XftFont*)data->font)->max_advance_width;
3895     data->font_ascent = ((XftFont*)data->font)->ascent;
3896     data->font_descent = ((XftFont*)data->font)->descent;
3897 #endif
3898   } else {
3899     font = data->font;
3900     data->font_ascent = font->max_bounds.ascent;
3901     data->font_descent = font->max_bounds.descent;
3902     if (XmDirectionMatch(XmPrim_layout_direction(tw),
3903 			 XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
3904 	  width = font->max_bounds.rbearing - font->max_bounds.lbearing;
3905     } else {
3906       if ((!XGetFontProperty(font, XA_QUAD_WIDTH, &width)) || width == 0) {
3907 	if (font->per_char && font->min_char_or_byte2 <= '0' &&
3908 	    font->max_char_or_byte2 >= '0')
3909 	  width = font->per_char['0' - font->min_char_or_byte2].width;
3910 	else
3911 	  width = font->max_bounds.width;
3912       }
3913     }
3914   }
3915   if (XmDirectionMatch(XmPrim_layout_direction(tw),
3916 		       XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
3917     if (width <= 0) width = 1;
3918     data->linewidth = width;
3919     data->averagecharwidth = (int) width;
3920     data->tabheight = (int)(8 * (data->font_ascent + data->font_descent));
3921   } else {
3922     data->lineheight = data->font_descent + data->font_ascent;
3923     if (width <= 0) width = 1;
3924     data->averagecharwidth = (int) width; /* This assumes there will be no
3925 					   truncation */
3926     if (data->use_fontset) {
3927 	data->tabwidth = 8 * XmbTextEscapement((XFontSet)data->font, "0", 1);
3928 	/* Check if tabwidth was not calculated correctly */
3929 	if (data->tabwidth == 0)
3930 	    data->tabwidth = (int)(8 * width);
3931     } else {
3932 	data->tabwidth = (int)(8 * width); /* This assumes there will be no
3933 					      truncation */
3934     }
3935   }
3936   return True;
3937 }
3938 
3939 
3940 static Boolean
3941 SetXOCOrientation(XmTextWidget tw,
3942         XOC oc,
3943         XOrientation orientation)
3944 {
3945   XOM om;
3946   XOMOrientation orients;
3947   int i = 0;
3948 
3949   if(!oc)
3950     return False;
3951 
3952   om = XOMOfOC(oc);
3953   if(om) {
3954     if(!XGetOMValues(om, XNQueryOrientation, &orients, NULL)) {
3955       for (i = 0 ; i < orients.num_orientation ; i++) {
3956 	if(orients.orientation[i] == orientation) {
3957 	  if(XSetOCValues(oc, XNOrientation, orientation, NULL)!=NULL)
3958 	    return False;
3959 	}
3960       }
3961     } else return False;
3962   } else return False;
3963 
3964   return True;
3965 }
3966 
3967 
3968 static void
3969 LoadGCs(XmTextWidget tw,
3970         Pixel background,
3971         Pixel foreground)
3972 {
3973   OutputData data = tw->text.output->data;
3974   XGCValues values;
3975   unsigned long valueMask = (GCFunction | GCForeground | GCBackground |
3976 			     GCGraphicsExposures);
3977   unsigned long dynamicMask = GCClipMask;
3978   unsigned long unusedMask = GCClipXOrigin | GCClipYOrigin | GCFont;
3979 
3980   /*
3981    *Get GC for saving area under cursor.
3982    */
3983   values.function = GXcopy;
3984   values.foreground = tw->primitive.foreground;
3985   values.background = tw->core.background_pixel;
3986   values.graphics_exposures = (Bool) False;
3987   if (data->save_gc != NULL)
3988     XtReleaseGC((Widget) tw, data->save_gc);
3989   data->save_gc = XtAllocateGC((Widget) tw, tw->core.depth, valueMask,
3990 			       &values, dynamicMask, unusedMask);
3991 
3992   /*
3993    * Get GC for drawing text.
3994    */
3995 
3996 #if USE_XFT
3997   if (!data->use_fontset && !data->use_xft) {
3998 #else
3999   if (!data->use_fontset) {
4000 #endif
4001     valueMask |= GCFont;
4002     values.font = data->font->fid;
4003   }
4004 
4005   values.graphics_exposures = (Bool) True;
4006   values.foreground = foreground ^ background;
4007   values.background = 0;
4008   if (data->gc != NULL)
4009     XtReleaseGC((Widget) tw, data->gc);
4010   dynamicMask |= GCForeground | GCBackground | GCFillStyle | GCStipple;
4011   data->gc = XtAllocateGC((Widget) tw, tw->core.depth, valueMask,
4012 			  &values, dynamicMask, 0);
4013 
4014   /* Create a temporary GC - change it later in MakeIBeamStencil */
4015   valueMask |= GCStipple | GCFillStyle;
4016   values.graphics_exposures = (Bool) False;
4017   values.stipple = data->stipple_tile;
4018   values.fill_style = FillStippled;
4019   if (data->imagegc != NULL)
4020     XtReleaseGC((Widget) tw, data->imagegc);
4021   dynamicMask |= (GCTileStipXOrigin | GCTileStipYOrigin | GCFunction);
4022   data->imagegc = XtAllocateGC((Widget) tw, tw->core.depth,
4023 			       valueMask, &values, dynamicMask, 0);
4024 }
4025 
4026 static void
4027 MakeIBeamOffArea(XmTextWidget tw,
4028 #if NeedWidePrototypes
4029 		 int width,
4030 		 int height)
4031 #else
4032                  Dimension width,
4033                  Dimension height)
4034 #endif /* NeedWidePrototypes */
4035 {
4036   OutputData data = tw->text.output->data;
4037   Display *dpy = XtDisplay(tw);
4038   Screen  *screen = XtScreen((Widget)tw);
4039 
4040   /* Create a pixmap for storing the screen data where the I-Beam will
4041    * be painted */
4042   data->ibeam_off = XCreatePixmap(dpy, RootWindowOfScreen(screen), width,
4043 				  height, tw->core.depth);
4044 
4045   data->refresh_ibeam_off = True;
4046 }
4047 
4048 static Pixmap
4049 FindPixmap(
4050     Screen *screen,
4051     char *image_name,
4052     Pixel foreground,
4053     Pixel background,
4054     int depth )
4055 {
4056     XmAccessColorDataRec acc_color_rec;
4057 
4058     acc_color_rec.foreground = foreground;
4059     acc_color_rec.background = background;
4060     acc_color_rec.top_shadow_color = XmUNSPECIFIED_PIXEL;
4061     acc_color_rec.bottom_shadow_color = XmUNSPECIFIED_PIXEL;
4062     acc_color_rec.select_color = XmUNSPECIFIED_PIXEL;
4063     acc_color_rec.highlight_color = XmUNSPECIFIED_PIXEL;
4064     return  _XmGetColoredPixmap(screen, image_name,
4065 				&acc_color_rec, depth, True);
4066 }
4067 
4068 static void
4069 MakeIBeamStencil(XmTextWidget tw,
4070 		 int line_width)
4071 {
4072   Screen *screen = XtScreen((Widget)tw);
4073   char pixmap_name[64];
4074   XGCValues values;
4075   unsigned long valueMask;
4076   OutputData data = tw->text.output->data;
4077 
4078   sprintf(pixmap_name, "_XmText_%d_%d", data->cursorheight, line_width);
4079   data->cursor = FindPixmap(screen, pixmap_name, 1, 0, 1);
4080 
4081   if (data->cursor == XmUNSPECIFIED_PIXMAP) {
4082     Display *dpy = XtDisplay(tw);
4083     XSegment segments[3];
4084 
4085     /* Create a pixmap for the I-Beam stencil */
4086     data->cursor = XCreatePixmap(dpy, XtWindow(tw), data->cursorwidth,
4087 				 data->cursorheight, 1);
4088 
4089     values.foreground = 0;
4090     values.line_width = 0;
4091     values.fill_style = FillSolid;
4092     values.function = GXcopy;
4093     valueMask = GCForeground | GCLineWidth | GCFillStyle | GCFunction;
4094     XChangeGC(dpy, data->cursor_gc, valueMask, &values);
4095 
4096     XFillRectangle(dpy, data->cursor, data->cursor_gc, 0, 0, data->cursorwidth,
4097 		   data->cursorheight);
4098 
4099     /* Change the GC for use in "cutting out" the I-Beam shape */
4100     values.foreground = 1;
4101     values.line_width = line_width;
4102     XChangeGC(dpy, data->cursor_gc, GCForeground | GCLineWidth, &values);
4103 
4104     /* Draw the segments of the I-Beam */
4105     if(XmDirectionMatch(XmPrim_layout_direction(tw),
4106 			XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
4107       /* 1st segment is the left vertical line of the cursor */
4108       segments[0].x1 = 1;
4109       segments[0].y1 = line_width - 1;
4110       segments[0].x2 = 1;
4111       segments[0].y2 = data->cursorheight - 1;
4112 
4113       /* 2nd segment is the right vertical line of the cursor */
4114       segments[1].x1 = data->cursorwidth - 1;
4115       segments[1].y1 = line_width - 1;
4116       segments[1].x2 = data->cursorwidth - 1;
4117       segments[1].y2 = data->cursorheight - 1;
4118 
4119       /* 3rd segment is the horizontal line of the cursor */
4120       segments[2].x1 = 0;
4121       segments[2].y1 = data->cursorheight >> 1;
4122       segments[2].x2 = data->cursorwidth;
4123       segments[2].y2 = data->cursorheight >> 1;
4124     } else {
4125     /* 1st segment is the top horizontal line of the 'I' */
4126     segments[0].x1 = 0;
4127     segments[0].y1 = line_width - 1;
4128     segments[0].x2 = data->cursorwidth;
4129     segments[0].y2 = line_width - 1;
4130 
4131     /* 2nd segment is the bottom horizontal line of the 'I' */
4132     segments[1].x1 = 0;
4133     segments[1].y1 = data->cursorheight - 1;
4134     segments[1].x2 = data->cursorwidth;
4135     segments[1].y2 = data->cursorheight - 1;
4136 
4137     /* 3rd segment is the vertical line of the 'I' */
4138     segments[2].x1 = data->cursorwidth >> 1;
4139     segments[2].y1 = line_width;
4140     segments[2].x2 = data->cursorwidth >> 1;
4141     segments[2].y2 = data->cursorheight - 1;
4142     }
4143 
4144     /* Draw the segments onto the cursor */
4145     XDrawSegments(dpy, data->cursor, data->cursor_gc, segments, 3);
4146 
4147     /* Install the cursor for pixmap caching */
4148     (void) _XmCachePixmap(data->cursor, screen, pixmap_name, 1, 0,
4149 			    1, data->cursorwidth, data->cursorheight);
4150 
4151   }
4152 
4153   valueMask = (GCForeground | GCBackground | GCStipple |
4154 	       GCFillStyle);
4155   if (tw->text.input->data->overstrike) {
4156     values.background = values.foreground =
4157       tw->core.background_pixel ^ tw->primitive.foreground;
4158   } else {
4159     values.foreground = tw->primitive.foreground;
4160     values.background = tw->core.background_pixel;
4161   }
4162   values.stipple = data->cursor;
4163   values.fill_style = FillStippled;
4164   XChangeGC(XtDisplay(tw), data->imagegc, valueMask, &values);
4165 
4166 }
4167 
4168 
4169 
4170  /* The IBeam Stencil must have already been created before this routine
4171   * is called.
4172   */
4173 /* ARGSUSED */
4174 static void
4175 MakeAddModeCursor(XmTextWidget tw,
4176 		  int line_width)
4177 {
4178   Screen *screen = XtScreen((Widget)tw);
4179   char pixmap_name[64];
4180   OutputData data = tw->text.output->data;
4181 
4182   sprintf(pixmap_name, "_XmText_AddMode_%d_%d",
4183 	  data->cursorheight,line_width);
4184 
4185   data->add_mode_cursor = FindPixmap(screen, pixmap_name, 1, 0, 1);
4186 
4187   if (data->add_mode_cursor == XmUNSPECIFIED_PIXMAP) {
4188     XtGCMask  valueMask;
4189     XGCValues values;
4190     Display *dpy = XtDisplay((Widget)tw);
4191 
4192     data->add_mode_cursor =  XCreatePixmap(dpy, XtWindow((Widget)tw),
4193 					   data->cursorwidth,
4194 					   data->cursorheight, 1);
4195 
4196     values.function = GXcopy;
4197     valueMask = GCFunction;
4198     XChangeGC(dpy, data->cursor_gc, valueMask, &values);
4199 
4200     XCopyArea(dpy, data->cursor, data->add_mode_cursor, data->cursor_gc, 0, 0,
4201 	      data->cursorwidth, data->cursorheight, 0, 0);
4202 
4203     valueMask = (GCTile | GCFillStyle | GCForeground |
4204 		 GCBackground | GCFunction | GCTileStipXOrigin);
4205     values.function = GXand;
4206     values.tile = data->stipple_tile;
4207     values.fill_style = FillTiled;
4208     values.ts_x_origin = -1;
4209     values.foreground = tw->primitive.foreground;
4210     values.background = tw->core.background_pixel;
4211 
4212     XChangeGC(XtDisplay((Widget)tw), data->cursor_gc, valueMask, &values);
4213 
4214     XFillRectangle(dpy, data->add_mode_cursor, data->cursor_gc,
4215 		   0, 0, data->cursorwidth, data->cursorheight);
4216 
4217     /* Install the pixmap for pixmap caching */
4218     _XmCachePixmap(data->add_mode_cursor, screen, pixmap_name, 1, 0,
4219 		     1, data->cursorwidth, data->cursorheight);
4220 
4221   }
4222 }
4223 
4224 static void
4225 MakeCursors(XmTextWidget tw)
4226 {
4227   OutputData data = tw->text.output->data;
4228   Screen *screen = XtScreen(tw);
4229   int line_width = 1;
4230   int oldwidth = data->cursorwidth;
4231   int oldheight = data->cursorheight;
4232 
4233   if (!XtIsRealized((Widget) tw)) return;
4234 
4235   if(XmDirectionMatch(XmPrim_layout_direction(tw),
4236 		      XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
4237     data->cursorwidth = data->averagecharwidth;
4238     data->cursorheight = 5;
4239 
4240     /* setup parameters to make a thicker I-Beam */
4241     if (data->cursorwidth > 19) {
4242       data->cursorheight++;
4243       line_width = 2;
4244     }
4245   } else {
4246   data->cursorwidth = 5;
4247   data->cursorheight = data->font_ascent + data->font_descent;
4248 
4249   /* setup parameters to make a thicker I-Beam */
4250   if (data->cursorheight > 19) {
4251     data->cursorwidth++;
4252     line_width = 2;
4253   }
4254   }
4255 
4256   if (data->cursor == XmUNSPECIFIED_PIXMAP ||
4257       data->add_mode_cursor == XmUNSPECIFIED_PIXMAP ||
4258       data->ibeam_off == XmUNSPECIFIED_PIXMAP ||
4259       oldheight != data->cursorheight || oldwidth != data->cursorwidth) {
4260 
4261     if (data->cursor_gc == NULL) {
4262       unsigned long valueMask = 0;
4263       XGCValues values;
4264       unsigned long dynamicMask =
4265 	GCForeground | GCLineWidth | GCTile | GCFillStyle |
4266 	GCBackground | GCFunction | GCTileStipXOrigin;
4267 
4268       data->cursor_gc = XtAllocateGC((Widget)tw, 1, valueMask, &values,
4269 				     dynamicMask, 0);
4270     }
4271 
4272     /* Remove old ibeam_off pixmap */
4273     if (data->ibeam_off != XmUNSPECIFIED_PIXMAP)
4274       XFreePixmap(XtDisplay((Widget)tw), data->ibeam_off);
4275 
4276     /* Remove old insert stencil */
4277     if (data->cursor != XmUNSPECIFIED_PIXMAP)
4278       (void) XmDestroyPixmap(screen, data->cursor);
4279 
4280     /* Remove old add mode cursor */
4281     if (data->add_mode_cursor != XmUNSPECIFIED_PIXMAP)
4282       (void) XmDestroyPixmap(screen, data->add_mode_cursor);
4283 
4284     /* Create area in which to save text located underneath I beam */
4285     MakeIBeamOffArea(tw, MAX((int) data->cursorwidth,
4286                              (int) data->cursorheight >> 1),
4287                      data->cursorheight);
4288 
4289     /* Create a new i-beam stencil */
4290     MakeIBeamStencil(tw, line_width);
4291 
4292     /* Create a new add_mode cursor */
4293     MakeAddModeCursor(tw, line_width);
4294   }
4295 
4296   if (tw->text.input->data->overstrike)
4297     data->cursorwidth = data->cursorheight >> 1;
4298 }
4299 
4300 static void
4301 OutputGetValues(Widget w,
4302 		ArgList args,
4303 		Cardinal num_args)
4304 {
4305   XmTextWidget tw = (XmTextWidget) w;
4306 
4307   RefigureDependentInfo(tw);
4308   XtGetSubvalues((XtPointer) tw->text.output->data, output_resources,
4309 		 XtNumber(output_resources), args, num_args);
4310 }
4311 
4312 
4313 static Boolean
4314 CKCols(ArgList args,
4315        Cardinal num_args)
4316 {
4317   register ArgList arg;
4318   for (arg = args; num_args != 0; num_args--, arg++) {
4319     if (strcmp(arg->name, XmNcolumns) == 0) return(True);
4320   }
4321   return(False);
4322 }
4323 
4324 
4325 static Boolean
4326 CKRows(ArgList args,
4327        Cardinal num_args)
4328 {
4329   register ArgList arg;
4330   for (arg = args; num_args != 0; num_args--, arg++) {
4331     if (strcmp(arg->name, XmNrows) == 0) return(True);
4332   }
4333   return(False);
4334 }
4335 
4336 
4337 /* ARGSUSED */
4338 static Boolean
4339 OutputSetValues(Widget oldw,
4340 		Widget reqw,
4341 		Widget new_w,
4342 		ArgList args,
4343 		Cardinal *num_args)
4344 {
4345 #define CK(fld) (newdata->fld != data->fld)
4346 #define CP(fld) (data->fld = newdata->fld)
4347 
4348   XmTextWidget oldtw = (XmTextWidget) oldw;
4349   XmTextWidget newtw = (XmTextWidget) new_w;
4350   OutputData data = newtw->text.output->data;
4351   OutputDataRec newdatarec;
4352   OutputData newdata = &newdatarec;
4353   Boolean needgcs = False;
4354   Boolean newsize = False;
4355   Boolean o_redisplay = False;
4356   Dimension new_width = newtw->core.width;/* save in case something changes */
4357   Dimension new_height = newtw->core.height;/* these values during SetValues*/
4358   XPoint xmim_point;
4359   XRectangle xmim_area;
4360   Arg im_args[17];
4361   Cardinal n = 0;
4362 
4363   *newdata = *data;
4364   XtSetSubvalues((XtPointer) newdata, output_resources,
4365 		 XtNumber(output_resources), args, *num_args);
4366 
4367   if (newtw->core.background_pixel != oldtw->core.background_pixel) {
4368     needgcs = True;
4369   }
4370 
4371   if (newtw->primitive.foreground != oldtw->primitive.foreground) {
4372     needgcs = True;
4373   }
4374 
4375   if (CK(fontlist) || CK(rendertable)) {
4376     XmRenderTableFree(data->fontlist);
4377     if (CK(rendertable)) {
4378       if (newdata->rendertable == NULL)
4379 	newdata->fontlist = XmeGetDefaultRenderTable(new_w, XmTEXT_FONTLIST);
4380       else
4381 	newdata->fontlist = XmRenderTableCopy(newdata->rendertable, NULL, 0);
4382     } else if (CK(fontlist)) {
4383       if (newdata->fontlist == NULL)
4384 	newdata->fontlist = XmeGetDefaultRenderTable(new_w, XmTEXT_FONTLIST);
4385       else
4386 	newdata->fontlist = XmRenderTableCopy(newdata->fontlist, NULL, 0);
4387     }
4388     newdata->rendertable = newdata->fontlist;
4389     CP(fontlist);
4390     CP(rendertable);
4391     if(! LoadFontMetrics(newtw)) {
4392       XmRenderTableFree(newdata->fontlist);
4393       newdata->fontlist = XmeGetDefaultRenderTable(new_w, XmTEXT_FONTLIST);
4394       newdata->rendertable = newdata->fontlist;
4395       CP(fontlist);
4396       CP(rendertable);
4397       (void)LoadFontMetrics(newtw);
4398     }
4399 
4400     /* We want to be able to connect to an IM if XmNfontList has changed. */
4401     if (newtw->text.editable) {
4402       newtw->text.editable = False;
4403       XmTextSetEditable(new_w, True);
4404     }
4405 
4406     if(XmDirectionMatch(XmPrim_layout_direction(newtw),
4407 			XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
4408       if (data->vbar) {
4409 	XmNavigatorDataRec nav_data;
4410 	int new_sliderSize = 0;
4411 
4412 	data->ignorevbar = True;
4413 
4414 	new_sliderSize = newtw->text.inner_widget->core.height
4415 	  - (data->topmargin + data->bottommargin);
4416 
4417 	if (new_sliderSize < 1) new_sliderSize = 1;
4418 	if (new_sliderSize > data->scrollheight)
4419 	  new_sliderSize = data->scrollheight;
4420 
4421 	nav_data.value.y = data->voffset;
4422 	nav_data.minimum.y = 0;
4423 	nav_data.maximum.y = data->scrollheight;
4424 	nav_data.slider_size.y = new_sliderSize;
4425 	nav_data.increment.y = data->font_ascent + data->font_descent;
4426 	nav_data.page_increment.y = 0;
4427 
4428 	nav_data.dimMask = NavigDimensionY;
4429 	nav_data.valueMask = NavValue|NavMinimum|NavMaximum|
4430 	  NavSliderSize|NavIncrement;
4431 	_XmSFUpdateNavigatorsValue(XtParent(new_w), &nav_data, True);
4432 
4433 	data->ignorevbar = False;
4434 
4435       }
4436     } else {
4437     if (data->hbar) {
4438       XmNavigatorDataRec nav_data;
4439       int new_sliderSize;
4440 
4441       data->ignorehbar = True;
4442 
4443       new_sliderSize = newtw->text.inner_widget->core.width
4444 	- (data->leftmargin + data->rightmargin);
4445 
4446       if (new_sliderSize < 1) new_sliderSize = 1;
4447       if (new_sliderSize > data->scrollwidth)
4448 	new_sliderSize = data->scrollwidth;
4449 
4450       nav_data.value.x = data->hoffset;
4451       nav_data.minimum.x = 0;
4452       nav_data.maximum.x = data->scrollwidth;
4453       nav_data.slider_size.x = new_sliderSize;
4454       nav_data.increment.x = data->averagecharwidth;
4455       nav_data.page_increment.x = 0;
4456 
4457       nav_data.dimMask = NavigDimensionX;
4458       nav_data.valueMask = NavValue|NavMinimum|NavMaximum|
4459 	NavSliderSize|NavIncrement;
4460       _XmSFUpdateNavigatorsValue(XtParent(new_w), &nav_data, True);
4461 
4462       data->ignorehbar = False;
4463 
4464     }
4465     }
4466     o_redisplay = True;
4467     needgcs = True;
4468     newsize = True;
4469   }
4470 
4471   if (data->fontlist != oldtw->text.output->data->fontlist ||
4472       newtw->core.background_pixel != oldtw->core.background_pixel ||
4473       newtw->primitive.foreground != oldtw->primitive.foreground) {
4474     XtSetArg(im_args[n], XmNbackground, newtw->core.background_pixel); n++;
4475     XtSetArg(im_args[n], XmNforeground, newtw->primitive.foreground); n++;
4476     XtSetArg(im_args[n], XmNfontList, data->fontlist); n++;
4477   }
4478 
4479   /* Don't word wrap, have multiple row or have vertical scrollbars
4480      if editMode is single_line */
4481   if (newtw->text.edit_mode != oldtw->text.edit_mode) {
4482     if (newtw->text.edit_mode == XmSINGLE_LINE_EDIT)
4483 	newdata->rows = 1;
4484 
4485     if(XmDirectionMatch(XmPrim_layout_direction(newtw),
4486 			XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
4487       if (newtw->text.edit_mode == XmSINGLE_LINE_EDIT) {
4488 	if (data->hbar) XtUnmanageChild(data->hbar);
4489       } else {
4490 	if (data->hbar) XtManageChild(data->hbar);
4491       }
4492       if (newtw->text.edit_mode == XmSINGLE_LINE_EDIT) {
4493         if (data->vbar) XtUnmanageChild(data->vbar);
4494       } else {
4495         if (data->vbar) XtManageChild(data->vbar);
4496       }
4497     } else {
4498       if (data->hbar) XtManageChild(data->hbar);
4499       if (newtw->text.edit_mode != XmSINGLE_LINE_EDIT) {
4500           if (data->vbar) XtManageChild(data->vbar);
4501       } else {
4502           if (data->vbar) XtUnmanageChild(data->vbar);
4503       }
4504     }
4505     o_redisplay = True;
4506   }
4507 
4508   /*  what is called margin, in this code, is composed of margin, shadow, and
4509       highlight.   Previously, only margin was accomodated.   This addition
4510       may not be very clever, but it blends in with the rest of the way this
4511       code works.
4512       */
4513 
4514   if (newtw->text.margin_width != oldtw->text.margin_width ||
4515       newtw->text.margin_height != oldtw->text.margin_height ||
4516       newtw->primitive.shadow_thickness !=
4517       oldtw->primitive.shadow_thickness ||
4518       newtw->primitive.highlight_thickness !=
4519       oldtw->primitive.highlight_thickness)
4520     {
4521       data->leftmargin = data->rightmargin = newtw->text.margin_width +
4522 	newtw->primitive.shadow_thickness +
4523 	  newtw->primitive.highlight_thickness;
4524       data->topmargin = data->bottommargin = newtw->text.margin_height +
4525 	newtw->primitive.shadow_thickness +
4526 	  newtw->primitive.highlight_thickness;
4527       o_redisplay = True;
4528       newsize = True;
4529     }
4530 
4531   if (CK(wordwrap)) {
4532     if(XmDirectionMatch(XmPrim_layout_direction(newtw),
4533 			XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
4534       /* If we are turning on wrapping, we don't want any horiz. offset */
4535       if (!data->wordwrap) ChangeVOffset(newtw, 0, True);
4536 
4537       if (data->vbar) {
4538 	if (newdata->wordwrap) {
4539 	  XmNavigatorDataRec nav_data;
4540 
4541 	  data->ignorevbar = True;
4542 
4543 	  nav_data.value.y = 0;
4544 	  nav_data.minimum.y = 0;
4545 	  nav_data.maximum.y = 1;
4546 	  nav_data.slider_size.y = 1;
4547 	  nav_data.increment.y = 0;
4548 	  nav_data.page_increment.y = 0;
4549 
4550 	  nav_data.dimMask = NavigDimensionY;
4551 	  nav_data.valueMask = NavValue|NavMinimum|NavMaximum|
4552 	    NavSliderSize;
4553 	  _XmSFUpdateNavigatorsValue(XtParent(new_w), &nav_data, True);
4554 
4555 	  data->ignorevbar = False;
4556 
4557 	  data->voffset = 0;
4558 	} else {
4559 	  _XmRedisplayVBar(newtw);
4560 	}
4561       }
4562     } else {
4563     /* If we are turning on wrapping, we don't want any horiz. offset */
4564     if (!data->wordwrap) ChangeHOffset(newtw, 0, True);
4565 
4566     if (data->hbar) {
4567       if (newdata->wordwrap) {
4568 	XmNavigatorDataRec nav_data;
4569 
4570 	data->ignorehbar = True;
4571 
4572 	nav_data.value.x = 0;
4573 	nav_data.minimum.x = 0;
4574 	nav_data.maximum.x = 1;
4575 	nav_data.slider_size.x = 1;
4576 	nav_data.increment.x = 0;
4577 	nav_data.page_increment.x = 0;
4578 
4579 	nav_data.dimMask = NavigDimensionX;
4580 	nav_data.valueMask = NavValue|NavMinimum|NavMaximum|
4581 	  NavSliderSize;
4582 	_XmSFUpdateNavigatorsValue(XtParent(new_w), &nav_data, True);
4583 
4584 	data->ignorehbar = False;
4585 
4586 	data->hoffset = 0;
4587       } else {
4588 	_XmRedisplayHBar(newtw);
4589       }
4590     }
4591     }
4592 
4593     CP(wordwrap);
4594 
4595     _XmTextRealignLineTable(newtw, NULL, 0, 0, 0, PASTENDPOS);
4596 
4597     /* If we've just turned off wrapping, get new top_character by scanning */
4598     /* left from the current top character until we find a new line. */
4599     if (!oldtw->text.output->data->wordwrap) {
4600       if (data->resizeheight)
4601 	newtw->text.top_character = newtw->text.new_top = 0;
4602       else {
4603 	newtw->text.top_character = (*newtw->text.source->Scan)
4604 	  (newtw->text.source, newtw->text.top_character,
4605 	   XmSELECT_LINE, XmsdLeft, 1, False);
4606 	newtw->text.new_top = newtw->text.top_character;
4607       }
4608     }
4609 
4610     if (newtw->text.top_character)
4611       newtw->text.top_line = CountLines(newtw, 0,
4612 					newtw->text.top_character);
4613 
4614 
4615     o_redisplay = True;
4616   }
4617 
4618   if (data->hasfocus && XtIsSensitive((Widget)newtw) && CK(blinkrate)) {
4619     if (newdata->blinkrate == 0) {
4620       data->blinkstate = on;
4621       if (data->timerid) {
4622 	XtRemoveTimeOut(data->timerid);
4623 	data->timerid = (XtIntervalId)0;
4624       }
4625     } else if (data->timerid == (XtIntervalId)0) {
4626       data->timerid =
4627 	XtAppAddTimeOut(XtWidgetToApplicationContext(new_w),
4628 			(unsigned long) newdata->blinkrate,
4629 			HandleTimer, (XtPointer) newtw);
4630     }
4631   }
4632   CP(blinkrate);
4633 
4634   CP(resizewidth);
4635   CP(resizeheight);
4636 
4637   CP(cursor_position_visible);
4638 
4639   if (needgcs) {
4640     EraseInsertionPoint(newtw);
4641     LoadGCs(newtw, newtw->core.background_pixel,
4642 	    newtw->primitive.foreground);
4643     if (XtIsRealized(new_w)) {
4644       MakeCursors(newtw);
4645     }
4646     TextDrawInsertionPoint(newtw);
4647     o_redisplay = True;
4648   }
4649 
4650   if (newdata->rows <= 0) {
4651     XmeWarning(new_w, MSG1);
4652     newdata->rows = data->rows;
4653   }
4654 
4655   if (newdata->columns <= 0) {
4656     XmeWarning(new_w, MSG2);
4657     newdata->columns = data->columns;
4658   }
4659 
4660   /* Process arglist to verify the a value is being set */
4661   if (CKCols(args, *num_args))
4662     data->columns_set = newdata->columns_set = newdata->columns;
4663 
4664   /* Process arglist to verify the a value is being set */
4665   if (CKRows(args, *num_args))
4666     data->rows_set = newdata->rows_set = newdata->rows;
4667 
4668   if (!(new_width != oldtw->core.width &&
4669 	new_height != oldtw->core.height)) {
4670     if (CK(columns) || CK(rows) || newsize) {
4671       Dimension width, height;
4672       SizeFromRowsCols(newtw, &width, &height);
4673       if(XmDirectionMatch(XmPrim_layout_direction(newtw),
4674 			  XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
4675 	if (new_width == oldtw->core.width)
4676 	  newtw->core.width = width;
4677 	data->minwidth = newtw->core.width;
4678 	if (new_height == oldtw->core.height) {
4679 	  newtw->core.height = height;
4680 	  data->minheight =
4681 	    (Dimension)((data->rows_set *
4682 			(data->font_ascent + data->font_descent)) +
4683 			 data->topmargin + data->bottommargin);
4684 	} else {
4685 	  data->minheight = new_height;
4686 	}
4687       } else {
4688       if (new_width == oldtw->core.width) {
4689 	newtw->core.width = width;
4690 	data->minwidth =
4691 	  (Dimension)((data->columns_set * data->averagecharwidth) +
4692 		      data->leftmargin + data->rightmargin);
4693       } else {
4694 	data->minwidth = new_width;
4695       }
4696       if (new_height == oldtw->core.height)
4697 	newtw->core.height = height;
4698       data->minheight = newtw->core.height;
4699       }
4700       CP(columns);
4701       CP(rows);
4702       o_redisplay = True;
4703     }
4704   } else {
4705     newtw->core.width = new_width;
4706     data->minwidth = new_width;
4707     newtw->core.height = new_height;
4708     data->minheight = new_height;
4709   }
4710 
4711   PosToXY(newtw, newtw->text.cursor_position, &xmim_point.x, &xmim_point.y);
4712   (void)_XmTextGetDisplayRect((Widget)newtw, &xmim_area);
4713   XtSetArg(im_args[n], XmNbackgroundPixmap,
4714 	   newtw->core.background_pixmap);n++;
4715   XtSetArg(im_args[n], XmNspotLocation, &xmim_point); n++;
4716   XtSetArg(im_args[n], XmNarea, &xmim_area); n++;
4717   XtSetArg(im_args[n], XmNlineSpace, newdata->lineheight); n++;
4718   XmImSetValues(new_w, im_args, n);
4719 
4720   return (o_redisplay);
4721 #undef CK
4722 #undef CP
4723 }
4724 
4725 static void
4726 NotifyResized(Widget w,
4727 #if NeedWidePrototypes
4728 	      int o_create)
4729 #else
4730               Boolean o_create)
4731 #endif /* NeedWidePrototypes */
4732 {
4733   XmTextWidget tw = (XmTextWidget) w;
4734   OutputData data = tw->text.output->data;
4735   Boolean resizewidth = data->resizewidth;
4736   Boolean resizeheight = data->resizeheight;
4737   XmTextPosition linestart = 0;
4738   XmTextPosition position;
4739   XPoint xmim_point;
4740   XRectangle xmim_area;
4741   int n;
4742   XmTextBlockRec block;
4743   Arg args[10];
4744 
4745   data->resizewidth = data->resizeheight = False;
4746   if(XmDirectionMatch(XmPrim_layout_direction(tw),
4747 		      XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
4748     data->number_lines = tw->text.inner_widget->core.width -
4749       data->leftmargin - data->rightmargin;
4750     if (data->number_lines < (int) data->linewidth || !data->linewidth)
4751       data->number_lines = 1;
4752     else
4753       data->number_lines /= (int) data->linewidth;
4754 
4755     if (tw->text.top_character)
4756     {
4757       tw->text.top_line = CountLines(tw, 0,
4758 					 tw->text.top_character);
4759     if (tw->text.total_lines >= data->number_lines &&
4760 	   (tw->text.total_lines - tw->text.top_line) < data->number_lines)
4761 		tw->text.top_line = tw->text.total_lines - data->number_lines;
4762       tw->text.new_top = tw->text.line_table[tw->text.top_line].start_pos;
4763     }
4764   } else {
4765   data->number_lines = tw->text.inner_widget->core.height -
4766     data->topmargin - data->bottommargin;
4767   if (data->number_lines < (int) data->lineheight || !data->lineheight)
4768     data->number_lines = 1;
4769   else
4770     data->number_lines /= (int) data->lineheight;
4771 
4772   if (tw->text.top_character)
4773   {
4774     tw->text.top_line = CountLines(tw, 0,
4775 				       tw->text.top_character);
4776     if (tw->text.total_lines >= data->number_lines &&
4777 	   (tw->text.total_lines - tw->text.top_line) < data->number_lines)
4778 		tw->text.top_line = tw->text.total_lines - data->number_lines;
4779     tw->text.new_top = tw->text.line_table[tw->text.top_line].start_pos;
4780   }
4781   }
4782 
4783   if (data->vbar)
4784     {
4785       int local_total, new_size;
4786       XmNavigatorDataRec nav_data;
4787 #ifdef FIX_1396
4788       int new_voffset = 0;
4789 #endif
4790 
4791       if(XmDirectionMatch(XmPrim_layout_direction(tw),
4792 			  XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
4793 	new_size = tw->text.inner_widget->core.height
4794 	  - (data->topmargin + data->bottommargin);
4795 	if (new_size < 1) new_size = 1;
4796 	if (new_size > data->scrollheight) new_size = data->scrollheight;
4797 #ifdef FIX_1396
4798         new_voffset = data->voffset;
4799         if (new_voffset > data->scrollheight - new_size)
4800     	    new_voffset = data->scrollheight - new_size;
4801 #endif
4802 	data->ignorevbar = True;
4803 #ifdef FIX_1396
4804 	nav_data.value.y = new_voffset;
4805 #else
4806 	nav_data.value.y = data->voffset;
4807 #endif
4808 	nav_data.minimum.y = 0;
4809 	nav_data.maximum.y = data->scrollheight;
4810 	nav_data.slider_size.y = new_size;
4811 	nav_data.page_increment.y = new_size;
4812       } else {
4813       data->ignorevbar = True;
4814 
4815       if (tw->text.top_line + tw->text.number_lines >
4816 	  tw->text.total_lines)
4817 	local_total = tw->text.top_line + tw->text.number_lines;
4818       else
4819 	local_total = tw->text.total_lines;
4820 
4821       if (local_total >= tw->text.number_lines)
4822 	new_size = tw->text.number_lines;
4823       else
4824 	new_size = local_total;
4825       if (new_size + tw->text.top_line > local_total)
4826 	new_size = local_total - tw->text.top_line;
4827 
4828       nav_data.value.y = tw->text.top_line;
4829       nav_data.minimum.y = 0;
4830       nav_data.maximum.y = local_total;
4831       nav_data.slider_size.y = new_size;
4832       nav_data.page_increment.y = (data->number_lines > 1)?
4833 	(data->number_lines - 1): 1;
4834       }
4835 
4836       nav_data.dimMask = NavigDimensionY;
4837       nav_data.valueMask = NavValue|NavMinimum|NavMaximum|
4838 	NavSliderSize|NavPageIncrement;
4839       _XmSFUpdateNavigatorsValue(XtParent((Widget)tw), &nav_data, True);
4840 
4841       data->ignorevbar = False;
4842 
4843     }
4844 
4845   if (data->hbar)
4846     {
4847       XmNavigatorDataRec nav_data;
4848       int new_size = 0;
4849       int local_total = 0;
4850 #ifdef FIX_1396
4851       int new_hoffset = 0;
4852 #endif
4853       if(XmDirectionMatch(XmPrim_layout_direction(tw),
4854 			  XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
4855 	data->ignorehbar = True;
4856 
4857 	if (tw->text.top_line + tw->text.number_lines >
4858 	    tw->text.total_lines)
4859 	  local_total = tw->text.top_line + tw->text.number_lines;
4860 	else
4861 	  local_total = tw->text.total_lines;
4862 
4863 	if (local_total >= tw->text.number_lines)
4864 	  new_size = tw->text.number_lines;
4865 	else
4866 	  new_size = local_total;
4867 	if (new_size + tw->text.top_line > local_total)
4868 	  new_size = local_total - tw->text.top_line;
4869 
4870 	nav_data.value.x = tw->text.top_line;
4871 	nav_data.minimum.x = 0;
4872 	nav_data.maximum.x = local_total;
4873 	nav_data.slider_size.x = new_size;
4874 	nav_data.page_increment.x = (data->number_lines > 1)?
4875 	  (data->number_lines - 1): 1;
4876       } else {
4877       new_size = tw->text.inner_widget->core.width
4878 	- (data->leftmargin + data->rightmargin);
4879       if (new_size < 1) new_size = 1;
4880       if (new_size > data->scrollwidth) new_size = data->scrollwidth;
4881 #ifdef FIX_1396
4882       new_hoffset = data->hoffset;
4883       if (new_hoffset > data->scrollwidth - new_size)
4884         new_hoffset = data->scrollwidth - new_size;
4885 #endif
4886       data->ignorehbar = True;
4887 #ifdef FIX_1396
4888       nav_data.value.x = new_hoffset;
4889 #else
4890       nav_data.value.x = data->hoffset;
4891 #endif
4892       nav_data.minimum.x = 0;
4893       nav_data.maximum.x = data->scrollwidth;
4894       nav_data.slider_size.x = new_size;
4895       nav_data.page_increment.x = new_size;
4896       }
4897 
4898       nav_data.dimMask = NavigDimensionX;
4899       nav_data.valueMask = NavValue|NavMinimum|NavMaximum|
4900 	NavSliderSize|NavPageIncrement;
4901       _XmSFUpdateNavigatorsValue(XtParent((Widget)tw), &nav_data, True);
4902 
4903       data->ignorehbar = False;
4904     }
4905 
4906   RefigureDependentInfo(tw);
4907   if (resizewidth)
4908     data->columns_set = data->columns;
4909   if (resizeheight)
4910     data->rows_set = data->rows;
4911 
4912   if (XtIsRealized(w)) {
4913     XClearWindow(XtDisplay(tw), XtWindow(tw->text.inner_widget));
4914     data->refresh_ibeam_off = True;
4915   }
4916 
4917   if (!o_create)              /* False only if called from OutputCreate */
4918     _XmTextInvalidate(tw, (XmTextPosition) 0, (XmTextPosition) 0,
4919 		      NODELTA);
4920 
4921   /* the new size grew enough to include new text */
4922 
4923   if (XmDirectionMatch(XmPrim_layout_direction(tw),
4924 		       XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
4925     if (tw->text.edit_mode == XmSINGLE_LINE_EDIT) {
4926       /* this assumes only one line of text! (linestart = 0) */
4927 #ifdef AS_TEXTFIELD
4928       ChangeVOffset(tw, 0, True);
4929 #else
4930       int text_height = data->topmargin; /* to make tab calculation correct */
4931       int new_height = tw->core.height - (data->topmargin + data->bottommargin);
4932 
4933       position = (*tw->text.source->Scan)(tw->text.source, linestart,
4934 					      XmSELECT_LINE, XmsdRight,
4935 					      1, False);
4936       while (linestart < position) {
4937 	linestart = (*tw->text.source->ReadSource) (tw->text.source,
4938 						        linestart, position,
4939 						        &block);
4940 	text_height += FindHeight(tw, text_height, &block, 0, block.length);
4941       }
4942       text_height -= data->topmargin;
4943       if (text_height - new_height < data->voffset) {
4944 	/* space top over */
4945 	if (text_height - new_height >= 0)
4946 	  ChangeVOffset(tw, text_height - new_height, True);
4947 	else
4948 	  ChangeVOffset(tw, 0, True);
4949       }
4950 #endif
4951       if (tw->text.auto_show_cursor_position) {
4952 	MakePositionVisible(tw, tw->text.cursor_position);
4953       }
4954     } else _XmRedisplayVBar(tw);
4955   } else {
4956   if (tw->text.edit_mode == XmSINGLE_LINE_EDIT) {
4957     /* this assumes only one line of text! (linestart = 0) */
4958 #ifdef AS_TEXTFIELD
4959     ChangeHOffset(tw, 0, True);
4960 #else
4961     int text_width = data->leftmargin; /* to make tab calculation correct */
4962     int new_width = tw->core.width - (data->leftmargin + data->rightmargin);
4963 
4964     position = (*tw->text.source->Scan)(tw->text.source, linestart,
4965 					    XmSELECT_LINE, XmsdRight,
4966 					    1, False);
4967     while (linestart < position) {
4968       linestart = (*tw->text.source->ReadSource) (tw->text.source,
4969 				      linestart, position, &block);
4970       text_width += FindWidth(tw, text_width, &block, 0, block.length);
4971     }
4972     text_width -= data->leftmargin;
4973     if (text_width - new_width < data->hoffset) {
4974       /* space left over */
4975       if (text_width - new_width >= 0)
4976 	ChangeHOffset(tw, text_width - new_width, True);
4977       else
4978 	ChangeHOffset(tw, 0, True);
4979     }
4980 #endif
4981     if (tw->text.auto_show_cursor_position) {
4982       MakePositionVisible(tw, tw->text.cursor_position);
4983     }
4984   } else _XmRedisplayHBar(tw);
4985   }
4986 
4987   data->resizewidth = resizewidth;
4988   data->resizeheight = resizeheight;
4989 
4990   if (XtIsRealized(w))
4991     _XmTextDrawShadow(tw);
4992 
4993   /* Text is now rediplayed at the correct location, so force the tw to
4994    * refresh the putback area.
4995    */
4996 
4997   data->refresh_ibeam_off = True;
4998 
4999   /* Somehow we need to let the input method know that the window has
5000    * changed size (for case of over-the-spot).  Try telling it that
5001    * the cursor position has changed and hopefully it will re-evaluate
5002    * the position/visibility/... of the pre-edit window.
5003    */
5004 
5005   PosToXY(tw, tw->text.cursor_position, &xmim_point.x, &xmim_point.y);
5006   (void)_XmTextGetDisplayRect((Widget)tw, &xmim_area);
5007   n = 0;
5008   XtSetArg(args[n], XmNspotLocation, &xmim_point); n++;
5009   XtSetArg(args[n], XmNarea, &xmim_area); n++;
5010   XmImSetValues(w, args, n);
5011 }
5012 
5013 /* ARGSUSED */
5014 static void
5015 HandleTimer(XtPointer closure,
5016 	    XtIntervalId *id)
5017 {
5018   XmTextWidget tw = (XmTextWidget) closure;
5019   OutputData data = tw->text.output->data;
5020   if (data->blinkrate != 0)
5021     data->timerid =
5022       XtAppAddTimeOut(XtWidgetToApplicationContext((Widget) tw),
5023 		      (unsigned long)data->blinkrate,
5024 		      HandleTimer, (XtPointer) closure);
5025   if (data->hasfocus && XtIsSensitive((Widget)tw)) BlinkInsertionPoint(tw);
5026 }
5027 
5028 /*****************************************************************************
5029  * To make TextOut a True "Object" this function should be a class function. *
5030  *****************************************************************************/
5031 void
5032 _XmTextChangeBlinkBehavior(XmTextWidget tw,
5033 #if NeedWidePrototypes
5034 			   int newvalue)
5035 #else
5036                            Boolean newvalue)
5037 #endif /* NeedWidePrototypes */
5038 {
5039   OutputData data = tw->text.output->data;
5040 
5041   if (newvalue) {
5042     if (data->blinkrate != 0 && data->timerid == (XtIntervalId)0)
5043       data->timerid =
5044 	XtAppAddTimeOut(XtWidgetToApplicationContext((Widget) tw),
5045 			(unsigned long)data->blinkrate,
5046 			HandleTimer, (XtPointer) tw);
5047     data->blinkstate = on;
5048   } else {
5049     if (data->timerid)
5050       XtRemoveTimeOut(data->timerid);
5051     data->timerid = (XtIntervalId)0;
5052   }
5053 }
5054 
5055 /* ARGSUSED */
5056 
5057 static void
5058 HandleFocusEvents(Widget w,
5059 		  XtPointer closure,
5060 		  XEvent *event,
5061 		  Boolean *cont)
5062 {
5063   XmTextWidget tw = (XmTextWidget) w;
5064   OutputData data = tw->text.output->data;
5065   Boolean newhasfocus = data->hasfocus;
5066   XmAnyCallbackStruct cb;
5067   XPoint xmim_point;
5068   XRectangle xmim_area;
5069   Arg  args[10];
5070   int  n = 0;
5071 
5072   PosToXY(tw, tw->text.cursor_position, &xmim_point.x, &xmim_point.y);
5073   (void)_XmTextGetDisplayRect((Widget)tw, &xmim_area);
5074 
5075   switch (event->type) {
5076   case FocusIn:
5077     if (event->xfocus.send_event && !(newhasfocus)) {
5078       cb.reason = XmCR_FOCUS;
5079       cb.event = event;
5080       XtCallCallbackList (w, tw->text.focus_callback, (Opaque) &cb);
5081       newhasfocus = True;
5082 
5083       n = 0;
5084       XtSetArg(args[n], XmNspotLocation, &xmim_point); n++;
5085       XtSetArg(args[n], XmNarea, &xmim_area); n++;
5086       XmImSetFocusValues(w, args, n);
5087     }
5088     break;
5089   case FocusOut:
5090     if (event->xfocus.send_event && newhasfocus) {
5091       newhasfocus = False;
5092       XmImUnsetFocus(w);
5093     }
5094     break;
5095   case EnterNotify:
5096     if ((_XmGetFocusPolicy(w) != XmEXPLICIT) && !(newhasfocus) &&
5097 	event->xcrossing.focus &&
5098 	(event->xcrossing.detail != NotifyInferior)) {
5099       cb.reason = XmCR_FOCUS;
5100       cb.event = event;
5101       XtCallCallbackList (w, tw->text.focus_callback, (Opaque) &cb);
5102       newhasfocus = True;
5103       n = 0;
5104       XtSetArg(args[n], XmNspotLocation, &xmim_point); n++;
5105       XtSetArg(args[n], XmNarea, &xmim_area); n++;
5106       XmImSetFocusValues(w, args, n);
5107     }
5108     break;
5109   case LeaveNotify:
5110     if ((_XmGetFocusPolicy(w) != XmEXPLICIT) && newhasfocus &&
5111 	event->xcrossing.focus &&
5112 	(event->xcrossing.detail != NotifyInferior)) {
5113       newhasfocus = False;
5114       XmImUnsetFocus(w);
5115     }
5116     break;
5117   }
5118   if (newhasfocus != data->hasfocus) {
5119     if (newhasfocus && XtIsSensitive((Widget)tw)) {
5120       EraseInsertionPoint(tw);
5121       data->hasfocus = newhasfocus;
5122       data->blinkstate = off;
5123       _XmTextChangeBlinkBehavior(tw, True);
5124       TextDrawInsertionPoint(tw);
5125     } else {
5126       _XmTextChangeBlinkBehavior(tw, False);
5127       EraseInsertionPoint(tw);
5128       data->hasfocus = newhasfocus;
5129       data->blinkstate = on;
5130       TextDrawInsertionPoint(tw);
5131     }
5132   }
5133 }
5134 
5135 
5136 
5137 /* ARGSUSED */
5138 static void
5139 HandleGraphicsExposure(Widget w,
5140 		       XtPointer closure,
5141 		       XEvent *event,
5142 		       Boolean *cont)
5143 {
5144   XmTextWidget tw = (XmTextWidget) w;
5145   OutputData data = tw->text.output->data;
5146   if (event->xany.type == GraphicsExpose) {
5147     XGraphicsExposeEvent *xe = (XGraphicsExposeEvent *) event;
5148     if (data->exposehscroll != 0) {
5149       xe->x = 0;
5150       xe->width = tw->core.width;
5151     }
5152     if (data->exposevscroll != 0) {
5153       xe->y = 0;
5154       xe->height = tw->core.height;
5155     }
5156     RedrawRegion(tw, xe->x, xe->y, xe->width, xe->height);
5157     if (xe->count == 0) {
5158       if (data->exposehscroll) data->exposehscroll--;
5159       if (data->exposevscroll) data->exposevscroll--;
5160     }
5161   }
5162   if (event->xany.type == NoExpose) {
5163     if (data->exposehscroll) data->exposehscroll--;
5164     if (data->exposevscroll) data->exposevscroll--;
5165   }
5166 }
5167 
5168 
5169 static void
5170 OutputRealize(Widget w,
5171 	      XtValueMask *valueMask,
5172 	      XSetWindowAttributes *attributes)
5173 {
5174   XmTextWidget tw = (XmTextWidget) w;
5175 
5176   XtCreateWindow(w, (unsigned int) InputOutput, (Visual *) CopyFromParent,
5177 		 *valueMask, attributes);
5178   MakeCursors(tw);
5179 }
5180 
5181 
5182 static void
5183 OutputDestroy(Widget w)
5184 {
5185   XmTextWidget tw = (XmTextWidget) w;
5186   OutputData data = tw->text.output->data;
5187 
5188   if (data->timerid)
5189     XtRemoveTimeOut(data->timerid);
5190 
5191   XtRemoveEventHandler((Widget) tw->text.inner_widget,
5192 		       FocusChangeMask|EnterWindowMask|LeaveWindowMask,
5193 		       False, HandleFocusEvents, NULL);
5194 
5195   XtRemoveEventHandler((Widget) tw->text.inner_widget,
5196 		       (EventMask) 0, True, HandleGraphicsExposure,
5197 		       NULL);
5198 
5199   XtReleaseGC(w, data->imagegc);
5200   XtReleaseGC(w, data->gc);
5201   XtReleaseGC(w, data->save_gc);
5202   XtReleaseGC(w, data->cursor_gc);
5203 
5204   XmFontListFree(data->fontlist);
5205 
5206   if (data->add_mode_cursor != XmUNSPECIFIED_PIXMAP)
5207     (void) XmDestroyPixmap(XtScreen(tw), data->add_mode_cursor);
5208 
5209   if (data->cursor != XmUNSPECIFIED_PIXMAP)
5210     (void) XmDestroyPixmap(XtScreen(tw), data->cursor);
5211 
5212   if (data->ibeam_off != XmUNSPECIFIED_PIXMAP)
5213     XFreePixmap(XtDisplay((Widget)tw), data->ibeam_off);
5214 
5215   XtFree((char *)data);
5216   XtFree((char *)tw->text.output);
5217   _XmProcessLock();
5218   posToXYCachedWidget = NULL;
5219   _XmProcessUnlock();
5220 }
5221 
5222 static void
5223 RedrawRegion(XmTextWidget tw,
5224 	     int x,
5225 	     int y,
5226 	     int width,
5227 	     int height)
5228 {
5229   OutputData data = tw->text.output->data;
5230   int i;
5231   XmTextPosition first, last;
5232 
5233   if(XmDirectionMatch(XmPrim_layout_direction(tw),
5234 		      XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
5235     for (i = x; i < (int) (x + width + data->linewidth); i += data->linewidth) {
5236       first = XYToPos(tw, i, y);
5237       last = XYToPos(tw, i, y + height);
5238       first = (*tw->text.source->Scan)(tw->text.source, first,
5239 					   XmSELECT_POSITION,
5240 					   XmsdLeft, 1, True);
5241       last = (*tw->text.source->Scan)(tw->text.source, last,
5242 					  XmSELECT_POSITION,
5243 					  XmsdRight, 1, True);
5244       _XmTextMarkRedraw(tw, first, last);
5245     }
5246   } else {
5247   for (i = y; i < (int) (y + height + data->lineheight);
5248               i += data->lineheight) {
5249     first = XYToPos(tw, x, i);
5250     last = XYToPos(tw, x + width, i);
5251     first = (*tw->text.source->Scan)(tw->text.source, first,
5252 					 XmSELECT_POSITION,
5253 					 XmsdLeft, 1, True);
5254     last = (*tw->text.source->Scan)(tw->text.source, last,
5255 					XmSELECT_POSITION,
5256 					XmsdRight, 1, True);
5257     _XmTextMarkRedraw(tw, first, last);
5258   }
5259   }
5260 }
5261 
5262 /* ARGSUSED */
5263 static void
5264 OutputExpose(Widget w,
5265 	     XEvent *event,
5266 	     Region region)
5267 {
5268   XmTextWidget tw = (XmTextWidget) w;
5269   XExposeEvent *xe = (XExposeEvent *) event;
5270   OutputData data = tw->text.output->data;
5271   Boolean erased_cursor = False;
5272   int old_number_lines = data->number_lines;
5273   Arg im_args[10];
5274   XRectangle xmim_area;
5275   XPoint xmim_point;
5276   int n = 0;
5277   Boolean font_may_have_changed = False;
5278   int offset = 0;
5279 
5280   if (tw->text.in_setvalues) {
5281     /* Get here via SetValues.  Force x,y of IM and clip origin for
5282      * I-beam in case font changed.
5283      */
5284     tw->text.in_setvalues = False;
5285     font_may_have_changed = True;
5286   }
5287 
5288   if (event->xany.type != Expose)
5289     return;
5290 
5291   if (XtIsSensitive(w) && data->hasfocus)
5292     _XmTextChangeBlinkBehavior(tw, False);
5293   EraseInsertionPoint(tw);
5294 
5295   if(XmDirectionMatch(XmPrim_layout_direction(tw),
5296 		      XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
5297     data->number_lines = tw->text.inner_widget->core.width -
5298       data->leftmargin - data->rightmargin;
5299     if (data->number_lines < (int) data->linewidth || !data->linewidth)
5300       data->number_lines = 1;
5301     else
5302       data->number_lines /= (int) data->linewidth;
5303 
5304     if (data->hbar && old_number_lines != data->number_lines)
5305       {
5306 	int local_total, new_size;
5307 	XmNavigatorDataRec nav_data;
5308 
5309 	data->ignorehbar = True;
5310 
5311 	if (tw->text.top_line + tw->text.number_lines >
5312 	    tw->text.total_lines)
5313 	  local_total = tw->text.top_line + tw->text.number_lines;
5314 	else
5315 	  local_total = tw->text.total_lines;
5316 
5317 	if (local_total >= tw->text.number_lines)
5318 	  new_size = tw->text.number_lines;
5319 	else
5320 	  new_size = local_total;
5321 	if (new_size + tw->text.top_line > local_total)
5322 	  new_size = local_total - tw->text.top_line;
5323 
5324         offset = local_total - (tw->text.number_lines + tw->text.top_line);
5325 	nav_data.value.x = offset;
5326 	nav_data.minimum.x = 0;
5327 	nav_data.maximum.x = local_total;
5328 	nav_data.slider_size.x = new_size;
5329 	nav_data.page_increment.x = (data->number_lines > 1)?
5330 	  (data->number_lines - 1): 1;
5331 
5332 	nav_data.dimMask = NavigDimensionX;
5333 	nav_data.valueMask = NavValue|NavMinimum|NavMaximum|
5334 	  NavSliderSize|NavPageIncrement;
5335 	_XmSFUpdateNavigatorsValue(XtParent((Widget)tw), &nav_data, True);
5336 
5337 	data->ignorehbar = False;
5338       }
5339   } else {
5340   data->number_lines = tw->text.inner_widget->core.height -
5341     data->topmargin - data->bottommargin;
5342   if (data->number_lines < (int) data->lineheight || !data->lineheight)
5343     data->number_lines = 1;
5344   else
5345     data->number_lines /= (int) data->lineheight;
5346 
5347   if (data->vbar && old_number_lines != data->number_lines)
5348     {
5349       int local_total, new_size;
5350       XmNavigatorDataRec nav_data;
5351 
5352       data->ignorevbar = True;
5353 
5354       if (tw->text.top_line + tw->text.number_lines >
5355 	  tw->text.total_lines)
5356 	local_total = tw->text.top_line + tw->text.number_lines;
5357       else
5358 	local_total = tw->text.total_lines;
5359 
5360       if (local_total >= tw->text.number_lines)
5361 	new_size = tw->text.number_lines;
5362       else
5363 	new_size = local_total;
5364       if (new_size + tw->text.top_line > local_total)
5365 	new_size = local_total - tw->text.top_line;
5366 
5367       nav_data.value.y = tw->text.top_line;
5368       nav_data.minimum.y = 0;
5369       nav_data.maximum.y = local_total;
5370       nav_data.slider_size.y = new_size;
5371       nav_data.page_increment.y = (data->number_lines > 1)?
5372 	(data->number_lines - 1): 1;
5373 
5374       nav_data.dimMask = NavigDimensionY;
5375       nav_data.valueMask = NavValue|NavMinimum|NavMaximum|
5376 	NavSliderSize|NavPageIncrement;
5377       _XmSFUpdateNavigatorsValue(XtParent((Widget)tw), &nav_data, True);
5378 
5379       data->ignorevbar = False;
5380     }
5381   }
5382 
5383   if (!data->handlingexposures) {
5384     _XmTextDisableRedisplay(tw, False);
5385     data->handlingexposures = True;
5386   }
5387   if (data->exposehscroll != 0) {
5388     xe->x = 0;
5389     xe->width = tw->core.width;
5390   }
5391   if (data->exposevscroll != 0) {
5392     xe->y = 0;
5393     xe->height = tw->core.height;
5394   }
5395   if (xe->x == 0 && xe->y == 0 && xe->width == tw->core.width &&
5396       xe->height == tw->core.height)
5397     _XmTextMarkRedraw(tw, (XmTextPosition)0, 9999999);
5398   else {
5399     if (!erased_cursor)
5400       RedrawRegion(tw, xe->x, xe->y, xe->width, xe->height);
5401   }
5402 
5403   _XmTextInvalidate(tw, (XmTextPosition) tw->text.top_character,
5404 		    (XmTextPosition) tw->text.top_character, NODELTA);
5405 
5406   _XmTextEnableRedisplay(tw);
5407 
5408   data->handlingexposures = False;
5409 
5410   _XmTextDrawShadow(tw);
5411 
5412   /* If the expose happened because of SetValues, the font may have changed.
5413    * At this point, RefigureLines has run and the tw is relayed out.
5414    * So it is safe to calculate the x,y position of the cursor to pass
5415    * to the IM.  And we can reset the clip origin so that the I-Beam will
5416    * be drawn correctly.
5417    */
5418   if (font_may_have_changed) {
5419     EraseInsertionPoint(tw);
5420     TextDrawInsertionPoint(tw);
5421     PosToXY(tw, tw->text.cursor_position, &xmim_point.x,
5422 	    &xmim_point.y);
5423     (void)_XmTextGetDisplayRect((Widget)tw, &xmim_area);
5424     XtSetArg(im_args[n], XmNspotLocation, &xmim_point); n++;
5425     XtSetArg(im_args[n], XmNarea, &xmim_area); n++;
5426     XmImSetValues(w, im_args, n);
5427   }
5428 
5429   if ((data->cursor_on < 0) || (data->blinkstate == off))
5430     data->refresh_ibeam_off = True;
5431 
5432   if (XtIsSensitive((Widget)tw) && data->hasfocus)
5433     _XmTextChangeBlinkBehavior(tw, True);
5434   TextDrawInsertionPoint(tw);
5435 }
5436 
5437 static void
5438 GetPreferredSize(Widget w,
5439 		 Dimension *width,
5440 		 Dimension *height)
5441 {
5442   XmTextWidget tw = (XmTextWidget) w;
5443   OutputData data = tw->text.output->data;
5444 
5445   SizeFromRowsCols(tw, width, height);
5446 
5447   if (data->resizewidth) {
5448     TextFindNewWidth(tw, width);
5449     if (*width < data->minwidth) *width = data->minwidth;
5450   }
5451 
5452   if (data->resizeheight) {
5453     TextFindNewHeight(tw, PASTENDPOS, height);
5454     if (*height < data->minheight) *height = data->minheight;
5455   }
5456 
5457   if (*width == 0) *width = 1;
5458   if (*height == 0) *height = 1;
5459 }
5460 
5461 /* ARGSUSED */
5462 static void
5463 HandleVBarButtonRelease(Widget w,
5464 			XtPointer closure,
5465 			XEvent *event,
5466 			Boolean *cont)
5467 {
5468   XmTextWidget tw = (XmTextWidget) closure;
5469   OutputData data = tw->text.output->data;
5470 
5471   data->suspend_hoffset = False;
5472 
5473   EraseInsertionPoint(tw);
5474   XmTextScroll((Widget) tw, 0);
5475   TextDrawInsertionPoint(tw);
5476 }
5477 
5478 
5479 /* ARGSUSED */
5480 static void
5481 HandleHBarButtonRelease(Widget w,
5482 			XtPointer closure,
5483 			XEvent *event,
5484 			Boolean *cont)
5485 {
5486   XmTextWidget tw = (XmTextWidget) closure;
5487   OutputData data = tw->text.output->data;
5488 
5489   data->suspend_voffset = False;
5490 
5491   EraseInsertionPoint(tw);
5492   XmTextScroll((Widget) tw, 0);
5493   TextDrawInsertionPoint(tw);
5494 }
5495 
5496 
5497 /************************************************************************
5498  *
5499  *  SliderMove
5500  *  Callback for the value changes of navigators.
5501  *
5502  ************************************************************************/
5503 /* ARGSUSED */
5504 static void
5505 SliderMove(Widget w,
5506 	   XtPointer closure,
5507 	   XtPointer cd)
5508 {
5509   /* w is a navigator tw */
5510 
5511   XmTextWidget tw = (XmTextWidget) closure;
5512   XmNavigatorDataRec nav_data;
5513   int offset, n;
5514   XPoint xmim_point;
5515   XRectangle xmim_area;
5516   Arg args[10];
5517   OutputData data = tw->text.output->data;
5518   int local_total = 0;
5519   int new_top = 0;
5520 
5521   /* get the navigator information using the trait getValue since I
5522      cannot use a callback struct */
5523 
5524   nav_data.valueMask = NavValue;
5525   ((XmNavigatorTrait)XmeTraitGet((XtPointer) XtClass(w), XmQTnavigator))
5526     ->getValue(w, &nav_data);
5527 
5528 
5529   /* look at the kind of navigator and make the appropriate update */
5530 
5531   if (!data->ignorehbar && (nav_data.dimMask & NavigDimensionX)) {
5532     if(XmDirectionMatch(XmPrim_layout_direction(tw),
5533 			XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
5534       data->suspend_voffset = True;
5535       tw->text.hsbar_scrolling = True;
5536       if (tw->text.top_line + tw->text.number_lines > tw->text.total_lines)
5537 	local_total = tw->text.top_line + tw->text.number_lines;
5538       else
5539 	local_total = tw->text.total_lines;
5540 
5541       new_top = local_total - nav_data.value.x - tw->text.number_lines;
5542       offset = nav_data.value.x - tw->text.top_line;
5543       tw->text.top_line = nav_data.value.x;
5544       EraseInsertionPoint(tw);
5545       XmTextScroll((Widget)tw, offset);
5546       TextDrawInsertionPoint(tw);
5547       tw->text.hsbar_scrolling = False;
5548     } else {
5549     offset = nav_data.value.x;
5550     EraseInsertionPoint(tw);
5551     ChangeHOffset(tw, offset, False);
5552     TextDrawInsertionPoint(tw);
5553     }
5554 
5555     PosToXY(tw, tw->text.cursor_position, &xmim_point.x, &xmim_point.y);
5556     (void)_XmTextGetDisplayRect((Widget)tw, &xmim_area);
5557     n = 0;
5558     XtSetArg(args[n], XmNarea, &xmim_area); n++;
5559     XtSetArg(args[n], XmNspotLocation, &xmim_point); n++;
5560     XmImSetValues(w, args, n);
5561     data->suspend_voffset = False;
5562   }
5563 
5564   if (!data->ignorevbar && (nav_data.dimMask & NavigDimensionY)) {
5565     if(XmDirectionMatch(XmPrim_layout_direction(tw),
5566 			XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
5567       offset = nav_data.value.y;
5568       EraseInsertionPoint(tw);
5569       ChangeVOffset(tw, offset, False);
5570       TextDrawInsertionPoint(tw);
5571     } else {
5572     data->suspend_hoffset = True;
5573 
5574     tw->text.vsbar_scrolling = True;
5575     offset = nav_data.value.y - tw->text.top_line;
5576     tw->text.top_line = nav_data.value.y;
5577     EraseInsertionPoint(tw);
5578     XmTextScroll((Widget)tw, offset);
5579     TextDrawInsertionPoint(tw);
5580 
5581     tw->text.vsbar_scrolling = False;
5582     }
5583     PosToXY(tw, tw->text.cursor_position, &xmim_point.x, &xmim_point.y);
5584     (void)_XmTextGetDisplayRect((Widget)tw, &xmim_area);
5585     n = 0;
5586     XtSetArg(args[n], XmNarea, &xmim_area); n++;
5587     XtSetArg(args[n], XmNspotLocation, &xmim_point); n++;
5588     XmImSetValues(w, args, n);
5589     data->suspend_hoffset = False;
5590   }
5591 
5592     /* now update the other navigator value */
5593     _XmSFUpdateNavigatorsValue(XtParent((Widget)tw), &nav_data, False);
5594 
5595 
5596 }
5597 
5598 
5599 /* Public routines. */
5600 
5601 /*****************************************************************************
5602  * To make TextOut a True "Object" this function should be a class function. *
5603  *****************************************************************************/
5604 void
5605 _XmTextOutputCreate(Widget wid,
5606 		    ArgList args,
5607 		    Cardinal num_args)
5608 {
5609   XmTextWidget tw = (XmTextWidget) wid;
5610   Output output;
5611   OutputData data;
5612   Dimension width, height;
5613   XmScrollFrameTrait scrollFrameTrait;
5614 
5615   tw->text.output = output = (Output)
5616     XtMalloc((unsigned) sizeof(OutputRec));
5617   output->data = data = (OutputData)
5618     XtMalloc((unsigned) sizeof(OutputDataRec));
5619 
5620   XtGetSubresources(wid, (XtPointer)data, NULL, NULL, output_resources,
5621 		    XtNumber(output_resources), args, num_args);
5622 
5623   if (output->data->scrollleftside == XmDYNAMIC_BOOL) {
5624     if (XmDirectionMatch(XmPrim_layout_direction(tw),
5625 			 XmTOP_TO_BOTTOM_RIGHT_TO_LEFT))
5626       output->data->scrollleftside = True;
5627     else
5628       output->data->scrollleftside = False;
5629   }
5630 
5631   output->XYToPos = XYToPos;
5632   output->PosToXY = PosToXY;
5633   output->MeasureLine = MeasureLine;
5634   output->Draw = Draw;
5635   output->DrawInsertionPoint = DrawInsertionPoint;
5636   output->MakePositionVisible = MakePositionVisible;
5637   output->MoveLines = MoveLines;
5638   output->Invalidate = OutputInvalidate;
5639   output->GetPreferredSize = GetPreferredSize;
5640   output->GetValues = OutputGetValues;
5641   output->SetValues = OutputSetValues;
5642   output->realize = OutputRealize;
5643   output->destroy = OutputDestroy;
5644   output->resize = NotifyResized;
5645   output->expose = OutputExpose;
5646 
5647   data->insertx = data->inserty = -99;
5648   data->suspend_hoffset = False;
5649   data->hoffset = 0;
5650   data->scrollwidth = 1;
5651   data->exposehscroll = data->exposevscroll = False;
5652   data->stipple_tile = _XmGetInsensitiveStippleBitmap((Widget) tw);
5653   data->add_mode_cursor = XmUNSPECIFIED_PIXMAP;
5654   data->ibeam_off = XmUNSPECIFIED_PIXMAP;
5655   data->cursor = XmUNSPECIFIED_PIXMAP;
5656   data->timerid = (XtIntervalId)0;
5657   data->font = NULL;
5658   data->scrollheight = 1;
5659   data->voffset = 0;
5660   data->suspend_voffset = False;
5661 
5662   /* copy over the fontlist/rendertable */
5663   /* Final result stored in fontlist since that's what the rest of the
5664    * code is expecting, but rendertable takes precedence since that's the
5665    * model for 2.0.
5666    */
5667   if ((data->fontlist == NULL) && (data->rendertable == NULL)) {
5668     data->fontlist =
5669       XmRenderTableCopy(XmeGetDefaultRenderTable(wid, XmTEXT_FONTLIST),
5670 			NULL, 0);
5671   }
5672   else if (data->rendertable != NULL)
5673     data->fontlist = XmRenderTableCopy(data->rendertable, NULL, 0);
5674   else data->fontlist = XmRenderTableCopy(data->fontlist, NULL, 0);
5675   if(!LoadFontMetrics(tw)) {
5676     XmFontListFree(data->fontlist);
5677     data->fontlist = XmRenderTableCopy(
5678 		       XmeGetDefaultRenderTable(wid, XmTEXT_FONTLIST), NULL, 0);
5679     (void)!LoadFontMetrics(tw);
5680   }
5681   data->rendertable = data->fontlist;
5682 
5683   data->cursorwidth = 5;
5684   data->cursorheight = data->font_ascent + data->font_descent;
5685   tw->text.inner_widget = wid;
5686   data->leftmargin = data->rightmargin = tw->text.margin_width +
5687     tw->primitive.shadow_thickness +
5688       tw->primitive.highlight_thickness;
5689   data->topmargin = data->bottommargin = tw->text.margin_height +
5690     tw->primitive.shadow_thickness +
5691       tw->primitive.highlight_thickness;
5692 
5693   /* Don't word wrap, have multiple row or have vertical scrollbars
5694      if editMode is single_line */
5695   if (tw->text.edit_mode == XmSINGLE_LINE_EDIT) {
5696     if(XmDirectionMatch(XmPrim_layout_direction(tw),
5697 			XmTOP_TO_BOTTOM_RIGHT_TO_LEFT))
5698       data->columns = 1;
5699     else
5700       data->rows = 1;
5701   }
5702 
5703   /* Don't grow in width if word wrap is on */
5704   if (tw->text.edit_mode != XmSINGLE_LINE_EDIT &&
5705       data->wordwrap) {
5706     if(XmDirectionMatch(XmPrim_layout_direction(tw),
5707 		      XmTOP_TO_BOTTOM_RIGHT_TO_LEFT))
5708         data->resizeheight = False;
5709     else
5710         data->resizewidth = False;
5711   }
5712 
5713   if (data->rows <= 0) {
5714     if (data->rows < 0)
5715       XmeWarning(wid, MSG1);
5716 
5717     if(XmDirectionMatch(XmPrim_layout_direction(tw),
5718 			XmTOP_TO_BOTTOM_RIGHT_TO_LEFT))
5719       data->rows = 20;
5720     else
5721       data->rows = 1;
5722   }
5723 
5724   if (data->columns <= 0) {
5725     if (data->columns < 0)
5726       XmeWarning(wid, MSG2);
5727 
5728     if(XmDirectionMatch(XmPrim_layout_direction(tw),
5729 			XmTOP_TO_BOTTOM_RIGHT_TO_LEFT))
5730       data->columns = 1;
5731     else
5732       data->columns = 20;
5733   }
5734 
5735   /* Initialize columns_set and rows_set for Query Geometry.  Also
5736    * used in SizeFromRowsCols().
5737    */
5738   data->columns_set = data->columns;
5739   data->rows_set = data->rows;
5740 
5741   SizeFromRowsCols(tw, &width, &height);
5742 
5743   if (tw->core.width == 0)
5744     tw->core.width = width;
5745   if (tw->core.height == 0)
5746     tw->core.height = height;
5747 
5748   /* initialize number_lines before RefigureDependentInfo() */
5749   if(XmDirectionMatch(XmPrim_layout_direction(tw),
5750 		      XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
5751     data->number_lines = tw->text.inner_widget->core.width -
5752       data->leftmargin - data->rightmargin;
5753     if (data->number_lines < (int) data->linewidth || !data->linewidth)
5754       data->number_lines = 1;
5755     else
5756       data->number_lines /= (int) data->linewidth;
5757   } else {
5758   data->number_lines = tw->text.inner_widget->core.height -
5759     data->topmargin - data->bottommargin;
5760   if (data->number_lines < (int) data->lineheight || !data->lineheight)
5761     data->number_lines = 1;
5762   else
5763     data->number_lines /= (int) data->lineheight;
5764   }
5765 
5766   if (tw->core.height != height || tw->core.width != width)
5767     RefigureDependentInfo(tw);
5768 
5769   /* reset columns_set and rows_set after RefigureDependentInfo() */
5770   data->columns_set = data->columns;
5771   data->rows_set = data->rows;
5772   data->prevW = tw->core.width;
5773   data->prevH = tw->core.height;
5774   data->minwidth = tw->core.width;
5775   data->minheight = tw->core.height;
5776 
5777   data->imagegc = NULL;
5778   data->gc = NULL;
5779   data->save_gc = NULL;
5780   data->cursor_gc = NULL;
5781   data->has_rect = False;
5782 
5783   LoadGCs(tw, tw->core.background_pixel,
5784 	  tw->primitive.foreground);
5785 
5786 
5787   /****************
5788    *
5789    * Now look at our parent and see if it's a non inited ScrollFrame.
5790    * If it is, create the navigators
5791    * and set up all the scrolling stuff using the trait.
5792    *
5793    */
5794   scrollFrameTrait = (XmScrollFrameTrait)
5795     XmeTraitGet((XtPointer) XtClass(wid->core.parent), XmQTscrollFrame);
5796 
5797   if (scrollFrameTrait != NULL &&
5798       !(scrollFrameTrait -> getInfo (wid->core.parent, NULL, NULL, NULL))) {
5799     int n;
5800     Arg arglist[30];
5801     Arg swarglist[1];
5802 
5803     /***********************
5804       set up the default move callback, so that our navigator gets
5805       associated nicely by the scrollFrame */
5806     scrollFrameTrait -> init (wid->core.parent, SliderMove, wid);
5807 
5808     if (data->scrollhorizontal) {
5809       data->resizewidth = False;
5810       data->ignorehbar = False;
5811 
5812       n = 0;
5813       /* Force to use pixels for shadowThickness */
5814       XtSetArg(arglist[n], XmNunitType, XmPIXELS); n++;
5815       XtSetArg(arglist[n], XmNshadowThickness,
5816 	       tw->primitive.shadow_thickness); n++;
5817 
5818       XtSetArg(arglist[n], XmNorientation, XmHORIZONTAL); n++;
5819 
5820       XtSetArg(arglist[n], XmNtraversalOn, False); n++;
5821       XtSetArg(arglist[n], XmNhighlightThickness, 0); n++;
5822 
5823       data->hbar = XmCreateScrollBar(XtParent(tw), "HorScrollBar",
5824 				     arglist, n);
5825 
5826       if(XmDirectionMatch(XmPrim_layout_direction(tw),
5827 			  XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
5828 	if (tw->text.edit_mode != XmSINGLE_LINE_EDIT)
5829 	  XtManageChild(data->hbar);
5830 
5831 	XtAddEventHandler(data->hbar, (EventMask)ButtonReleaseMask,
5832 			  False, HandleHBarButtonRelease, (Opaque)tw);
5833       } else
5834 	XtManageChild(data->hbar);
5835 
5836 
5837     } else data->hbar = NULL;
5838 
5839     if (data->scrollvertical) {
5840       data->resizeheight = False;
5841       data->ignorevbar = False;
5842 
5843       n = 0;
5844       /* Force to use pixels for shadowThickness */
5845       XtSetArg(arglist[n], XmNunitType, XmPIXELS); n++;
5846       XtSetArg(arglist[n], XmNshadowThickness,
5847 	       tw->primitive.shadow_thickness); n++;
5848 
5849       XtSetArg(arglist[n], XmNorientation, XmVERTICAL); n++;
5850 
5851       XtSetArg(arglist[n], XmNtraversalOn, False); n++;
5852       XtSetArg(arglist[n], XmNhighlightThickness, 0); n++;
5853 
5854 
5855       data->vbar = XmCreateScrollBar(XtParent(tw),
5856 				     "VertScrollBar", arglist, n);
5857 
5858       if(XmDirectionMatch(XmPrim_layout_direction(tw),
5859 			  XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
5860 	XtManageChild(data->vbar);
5861       } else {
5862 	if (tw->text.edit_mode != XmSINGLE_LINE_EDIT)
5863 	  XtManageChild(data->vbar);
5864 
5865 	XtAddEventHandler(data->vbar, (EventMask)ButtonReleaseMask,
5866 			  False, HandleVBarButtonRelease, (Opaque)tw);
5867       }
5868 
5869 
5870     } else data->vbar = NULL;
5871 
5872 
5873     /* Tell scrolled window parent where to put the scrollbars */
5874 
5875     if (data->scrollleftside) {
5876       if (data->scrolltopside)
5877 	XtSetArg(swarglist[0], XmNscrollBarPlacement, XmTOP_LEFT);
5878       else
5879 	XtSetArg(swarglist[0], XmNscrollBarPlacement, XmBOTTOM_LEFT);
5880     } else {
5881       if (data->scrolltopside)
5882 	XtSetArg(swarglist[0], XmNscrollBarPlacement, XmTOP_RIGHT);
5883       else
5884 	XtSetArg(swarglist[0], XmNscrollBarPlacement, XmBOTTOM_RIGHT);
5885     }
5886 
5887     XtSetValues(tw->core.parent, swarglist, 1);
5888 
5889   } else {
5890     data->vbar = NULL;
5891     data->hbar = NULL;
5892     if (XmIsScrolledWindow(XtParent(tw)) &&
5893 	(((XmScrolledWindowWidget)tw->core.parent)->swindow.VisualPolicy
5894 	 == XmCONSTANT)) {
5895       data->scrollhorizontal = False;
5896       data->scrollvertical = False;
5897       data->resizewidth = True;
5898       data->resizeheight = True;
5899     }
5900   }
5901 
5902   data->hasfocus = False;
5903   data->blinkstate = on;
5904   data->cursor_on = 0;
5905   data->refresh_ibeam_off = True;
5906   data->have_inverted_image_gc = False;
5907   data->handlingexposures = False;
5908   XtAddEventHandler((Widget) tw->text.inner_widget,
5909 		    (EventMask) FocusChangeMask|EnterWindowMask|
5910 		    LeaveWindowMask,
5911 		    False, HandleFocusEvents, (Opaque)NULL);
5912   XtAddEventHandler((Widget) tw->text.inner_widget,
5913 		    (EventMask) 0, True, HandleGraphicsExposure,
5914 		    (Opaque)NULL);
5915 }
5916 
5917 /*****************************************************************************
5918  * To make TextOut a True "Object" this function should be a class function. *
5919  *****************************************************************************/
5920 Boolean
5921 _XmTextGetBaselines(Widget w,
5922 		    Dimension ** baselines,
5923 		    int *line_count)
5924 {
5925   XmTextWidget tw = (XmTextWidget) w;
5926   OutputData data = tw->text.output->data;
5927   Dimension *base_array;
5928   int i;
5929 
5930   *line_count = data->number_lines;
5931 
5932   base_array = (Dimension *)XtMalloc((sizeof(Dimension) * (*line_count)));
5933 
5934   for (i = 0; i < *line_count; i++) {
5935     base_array[i] = data->topmargin + i * data->lineheight +
5936       data->font_ascent;
5937   }
5938 
5939   *baselines = base_array;
5940 
5941   return (True);
5942 }
5943 
5944 
5945 /*****************************************************************************
5946  * To make TextOut a True "Object" this function should be a class function. *
5947  *****************************************************************************/
5948 Boolean
5949 _XmTextGetDisplayRect(Widget w,
5950 		      XRectangle * display_rect)
5951 {
5952   XmTextWidget tw = (XmTextWidget) w;
5953   OutputData data = tw->text.output->data;
5954 
5955   (*display_rect).x = data->leftmargin;
5956   (*display_rect).y = data->topmargin;
5957   (*display_rect).width = tw->core.width -
5958     (data->leftmargin + data->rightmargin);
5959   (*display_rect).height = data->number_lines * data->lineheight;
5960 
5961   return(True);
5962 }
5963 
5964 
5965 /*****************************************************************************
5966  * To make TextOut a true "Object" this function should be a class function. *
5967  *****************************************************************************/
5968 /* ARGSUSED */
5969 void
5970 _XmTextMarginsProc(Widget w,
5971 		   XmBaselineMargins *margins_rec)
5972 {
5973   XmTextWidget tw = (XmTextWidget) w;
5974   OutputData data = tw->text.output->data;
5975 
5976   if (margins_rec->get_or_set == XmBASELINE_SET) {
5977     data->topmargin = margins_rec->margin_top +
5978       tw->primitive.shadow_thickness +
5979 	tw->primitive.highlight_thickness;
5980     _XmProcessLock();
5981     posToXYCachedWidget = NULL;
5982     _XmProcessUnlock();
5983   } else {
5984     margins_rec->margin_top = data->topmargin -
5985       (tw->primitive.shadow_thickness +
5986        tw->primitive.highlight_thickness);
5987     margins_rec->margin_bottom = data->bottommargin -
5988       (tw->primitive.shadow_thickness +
5989        tw->primitive.highlight_thickness);
5990     margins_rec->text_height =  data->font_ascent + data->font_descent;
5991     margins_rec->shadow = tw->primitive.shadow_thickness;
5992     margins_rec->highlight = tw->primitive.highlight_thickness;
5993     margins_rec->margin_height = 0;
5994   }
5995 }
5996 
5997 /*****************************************************************************
5998  * To make TextOut a True "Object" this function should be a class function. *
5999  *****************************************************************************/
6000 void
6001 _XmTextChangeHOffset(XmTextWidget tw,
6002 		     int length)
6003 {
6004   OutputData data = tw->text.output->data;
6005   Dimension margin_width = tw->text.margin_width +
6006     tw->primitive.shadow_thickness +
6007       tw->primitive.highlight_thickness;
6008   int new_offset = data->hoffset;
6009   XmTextPosition nextpos;
6010   XmTextPosition last_position;
6011   XmTextPosition temp;
6012   int inner_width, width, i;
6013   int text_width = 0;
6014   int new_text_width;
6015   XmTextBlockRec block;
6016 
6017   /* subtract margins from the offset: Fixes CR 3187 */
6018   length += (length < 0 ? (2 * margin_width) : - (2 * margin_width));
6019   new_offset += length;
6020 
6021   for (i = 0; i < tw->text.number_lines; i++) {
6022     last_position = (*tw->text.source->Scan) (tw->text.source,
6023 						  tw->text.line[i].start,
6024 						  XmSELECT_LINE,
6025 						  XmsdRight, 1, False);
6026     nextpos = (*tw->text.source->Scan)(tw->text.source,
6027 					   last_position, XmSELECT_LINE,
6028 					   XmsdRight, 1, True);
6029     if (nextpos == last_position)
6030       nextpos = PASTENDPOS;
6031     width = data->leftmargin;
6032     temp = tw->text.line[i].start;
6033     while (temp < last_position) {
6034       temp = (*tw->text.source->ReadSource)
6035 	(tw->text.source, temp, last_position, &block);
6036       width += FindWidth(tw, (Position) width, &block,
6037 			 0, block.length);
6038     }
6039     new_text_width = width - data->leftmargin;
6040     if (new_text_width > text_width) text_width = new_text_width;
6041   }
6042 
6043   inner_width = tw->core.width - (2 * margin_width);
6044   if (new_offset >= text_width - inner_width)
6045     new_offset = text_width - inner_width;
6046 
6047   ChangeHOffset(tw, new_offset, True);
6048 }
6049 
6050 
6051 /*****************************************************************************
6052  * To make TextOut a True "Object" this function should be a class function. *
6053  *****************************************************************************/
6054 void
6055 _XmTextChangeVOffset(XmTextWidget tw,
6056 		     int length)
6057 {
6058   OutputData data = tw->text.output->data;
6059   Dimension margin_height = tw->text.margin_height +
6060     tw->primitive.shadow_thickness +
6061       tw->primitive.highlight_thickness;
6062   int new_offset = data->voffset;
6063   XmTextPosition nextpos = 0;
6064   XmTextPosition last_position = 0;
6065   XmTextPosition temp = 0;
6066   int inner_height = 0, height = 0, i = 0;
6067   int text_height = 0;
6068   int new_text_height = 0;
6069   XmTextBlockRec block;
6070 
6071   /* subtract margins from the offset: Fixes CR 3187 */
6072   length += (length < 0 ? (2 * margin_height) : - (2 * margin_height));
6073   new_offset += length;
6074 
6075   for (i = 0; i < tw->text.number_lines; i++) {
6076     last_position = (*tw->text.source->Scan) (tw->text.source,
6077 						  tw->text.line[i].start,
6078 						  XmSELECT_LINE,
6079 						  XmsdRight, 1, False);
6080     nextpos = (*tw->text.source->Scan)(tw->text.source,
6081 					   last_position, XmSELECT_LINE,
6082 					   XmsdRight, 1, True);
6083     if (nextpos == last_position)
6084       nextpos = PASTENDPOS;
6085     height = data->topmargin;
6086     temp = tw->text.line[i].start;
6087     while (temp < last_position) {
6088       temp = (*tw->text.source->ReadSource)
6089 	(tw->text.source, temp, last_position, &block);
6090       height += FindHeight(tw, (Position) height, &block,
6091 			   0, block.length);
6092     }
6093     new_text_height = height - data->topmargin;
6094     if (new_text_height > text_height) text_height = new_text_height;
6095   }
6096 
6097   inner_height = tw->core.height - (2 * margin_height);
6098   if (new_offset >= text_height - inner_height)
6099     new_offset = text_height - inner_height;
6100 
6101   ChangeVOffset(tw, new_offset, True);
6102 }
6103 
6104 
6105 /*****************************************************************************
6106  * To make TextOut a true "Object" this function should be a class function. *
6107  *****************************************************************************/
6108 void
6109 _XmTextToggleCursorGC(Widget w)
6110 {
6111   XmTextWidget tw = (XmTextWidget) w;
6112   OutputData data = tw->text.output->data;
6113   InputData i_data = tw->text.input->data;
6114   XGCValues values;
6115   unsigned long valueMask;
6116   Pixmap stipple = XmUNSPECIFIED_PIXMAP;
6117 
6118   if (!XtIsRealized((Widget)tw)) return;
6119 
6120   SetFullGC(tw, data->imagegc);
6121 
6122   _XmTextResetClipOrigin(tw, tw->text.cursor_position, False);
6123 
6124 #ifdef FIX_1501
6125   if (!XtIsSensitive((Widget)tw)) {
6126     valueMask = GCForeground|GCBackground|GCFillStyle|GCStipple|GCFunction;
6127     values.foreground = _XmAssignInsensitiveColor((Widget)tw);
6128     values.background = tw->core.background_pixel;
6129     values.fill_style = FillStippled;
6130 
6131     if (i_data->overstrike) {
6132       if (data->stipple_tile == XmUNSPECIFIED_PIXMAP) return;
6133       values.stipple = data->stipple_tile;
6134       values.function = GXxor;
6135     } else {
6136       if (data->cursor == XmUNSPECIFIED_PIXMAP) return;
6137       values.stipple = data->cursor;
6138       values.function = GXcopy;
6139     }
6140   } else {
6141 #endif
6142   if (i_data->overstrike) {
6143     valueMask = GCFillStyle|GCFunction|GCForeground|GCBackground;
6144     if (XtIsSensitive(w) && !tw->text.add_mode &&
6145 	(data->hasfocus || _XmTextHasDestination(w)))
6146       values.fill_style = FillSolid;
6147     else {
6148       valueMask |= GCStipple;
6149       values.fill_style = FillStippled;
6150       values.stipple = data->stipple_tile;
6151     }
6152     values.foreground = values.background =
6153       tw->primitive.foreground ^ tw->core.background_pixel;
6154     values.function = GXxor;
6155   } else {
6156     valueMask = GCStipple;
6157     if (XGetGCValues(XtDisplay(tw), data->imagegc,
6158 		     valueMask, &values))
6159       stipple = values.stipple;
6160     valueMask = GCFillStyle|GCFunction|GCForeground|GCBackground;
6161     if (XtIsSensitive(w) && !tw->text.add_mode &&
6162 	(data->hasfocus || _XmTextHasDestination(w))) {
6163       if (stipple != data->cursor) {
6164 	values.stipple = data->cursor;
6165 	valueMask |= GCStipple;
6166       }
6167     } else
6168       if (stipple != data->add_mode_cursor) {
6169 	values.stipple = data->add_mode_cursor;
6170 	valueMask |= GCStipple;
6171       }
6172     if (tw->text.input->data->overstrike) {
6173       values.background = values.foreground =
6174 	tw->core.background_pixel ^ tw->primitive.foreground;
6175     } else if (data->have_inverted_image_gc) {
6176       values.background = tw->primitive.foreground;
6177       values.foreground = tw->core.background_pixel;
6178     } else {
6179       values.foreground = tw->primitive.foreground;
6180       values.background = tw->core.background_pixel;
6181     }
6182     values.fill_style = FillStippled;
6183     values.function = GXcopy;
6184   }
6185 #ifdef FIX_1501
6186   }
6187 #endif
6188 
6189   XSetClipMask(XtDisplay(tw), data->save_gc, None);
6190   XChangeGC(XtDisplay(tw), data->imagegc, valueMask, &values);
6191 }
6192