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 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 
28 #ifdef REV_INFO
29 #ifndef lint
30 static char rcsid[] = "$TOG: Text.c /main/47 1999/01/26 15:18:26 mgreess $"
31 #endif
32 #endif
33 #define TEXT
34 
35 #include <string.h>
36 #include <X11/Xos.h>
37 #include <X11/keysymdef.h>
38 #include <Xm/AccTextT.h>
39 #include <Xm/AtomMgr.h>
40 #include <Xm/BaseClassP.h>
41 #include <Xm/CutPaste.h>
42 #include <Xm/Display.h>
43 #include <Xm/DropSMgr.h>
44 #include <Xm/ManagerP.h>
45 #include <Xm/ScrolledW.h>
46 #include <Xm/TraitP.h>
47 #include <Xm/TransltnsP.h>
48 #include <Xm/XmosP.h>
49 #include <Xm/VaSimpleP.h>
50 #include "MessagesI.h"
51 #include "RepTypeI.h"
52 #include "TextI.h"
53 #include "TextInI.h"
54 #include "TextOutI.h"
55 #include "TextSelI.h"
56 #include "TextStrSoI.h"
57 #include "VendorSEI.h"
58 #include "XmI.h"
59 #include "XmStringI.h"
60 
61 #define FIX_1367
62 #define FIX_1147
63 /* Resolution independence conversion functions */
64 
65 #define MESSAGE2	_XmMMsgText_0000
66 
67 /* Memory Management for global line table */
68 #define INIT_TABLE_SIZE		  64
69 #define TABLE_INCREMENT		1024
70 #define XmDYNAMIC_BOOL		 255
71 
72 
73 /* Change ChangeVSB() and RedisplayHBar from TextOut.c to non-static functions;
74  * they are needed for updating the scroll bars after re-enable redisplay.
75  * DisableRedisplay prohibits the visuals of the widget from being updated
76  * as the widget's contents are changed.  If the widget is a scrolled widget,
77  * this change prohibits the scroll bars from being updated until redisplay
78  * is re-enabled.
79  */
80 extern void _XmChangeVSB(XmTextWidget widget);
81 extern void _XmRedisplayHBar(XmTextWidget widget);
82 extern void _XmChangeHSB(XmTextWidget widget);
83 extern void _XmRedisplayVBar(XmTextWidget widget);
84 
85 /********    Static Function Declarations    ********/
86 
87 static void NullAddWidget(XmTextSource source,
88 			  XmTextWidget tw);
89 
90 static void NullRemoveWidget(XmTextSource source,
91 			     XmTextWidget tw);
92 
93 static XmTextPosition NullRead(XmTextSource source,
94 			       XmTextPosition position,
95 			       XmTextPosition last_position,
96 			       XmTextBlock block);
97 
98 static XmTextStatus NullReplace(XmTextWidget tw,
99 				XEvent *event,
100 				XmTextPosition *start,
101 				XmTextPosition *end,
102 				XmTextBlock block,
103 #if NeedWidePrototypes
104 				int call_callbacks);
105 #else
106                                 Boolean call_callbacks);
107 #endif /* NeedsWidePrototypes */
108 
109 static XmTextPosition NullScan(XmTextSource source,
110                                XmTextPosition position,
111                                XmTextScanType sType,
112                                XmTextScanDirection dir,
113 			       int n,
114 #if NeedWidePrototypes
115 			       int include);
116 #else
117                                Boolean include);
118 #endif /* NeedWidePrototypes */
119 
120 static Boolean NullGetSelection(XmTextSource source,
121                                 XmTextPosition *start,
122                                 XmTextPosition *end);
123 
124 static void NullSetSelection(XmTextSource source,
125 			     XmTextPosition start,
126 			     XmTextPosition end,
127 			     Time time);
128 
129 static void _XmCreateCutBuffers(Widget w);
130 
131 static Cardinal GetSecResData(WidgetClass w_class,
132 			      XmSecondaryResourceData **secResDataRtn);
133 
134 static void ClassPartInitialize(WidgetClass wc);
135 
136 static void ClassInitialize(void);
137 
138 static void AddRedraw(XmTextWidget tw,
139 		      XmTextPosition left,
140 		      XmTextPosition right);
141 
142 static _XmHighlightRec * FindHighlight(XmTextWidget tw,
143 				       XmTextPosition position,
144 				       XmTextScanDirection dir);
145 
146 static void DisplayText(XmTextWidget tw,
147                         XmTextPosition updateFrom,
148                         XmTextPosition updateTo);
149 
150 static void RedrawChanges(XmTextWidget tw);
151 
152 static void DoMove(XmTextWidget tw,
153 		   int startcopy,
154 		   int endcopy,
155 		   int destcopy);
156 
157 static void RefigureLines(XmTextWidget tw);
158 
159 static void RemoveLines(XmTextWidget tw,
160                         int num_lines,
161                         unsigned int cur_index);
162 
163 static void AddLines(XmTextWidget tw,
164 		     XmTextLineTable temp_table,
165 		     unsigned int tmp_index,
166 		     unsigned int current_index);
167 
168 static void InitializeLineTable(XmTextWidget tw,
169 				register int size);
170 
171 static void FindHighlightingChanges(XmTextWidget tw);
172 
173 static void Redisplay(XmTextWidget tw);
174 
175 static void InsertHighlight(XmTextWidget tw,
176 			    XmTextPosition position,
177 			    XmHighlightMode mode);
178 
179 static void Initialize(Widget rw,
180 		       Widget nw,
181 		       ArgList args,
182 		       Cardinal *num_args);
183 
184 static void InitializeHook(Widget wid,
185 			   ArgList args,
186 			   Cardinal *num_args_ptr);
187 
188 static void Realize(Widget w,
189 		    XtValueMask *valueMask,
190 		    XSetWindowAttributes *attributes);
191 
192 static void Destroy(Widget w);
193 
194 static void Resize(Widget w);
195 
196 static void DoExpose(Widget w,
197 		     XEvent *event,
198 		     Region region);
199 
200 static void GetValuesHook(Widget w,
201 			  ArgList args,
202 			  Cardinal *num_args_ptr);
203 
204 static Boolean SetValues(Widget oldw,
205 			 Widget reqw,
206 			 Widget new_w,
207 			 ArgList args,
208 			 Cardinal *num_args);
209 
210 static XtGeometryResult QueryGeometry(Widget w,
211 				      XtWidgetGeometry *intended,
212 				      XtWidgetGeometry *reply);
213 
214 static void _XmTextSetString(Widget widget,
215 			     char *value);
216 
217 static XtPointer TextGetValue(Widget w,
218 			      int format);
219 
220 static void TextSetValue(Widget w,
221 			 XtPointer s,
222 			 int format);
223 
224 static int TextPreferredValue(Widget w);
225 
226 static int PreeditStart(XIC xic,
227                         XPointer client_data,
228                         XPointer call_data);
229 
230 static void PreeditDone(XIC xic,
231                         XPointer client_data,
232                         XPointer call_data);
233 
234 static void PreeditDraw(XIC xic,
235                         XPointer client_data,
236                         XIMPreeditDrawCallbackStruct *call_data);
237 
238 static void PreeditCaret(XIC xic,
239                          XPointer client_data,
240                          XIMPreeditCaretCallbackStruct *call_data);
241 
242 static void ResetUnder(XmTextWidget tw);
243 
244 /********    End Static Function Declarations    ********/
245 
246 /*
247  * For resource list management.
248  */
249 
250 static XmTextSourceRec nullsource;
251 static XmTextSource nullsourceptr = &nullsource;
252 
253 #define _XmTextEventBindings1	_XmTextIn_XmTextEventBindings1
254 #define _XmTextEventBindings2	_XmTextIn_XmTextEventBindings2
255 #define _XmTextEventBindings3	_XmTextIn_XmTextEventBindings3
256 #define _XmTextVEventBindings	_XmTextIn_XmTextVEventBindings
257 
258 #define EraseInsertionPoint(tw)\
259 {\
260   (*tw->text.output->DrawInsertionPoint)(tw, tw->text.cursor_position, off);\
261 }
262 
263 #define TextDrawInsertionPoint(tw)\
264 {\
265   (*tw->text.output->DrawInsertionPoint)(tw, tw->text.cursor_position, on);\
266 }
267 
268 static XtResource resources[] =
269 {
270   {
271     XmNsource, XmCSource, XmRPointer, sizeof(XtPointer),
272     XtOffsetOf(struct _XmTextRec, text.source),
273     XmRPointer, (XtPointer) &nullsourceptr
274   },
275 
276   {
277     XmNactivateCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
278     XtOffsetOf(struct _XmTextRec, text.activate_callback),
279     XmRCallback, NULL
280   },
281 
282   {
283     XmNfocusCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
284     XtOffsetOf(struct _XmTextRec, text.focus_callback),
285     XmRCallback, NULL
286   },
287 
288   {
289     XmNlosingFocusCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
290     XtOffsetOf(struct _XmTextRec, text.losing_focus_callback),
291     XmRCallback, NULL
292   },
293 
294   {
295     XmNvalueChangedCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
296     XtOffsetOf(struct _XmTextRec, text.value_changed_callback),
297     XmRCallback, NULL
298   },
299 
300   {
301     XmNdestinationCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
302     XtOffsetOf(struct _XmTextRec, text.destination_callback),
303     XmRCallback, NULL
304   },
305 
306   {
307     XmNmodifyVerifyCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
308     XtOffsetOf(struct _XmTextRec, text.modify_verify_callback),
309     XmRCallback, NULL
310   },
311 
312   {
313     XmNmodifyVerifyCallbackWcs, XmCCallback, XmRCallback,
314     sizeof(XtCallbackList),
315     XtOffsetOf(struct _XmTextRec, text.wcs_modify_verify_callback),
316     XmRCallback, NULL
317   },
318 
319   {
320     XmNmotionVerifyCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
321     XtOffsetOf(struct _XmTextRec, text.motion_verify_callback),
322     XmRCallback, NULL
323   },
324 
325   {
326     XmNgainPrimaryCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
327     XtOffsetOf(struct _XmTextRec, text.gain_primary_callback),
328     XmRCallback, NULL
329   },
330 
331   {
332     XmNlosePrimaryCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
333     XtOffsetOf(struct _XmTextRec, text.lose_primary_callback),
334     XmRCallback, NULL
335   },
336 
337   {
338     XmNvalue, XmCValue, XmRString, sizeof(String),
339     XtOffsetOf(struct _XmTextRec, text.value),
340     XmRString, ""
341   },
342 
343   {
344     XmNvalueWcs, XmCValueWcs, XmRValueWcs, sizeof(wchar_t*),
345     XtOffsetOf(struct _XmTextRec, text.wc_value),
346     XmRString, NULL
347   },
348 
349   {
350     XmNmaxLength, XmCMaxLength, XmRInt, sizeof(int),
351     XtOffsetOf(struct _XmTextRec, text.max_length),
352     XmRImmediate, (XtPointer) INT_MAX
353   },
354 
355   {
356     XmNmarginHeight, XmCMarginHeight, XmRVerticalDimension, sizeof(Dimension),
357     XtOffsetOf(struct _XmTextRec, text.margin_height),
358     XmRImmediate, (XtPointer) 5
359   },
360 
361   {
362     XmNmarginWidth, XmCMarginWidth, XmRHorizontalDimension, sizeof(Dimension),
363     XtOffsetOf(struct _XmTextRec, text.margin_width),
364     XmRImmediate, (XtPointer) 5
365   },
366 
367   {
368     XmNoutputCreate, XmCOutputCreate,  XmRFunction, sizeof(OutputCreateProc),
369     XtOffsetOf(struct _XmTextRec, text.output_create),
370     XmRFunction, (XtPointer) NULL
371   },
372 
373   {
374     XmNinputCreate, XmCInputCreate, XmRFunction, sizeof(InputCreateProc),
375     XtOffsetOf(struct _XmTextRec, text.input_create),
376     XmRFunction, (XtPointer) NULL
377   },
378 
379   {
380     XmNtopCharacter, XmCTopCharacter, XmRTextPosition, sizeof(XmTextPosition),
381     XtOffsetOf(struct _XmTextRec, text.top_character),
382     XmRImmediate, (XtPointer) 0
383   },
384 
385   {
386     XmNcursorPosition, XmCCursorPosition, XmRTextPosition,
387     sizeof (XmTextPosition),
388     XtOffsetOf(struct _XmTextRec, text.cursor_position),
389     XmRImmediate, (XtPointer) 0
390   },
391 
392   {
393     XmNeditMode, XmCEditMode, XmREditMode, sizeof(int),
394     XtOffsetOf(struct _XmTextRec, text.edit_mode),
395     XmRImmediate, (XtPointer) XmSINGLE_LINE_EDIT
396   },
397 
398   {
399     XmNautoShowCursorPosition, XmCAutoShowCursorPosition, XmRBoolean,
400     sizeof(Boolean),
401     XtOffsetOf(struct _XmTextRec, text.auto_show_cursor_position),
402     XmRImmediate, (XtPointer) True
403   },
404 
405   {
406     XmNeditable, XmCEditable, XmRBoolean, sizeof(Boolean),
407     XtOffsetOf(struct _XmTextRec, text.editable),
408     XmRImmediate, (XtPointer) True
409   },
410 
411   {
412     XmNverifyBell, XmCVerifyBell, XmRBoolean, sizeof(Boolean),
413     XtOffsetOf(struct _XmTextRec, text.verify_bell),
414     XmRImmediate, (XtPointer) XmDYNAMIC_BOOL
415   },
416 
417   {
418     XmNnavigationType, XmCNavigationType, XmRNavigationType,
419     sizeof (unsigned char),
420     XtOffsetOf(struct _XmPrimitiveRec, primitive.navigation_type),
421     XmRImmediate, (XtPointer) XmTAB_GROUP
422   },
423 
424   {
425     XmNtotalLines, XmCTotalLines, XmRInt,
426     sizeof (int),
427     XtOffsetOf(struct _XmTextRec, text.total_lines),
428     XmRImmediate, (XtPointer) 1
429   },
430 
431 
432 };
433 
434 /* Definition for resources that need special processing in get values */
435 
436 static XmSyntheticResource get_resources[] =
437 {
438   {
439     XmNmarginWidth,
440     sizeof(Dimension),
441     XtOffsetOf(struct _XmTextRec, text.margin_width),
442     XmeFromHorizontalPixels,
443     XmeToHorizontalPixels
444   },
445 
446   {
447     XmNmarginHeight,
448     sizeof(Dimension),
449     XtOffsetOf(struct _XmTextRec, text.margin_height),
450     XmeFromVerticalPixels,
451     XmeToVerticalPixels
452   },
453 };
454 
455 static XmBaseClassExtRec       textBaseClassExtRec = {
456   NULL,                                     /* Next extension       */
457   NULLQUARK,                                /* record type XmQmotif */
458   XmBaseClassExtVersion,                    /* version              */
459   sizeof(XmBaseClassExtRec),                /* size                 */
460   XmInheritInitializePrehook,               /* initialize prehook   */
461   XmInheritSetValuesPrehook,                /* set_values prehook   */
462   XmInheritInitializePosthook,              /* initialize posthook  */
463   XmInheritSetValuesPosthook,               /* set_values posthook  */
464   XmInheritClass,   		      	    /* secondary class      */
465   XmInheritSecObjectCreate,                 /* creation proc        */
466   GetSecResData,                	    /* getSecResData 	      */
467   {0},                                      /* fast subclass        */
468   XmInheritGetValuesPrehook,                /* get_values prehook   */
469   XmInheritGetValuesPosthook,               /* get_values posthook  */
470   XmInheritClassPartInitPrehook,            /* classPartInitPrehook */
471   XmInheritClassPartInitPosthook,           /* classPartInitPosthook*/
472   NULL,                                     /* ext_resources        */
473   NULL,                                     /* compiled_ext_resources*/
474   0,                                        /* num_ext_resources    */
475   FALSE,                                    /* use_sub_resources    */
476   XmInheritWidgetNavigable,                 /* widgetNavigable      */
477   XmInheritFocusChange,                     /* focusChange          */
478   NULL,		      		            /* wrapperData 	      */
479 };
480 
481 static XmPrimitiveClassExtRec _XmTextPrimClassExtRec = {
482   NULL,
483   NULLQUARK,
484   XmPrimitiveClassExtVersion,
485   sizeof(XmPrimitiveClassExtRec),
486   _XmTextGetBaselines,                  /* widget_baseline */
487   _XmTextGetDisplayRect,                /* widget_display_rect */
488   _XmTextMarginsProc,			/* get/set widget margins */
489 };
490 
491 externaldef(xmtextclassrec) XmTextClassRec xmTextClassRec = {
492   {
493 /* core_class fields */
494     /* superclass	  */	(WidgetClass) &xmPrimitiveClassRec,
495     /* class_name	  */	"XmText",
496     /* widget_size	  */	sizeof(XmTextRec),
497     /* class_initialize   */    ClassInitialize,
498     /* class_part_initiali*/	ClassPartInitialize,
499     /* class_inited       */	FALSE,
500     /* initialize	  */	Initialize,
501     /* initialize_hook    */	InitializeHook,
502     /* realize		  */	Realize,
503     /* actions		  */    NULL,
504     /* num_actions	  */	0,
505     /* resources	  */	resources,
506     /* num_resources	  */	XtNumber(resources),
507     /* xrm_class	  */	NULLQUARK,
508     /* compress_motion	  */	TRUE,
509     /* compress_exposure  */	XtExposeCompressMaximal,
510     /* compress_enterleave*/	TRUE,
511     /* visible_interest	  */	FALSE,
512     /* destroy		  */	Destroy,
513     /* resize		  */	Resize,
514     /* expose		  */	DoExpose,
515     /* set_values	  */	SetValues,
516     /* set_values_hook	  */	NULL,
517     /* set_values_almost  */	XtInheritSetValuesAlmost,
518     /* get_values_hook    */	GetValuesHook,
519     /* accept_focus	  */	NULL,
520     /* version		  */	XtVersion,
521     /* callback_private   */	NULL,
522     /* tm_table		  */	NULL,
523     /* query_geometry     */    QueryGeometry,
524     /* display accel	  */	NULL,
525     /* extension	  */	(XtPointer)&textBaseClassExtRec,
526   },
527 
528 /* primitive_class fields  */
529   {
530     XmInheritBorderHighlight,             /* Primitive border_highlight   */
531     XmInheritBorderUnhighlight,           /* Primitive border_unhighlight */
532     NULL,         		          /* translations                 */
533     NULL,         		          /* arm_and_activate             */
534     get_resources,	    	          /* get resources 	          */
535     XtNumber(get_resources),	          /* num get_resources            */
536     (XtPointer) &_XmTextPrimClassExtRec,  /* extension                    */
537   },
538 
539   {				/* text class fields */
540     NULL,             	        /* extension         */
541   }
542 };
543 
544 externaldef(xmtextwidgetclass) WidgetClass xmTextWidgetClass =
545 					 (WidgetClass) &xmTextClassRec;
546 
547 /****************************************************************
548  *
549  * Definitions for the null source.
550  *
551  ****************************************************************/
552 
553 /* ARGSUSED */
554 static void
NullAddWidget(XmTextSource source,XmTextWidget tw)555 NullAddWidget(XmTextSource source,
556 	      XmTextWidget tw)
557 {
558 }
559 
560 /* ARGSUSED */
561 static void
NullRemoveWidget(XmTextSource source,XmTextWidget tw)562 NullRemoveWidget(XmTextSource source,
563 		 XmTextWidget tw)
564 {
565 }
566 
567 /* ARGSUSED */
568 static XmTextPosition
NullRead(XmTextSource source,XmTextPosition position,XmTextPosition last_position,XmTextBlock block)569 NullRead(XmTextSource source,
570 	 XmTextPosition position,
571 	 XmTextPosition last_position,
572 	 XmTextBlock block)
573 {
574   block->ptr = NULL;
575   block->length = 0;
576   block->format = XmFMT_8_BIT;
577 
578   return 0;
579 }
580 
581 /* ARGSUSED */
582 static XmTextStatus
NullReplace(XmTextWidget tw,XEvent * event,XmTextPosition * start,XmTextPosition * end,XmTextBlock block,int call_callbacks)583 NullReplace(XmTextWidget tw,
584 	    XEvent * event,
585 	    XmTextPosition *start,
586 	    XmTextPosition *end,
587 	    XmTextBlock block,
588 #if NeedWidePrototypes
589 	    int call_callbacks)
590 #else
591             Boolean call_callbacks)
592 #endif
593 {
594   return EditError;
595 }
596 
597 /* ARGSUSED */
598 static XmTextPosition
NullScan(XmTextSource source,XmTextPosition position,XmTextScanType sType,XmTextScanDirection dir,int n,int include)599 NullScan(XmTextSource source,
600 	 XmTextPosition position,
601 	 XmTextScanType sType,
602 	 XmTextScanDirection dir,
603 	 int n,
604 #if NeedWidePrototypes
605 	 int include)
606 #else
607          Boolean include)
608 #endif /* NeedWidePrototypes */
609 {
610   return 0;
611 }
612 
613 /* ARGSUSED */
614 static Boolean
NullGetSelection(XmTextSource source,XmTextPosition * start,XmTextPosition * end)615 NullGetSelection(XmTextSource source,
616 		 XmTextPosition *start,
617 		 XmTextPosition *end)
618 {
619   return FALSE;
620 }
621 
622 /* ARGSUSED */
623 static void
NullSetSelection(XmTextSource source,XmTextPosition start,XmTextPosition end,Time time)624 NullSetSelection(XmTextSource source,
625 		 XmTextPosition start,
626 		 XmTextPosition end,
627 		 Time time)
628 {
629 }
630 
631 static void
_XmCreateCutBuffers(Widget w)632 _XmCreateCutBuffers(Widget w)
633 {
634   static XContext context = (XContext)NULL;
635   char * tmp = NULL;
636   Display *dpy = XtDisplay(w);
637   Screen *screen = XtScreen(w);
638   XContext local_context;
639 
640   _XmProcessLock();
641   if (context == (XContext)NULL) context = XUniqueContext();
642 
643   local_context = context;
644   _XmProcessUnlock();
645 
646   if (XFindContext(dpy, (Window)screen, local_context, &tmp)) {
647     XmTextContextData ctx_data;
648     Widget xm_display = (Widget) XmGetXmDisplay(dpy);
649 
650     ctx_data = (XmTextContextData) XtMalloc(sizeof(XmTextContextDataRec));
651 
652     ctx_data->screen = screen;
653     ctx_data->context = local_context;
654     ctx_data->type = '\0';
655 
656     XtAddCallback(xm_display, XmNdestroyCallback,
657 		  (XtCallbackProc) _XmTextFreeContextData,
658 		  (XtPointer) ctx_data);
659 
660     XChangeProperty(dpy, RootWindowOfScreen(screen), XA_CUT_BUFFER0,
661 		    XA_STRING, 8, PropModeAppend, NULL, 0);
662     XChangeProperty(dpy, RootWindowOfScreen(screen), XA_CUT_BUFFER1,
663 		    XA_STRING, 8, PropModeAppend, NULL, 0);
664     XChangeProperty(dpy, RootWindowOfScreen(screen), XA_CUT_BUFFER2,
665 		    XA_STRING, 8, PropModeAppend, NULL, 0);
666     XChangeProperty(dpy, RootWindowOfScreen(screen), XA_CUT_BUFFER3,
667 		    XA_STRING, 8, PropModeAppend, NULL, 0);
668     XChangeProperty(dpy, RootWindowOfScreen(screen), XA_CUT_BUFFER4,
669 		    XA_STRING, 8, PropModeAppend, NULL, 0);
670     XChangeProperty(dpy, RootWindowOfScreen(screen), XA_CUT_BUFFER5,
671 		    XA_STRING, 8, PropModeAppend, NULL, 0);
672     XChangeProperty(dpy, RootWindowOfScreen(screen), XA_CUT_BUFFER6,
673 		    XA_STRING, 8, PropModeAppend, NULL, 0);
674     XChangeProperty(dpy, RootWindowOfScreen(screen), XA_CUT_BUFFER7,
675 		    XA_STRING, 8, PropModeAppend, NULL, 0);
676 
677     XSaveContext(dpy, (Window)screen, local_context, tmp);
678   }
679 }
680 
681 /****************************************************************
682  *
683  * Private definitions.
684  *
685  ****************************************************************/
686 /************************************************************************
687  *
688  *  GetSecResData
689  *
690  ************************************************************************/
691 /* ARGSUSED */
692 static Cardinal
GetSecResData(WidgetClass w_class,XmSecondaryResourceData ** secResDataRtn)693 GetSecResData(WidgetClass w_class,
694 	      XmSecondaryResourceData **secResDataRtn)
695 {
696   XmSecondaryResourceData               *secResDataPtr;
697 
698   secResDataPtr =
699     (XmSecondaryResourceData *) XtMalloc(sizeof(XmSecondaryResourceData) * 2);
700 
701   _XmTextInputGetSecResData(&secResDataPtr[0]);
702   _XmTextOutputGetSecResData(&secResDataPtr[1]);
703   *secResDataRtn = secResDataPtr;
704 
705   return 2;
706 }
707 
708 /*********************************************************************/
709 /* Trait definitions                                                 */
710 /*********************************************************************/
711 
712 /* AccessXmString Trait record for Text */
713 static XmConst XmAccessTextualTraitRec TextCS = {
714   0,  				/* version */
715   TextGetValue,			/* getValue */
716   TextSetValue,			/* setValue */
717   TextPreferredValue,		/* preferredFormat */
718 };
719 
720 /****************************************************************
721  *
722  * ClassPartInitialize
723  *     Set up the fast subclassing for the widget. Set up merged
724  *     Translation table.
725  *
726  ****************************************************************/
727 static void
ClassPartInitialize(WidgetClass wc)728 ClassPartInitialize(WidgetClass wc)
729 {
730   XmTextWidgetClass twc = (XmTextWidgetClass) wc;
731   WidgetClass super;
732   XmPrimitiveClassExt *wcePtr, *scePtr;
733   char * event_bindings;
734 
735   _XmProcessLock();
736   super = twc->core_class.superclass;
737   wcePtr = _XmGetPrimitiveClassExtPtr(wc, NULLQUARK);
738   scePtr = _XmGetPrimitiveClassExtPtr(super, NULLQUARK);
739 
740   if ((*wcePtr)->widget_baseline == XmInheritBaselineProc)
741     (*wcePtr)->widget_baseline = (*scePtr)->widget_baseline;
742 
743   if ((*wcePtr)->widget_display_rect == XmInheritDisplayRectProc)
744     (*wcePtr)->widget_display_rect  = (*scePtr)->widget_display_rect;
745 
746   event_bindings = (char *)XtMalloc(strlen(_XmTextEventBindings1) +
747 				    strlen(_XmTextEventBindings2) +
748 				    strlen(_XmTextEventBindings3) + 1);
749   strcpy(event_bindings, _XmTextEventBindings1);
750   strcat(event_bindings, _XmTextEventBindings2);
751   strcat(event_bindings, _XmTextEventBindings3);
752   xmTextClassRec.core_class.tm_table =
753     (String) XtParseTranslationTable(event_bindings);
754 
755   XtFree(event_bindings);
756 
757   _XmFastSubclassInit (wc, XmTEXT_BIT);
758   _XmProcessUnlock();
759 }
760 
761 /****************************************************************
762  *
763  * ClassInitialize
764  *
765  *
766  ****************************************************************/
767 static void
ClassInitialize(void)768 ClassInitialize(void)
769 {
770   xmTextClassRec.core_class.actions =
771     (XtActionList)_XmdefaultTextActionsTable;
772   xmTextClassRec.core_class.num_actions = _XmdefaultTextActionsTableSize;
773 
774   nullsource.AddWidget = NullAddWidget;
775   nullsource.RemoveWidget = NullRemoveWidget;
776   nullsource.ReadSource = NullRead;
777   nullsource.Replace = NullReplace;
778   nullsource.Scan = NullScan;
779   nullsource.GetSelection = NullGetSelection;
780   nullsource.SetSelection = NullSetSelection;
781 
782   textBaseClassExtRec.record_type = XmQmotif;
783   /* Install traits */
784   _XmTextInstallTransferTrait();
785   XmeTraitSet((XtPointer)xmTextWidgetClass, XmQTaccessTextual,
786 	      (XtPointer) &TextCS);
787 }
788 
789 
790 /*
791  * Mark the given range of text to be redrawn.
792  */
793 static void
AddRedraw(XmTextWidget tw,XmTextPosition left,XmTextPosition right)794 AddRedraw(XmTextWidget tw,
795 	  XmTextPosition left,
796 	  XmTextPosition right)
797 {
798   RangeRec *r = tw->text.repaint.range;
799   int i;
800 
801   if (left == tw->text.last_position &&
802       tw->text.output->data->number_lines >= 1)
803     left = (*tw->text.source->Scan)(tw->text.source, left,
804 					XmSELECT_POSITION, XmsdLeft, 1, TRUE);
805 
806   if (left < right) {
807     for (i = 0; i < tw->text.repaint.number; i++) {
808       if (left <= r[i].to && right >= r[i].from) {
809 	r[i].from = MIN(left, r[i].from);
810 	r[i].to = MAX(right, r[i].to);
811 	return;
812       }
813     }
814     if (tw->text.repaint.number >= tw->text.repaint.maximum) {
815       tw->text.repaint.maximum = tw->text.repaint.number + 1;
816       tw->text.repaint.range = r = (RangeRec *)
817 	XtRealloc((char *)r, tw->text.repaint.maximum * sizeof(RangeRec));
818     }
819     r[tw->text.repaint.number].from = left;
820     r[tw->text.repaint.number].to = right;
821     tw->text.repaint.number++;
822   }
823 }
824 
825 /*
826  * Find the highlight record corresponding to the given position.  Returns a
827  * pointer to the record.  The third argument indicates whether we are probing
828  * the left or right edge of a highlighting range.
829  */
830 static _XmHighlightRec *
FindHighlight(XmTextWidget tw,XmTextPosition position,XmTextScanDirection dir)831 FindHighlight(XmTextWidget tw,
832 	      XmTextPosition position,
833 	      XmTextScanDirection dir)
834 {
835   _XmHighlightRec *l = tw->text.highlight.list;
836   int i;
837   if (dir == XmsdLeft) {
838     for (i=tw->text.highlight.number - 1; i>=0;  i--)
839       if (position >= l[i].position) {
840 	l = l + i;
841 	break;
842       }
843   } else {
844     for (i=tw->text.highlight.number - 1; i>=0; i--)
845       if (position > l[i].position) {
846 	l = l + i;
847 	break;
848       }
849   }
850   return(l);
851 }
852 
853 /*
854  * Redraw the specified range of text.  Should only be called by
855  * RedrawChanges(), below (as well as calling itself recursively).
856  */
857 static void
DisplayText(XmTextWidget tw,XmTextPosition updateFrom,XmTextPosition updateTo)858 DisplayText(XmTextWidget tw,
859 	    XmTextPosition updateFrom,
860 	    XmTextPosition updateTo)
861 {
862   LineNum i;
863   XmTextPosition nextstart;
864   _XmHighlightRec *l1, *l2;
865 
866   if (updateFrom < tw->text.top_character)
867     updateFrom = tw->text.top_character;
868   if (updateTo > tw->text.bottom_position)
869     updateTo = tw->text.bottom_position;
870   if (updateFrom > updateTo) return;
871 
872   l1 = FindHighlight(tw, updateFrom, XmsdLeft);
873   l2 = FindHighlight(tw, updateTo, XmsdRight);
874   if ( (l1 != l2) && (l1->position != l2->position) ) {
875     DisplayText(tw, updateFrom, l2->position);
876     updateFrom = l2->position;
877   }
878 
879   /*
880    * Once we get here, we need to paint all of the text from updateFrom to
881    * updateTo with current highlightmode.  We have to break this into
882    * separate lines, and then call the output routine for each line.
883    */
884 
885   for (i = _XmTextPosToLine(tw, updateFrom);
886        updateFrom <= updateTo && i < tw->text.number_lines;
887        i++) {
888     nextstart = tw->text.line[i+1].start;
889     (*tw->text.output->Draw)(tw, i, updateFrom,
890 				 MIN(updateTo, nextstart), l2->mode);
891     updateFrom = nextstart;
892   }
893 }
894 
895 /*
896  * Redraw the changed areas of the text.  This should only be called by
897  * Redisplay(), below.
898  */
899 static void
RedrawChanges(XmTextWidget tw)900 RedrawChanges(XmTextWidget tw)
901 {
902   RangeRec *r = tw->text.repaint.range;
903   XmTextPosition updateFrom, updateTo;
904   int w, i;
905 
906   EraseInsertionPoint(tw);
907 
908   while (tw->text.repaint.number != 0) {
909     updateFrom = r[0].from;
910     w = 0;
911     for (i=1; i<tw->text.repaint.number; i++) {
912       if (r[i].from < updateFrom) {
913 	updateFrom = r[i].from;
914 	w = i;
915       }
916     }
917     updateTo = r[w].to;
918     tw->text.repaint.number--;
919     r[w].from = r[tw->text.repaint.number].from;
920     r[w].to = r[tw->text.repaint.number].to;
921     for (i=tw->text.repaint.number-1; i>=0; i--) {
922       while (i < tw->text.repaint.number) {
923 	updateTo = MAX(r[i].to, updateTo);
924 	tw->text.repaint.number--;
925 	r[i].from = r[tw->text.repaint.number].from;
926 	r[i].to = r[tw->text.repaint.number].to;
927       }
928     }
929     DisplayText(tw, updateFrom, updateTo);
930   }
931   if (tw->text.first_position == tw->text.last_position) {
932     (*tw->text.output->Draw)(tw, (LineNum) 0,
933 				 tw->text.first_position,
934 				 tw->text.last_position,
935 				 XmHIGHLIGHT_NORMAL);
936   }
937   TextDrawInsertionPoint(tw);
938 }
939 
940 static void
DoMove(XmTextWidget tw,int startcopy,int endcopy,int destcopy)941 DoMove(XmTextWidget tw,
942        int startcopy,
943        int endcopy,
944        int destcopy)
945 {
946   Line line = tw->text.line;
947   LineNum i;
948 
949   EraseInsertionPoint(tw);
950   if (tw->text.disable_depth == 0 &&
951       (*tw->text.output->MoveLines)(tw, (LineNum) startcopy,
952 					(LineNum) endcopy, (LineNum) destcopy))
953     {
954       TextDrawInsertionPoint(tw);
955       return;
956     }
957   for (i=destcopy; i <= destcopy + endcopy - startcopy; i++)
958     AddRedraw(tw, line[i].start, line[i+1].start);
959   TextDrawInsertionPoint(tw);
960 }
961 
962 
963 /*
964  * Find the starting position of the line that is delta lines away from the
965  * line starting with position start.
966  */
967 XmTextPosition
_XmTextFindScroll(XmTextWidget tw,XmTextPosition start,int delta)968 _XmTextFindScroll(XmTextWidget tw,
969 		  XmTextPosition start,
970 		  int delta)
971 {
972   register XmTextLineTable line_table;
973   register unsigned int t_index;
974   register unsigned int max_index = 0;
975 
976   if (tw->text.total_lines <= tw->text.table_index)
977     tw->text.table_index = tw->text.total_lines - 1;
978 
979 
980   line_table = tw->text.line_table;
981   t_index = tw->text.table_index;
982 
983   max_index = tw->text.total_lines - 1;
984 
985 
986 
987   /* look forward to find the current record */
988   if (line_table[t_index].start_pos < (unsigned int) start) {
989     while (t_index <= max_index &&
990 	   line_table[t_index].start_pos < (unsigned int) start) t_index++;
991 	   /* special handling if last lines of text are blank */
992            if (t_index <= max_index &&
993                 (line_table[t_index].start_pos == tw->text.last_position) &&
994 	  	(tw->text.number_lines == -delta) && t_index == max_index)
995 	  	t_index++;
996   } else
997     /* look backward to find the current record */
998     while (t_index &&
999 	   line_table[t_index].start_pos > (unsigned int) start) t_index--;
1000 
1001   if (delta > 0) {
1002     t_index += delta;
1003     if (t_index > tw->text.total_lines - 1)
1004       t_index = tw->text.total_lines - 1;
1005   } else {
1006     if (t_index > -delta)
1007       t_index += delta;
1008     else
1009       t_index = 0;
1010   }
1011 
1012   start = line_table[t_index].start_pos;
1013 
1014   tw->text.table_index = t_index;
1015 
1016   return start;
1017 }
1018 
1019 /*
1020  * Refigure the line breaks in this widget.
1021  */
1022 static void
RefigureLines(XmTextWidget tw)1023 RefigureLines(XmTextWidget tw)
1024 {
1025   Line line = tw->text.line;
1026   LineNum i, j;
1027   Line oldline = NULL;
1028   static XmTextPosition tell_output_force_display = -1;
1029   int oldNumLines = tw->text.number_lines;
1030   int startcopy, endcopy, destcopy, lastcopy; /* %%% Document! */
1031 
1032   if (tw->text.in_refigure_lines || !tw->text.needs_refigure_lines)
1033     return;
1034   tw->text.in_refigure_lines = TRUE;
1035   tw->text.needs_refigure_lines = FALSE;
1036   if (XtIsRealized((Widget)tw)) EraseInsertionPoint(tw);
1037   oldline = (Line) XtMalloc((oldNumLines + 2) * sizeof(LineRec));
1038 
1039   memcpy((void *) oldline, (void *) line,
1040 	 (size_t) (oldNumLines + 1) * sizeof(LineRec));
1041 
1042 
1043   if (tw->text.pending_scroll != 0) {
1044     tw->text.new_top = _XmTextFindScroll(tw, tw->text.new_top,
1045 					     tw->text.pending_scroll);
1046     tw->text.pending_scroll = 0;
1047   }
1048   if (tw->text.new_top < tw->text.first_position)
1049     tw->text.new_top = tw->text.first_position;
1050   line[0].start = tw->text.top_character = tw->text.new_top;
1051   line[0].past_end = FALSE;
1052   line[0].extra = NULL;
1053 
1054   tw->text.number_lines = 0;
1055   j = 0;
1056   startcopy = endcopy = lastcopy = destcopy = -99;
1057   for (i = 0; i == 0 || !line[i-1].past_end; i++) {
1058     if (i+2 > tw->text.maximum_lines) {
1059       tw->text.maximum_lines = i+2;
1060       line = tw->text.line = (Line)
1061 	XtRealloc((char *)line,
1062 		  tw->text.maximum_lines * sizeof(LineRec));
1063     }
1064     while (j < oldNumLines && oldline[j].start < line[i].start)
1065       j++;
1066     if (j < oldNumLines && oldline[j].start >= oldline[j+1].start)
1067       j = oldNumLines;
1068     if (j >= oldNumLines)
1069       oldline[j].start = -1; /* Make comparisons fail. */
1070     if (line[i].start >= tw->text.forget_past ||
1071 	line[i].start != oldline[j].start ||
1072 	oldline[j].changed ||
1073 	oldline[j+1].changed) {
1074       line[i].past_end =
1075 	!(*tw->text.output->MeasureLine)(tw, i, line[i].start,
1076 					     &line[i+1].start, &line[i].extra);
1077       line[i+1].extra = NULL;
1078       if (!line[i].past_end &&
1079 	  (line[i+1].start == PASTENDPOS) &&
1080 	  (line[i].start != PASTENDPOS))
1081 	AddRedraw(tw, line[i].start, tw->text.last_position);
1082     } else {
1083       line[i] = oldline[j];
1084       oldline[j].extra = NULL;
1085       line[i].past_end =
1086 	!(*tw->text.output->MeasureLine)(tw, i, line[i].start,
1087 					     NULL, NULL);
1088 
1089       line[i+1].start = oldline[j+1].start;
1090       line[i+1].extra = oldline[j+1].extra;
1091     }
1092     if (!line[i].past_end) {
1093       if (line[i].start != oldline[j].start ||
1094 	  line[i+1].start != oldline[j+1].start ||
1095 	  line[i].start >= tw->text.forget_past) {
1096 	AddRedraw(tw, line[i].start, line[i+1].start);
1097       } else {
1098 	if (i != j && line[i+1].start >= tw->text.last_position)
1099 	  AddRedraw(tw, tw->text.last_position,
1100 		    tw->text.last_position);
1101 	if (oldline[j].changed)
1102 	  AddRedraw(tw, oldline[j].changed_position,
1103 		    line[i+1].start);
1104 	if (i != j && line[i].start != PASTENDPOS) {
1105 	  if (endcopy == j-1) {
1106 	    endcopy = j;
1107 	    lastcopy++;
1108 	  } else if (lastcopy >= 0 && j <= lastcopy) {
1109 	    /* This line was stomped by a previous move. */
1110 	    AddRedraw(tw, line[i].start, line[i+1].start);
1111 	  } else {
1112 	    if (startcopy >= 0)
1113 	      DoMove(tw, startcopy, endcopy, destcopy);
1114 	    startcopy = endcopy = j;
1115 	    destcopy = lastcopy = i;
1116 	  }
1117 	}
1118       }
1119     }
1120     line[i].changed = FALSE;
1121     if (!line[i].past_end) tw->text.number_lines++;
1122     else tw->text.bottom_position =
1123       MIN(line[i].start, tw->text.last_position);
1124   }
1125   if (startcopy >= 0) {
1126     DoMove(tw, startcopy, endcopy, destcopy);
1127   }
1128   for (j=0; j<=oldNumLines; j++)
1129     if (oldline[j].extra) {
1130       XtFree((char *) oldline[j].extra);
1131       oldline[j].extra = NULL;
1132     }
1133 
1134   XtFree((char *)oldline); /* XTHREADS */
1135   tw->text.in_refigure_lines = FALSE;
1136   if (tw->text.top_character >= tw->text.last_position &&
1137       tw->text.last_position > tw->text.first_position &&
1138       tw->text.output->data->number_lines > 1) {
1139     tw->text.pending_scroll = -1; /* Try to not ever display nothing. */
1140     tw->text.needs_refigure_lines = TRUE;
1141   }
1142   if (tw->text.force_display >= 0) {
1143     if (tw->text.force_display < tw->text.top_character) {
1144       if (tw->text.force_display > tw->text.first_position)
1145         tw->text.new_top = tw->text.force_display + 1 ;
1146       else
1147         tw->text.new_top = tw->text.first_position;
1148       tw->text.pending_scroll--;
1149     } else if (tw->text.force_display > tw->text.bottom_position) {
1150       /* need to add one to account for border condition,
1151        * i.e. cursor at begginning of line
1152        */
1153       if (tw->text.force_display < tw->text.last_position)
1154 	tw->text.new_top = tw->text.force_display + 1;
1155       else
1156 	tw->text.new_top = tw->text.last_position;
1157       tw->text.pending_scroll -= tw->text.number_lines;
1158     } else if (tw->text.force_display ==
1159 	       line[tw->text.number_lines].start) {
1160       tw->text.new_top = tw->text.force_display;
1161       tw->text.pending_scroll -= (tw->text.number_lines - 1);
1162     }
1163     tw->text.needs_refigure_lines = TRUE;
1164     _XmProcessLock();
1165     tell_output_force_display = tw->text.force_display;
1166     _XmProcessUnlock();
1167     tw->text.force_display = -1;
1168   }
1169   if (tw->text.needs_refigure_lines) {
1170     RefigureLines(tw);
1171     if (XtIsRealized((Widget)tw)) TextDrawInsertionPoint(tw);
1172     return;
1173   }
1174   AddRedraw(tw, tw->text.forget_past, tw->text.bottom_position);
1175   tw->text.forget_past = LONG_MAX;
1176   _XmProcessLock();
1177   if (tell_output_force_display >= 0) {
1178     (*tw->text.output->MakePositionVisible)(tw,
1179 					tell_output_force_display);
1180     tell_output_force_display = -1;
1181   }
1182   _XmProcessUnlock();
1183   if (XtIsRealized((Widget)tw)) TextDrawInsertionPoint(tw);
1184 }
1185 
1186 /************************************************************************
1187  *
1188  * RemoveLines() - removes the lines from the global line table.
1189  *      widget - the widget that contains the global table.
1190  *      num_lines - number of lines to be removed.
1191  *      cur_line - pointer to the start of the lines to be removed.
1192  *
1193  ************************************************************************/
1194 /* ARGSUSED */
1195 static void
RemoveLines(XmTextWidget tw,int num_lines,unsigned int cur_index)1196 RemoveLines(XmTextWidget tw,
1197 	    int num_lines,
1198 	    unsigned int cur_index)
1199 {
1200   if (!num_lines) return;
1201 
1202   /* move the existing lines at the end of the buffer */
1203   if (tw->text.total_lines > cur_index)
1204     memmove((void *) &tw->text.line_table[cur_index - num_lines],
1205 	    (void *) &tw->text.line_table[cur_index],
1206 	    (size_t) ((tw->text.total_lines - (cur_index)) *
1207 		      sizeof (XmTextLineTableRec)));
1208 
1209   /* reduce total line count */
1210   tw->text.total_lines -= num_lines;
1211 
1212   /* fix for bug 5166 */
1213   if (tw->text.total_lines <= tw->text.table_index)
1214     tw->text.table_index = tw->text.total_lines - 1;
1215 
1216 
1217   /* Shrink Table if Necessary */
1218   if ((tw->text.table_size > TABLE_INCREMENT &&
1219        tw->text.total_lines <= tw->text.table_size-TABLE_INCREMENT) ||
1220       tw->text.total_lines <= tw->text.table_size >> 1) {
1221 
1222     tw->text.table_size = INIT_TABLE_SIZE;
1223 
1224     while (tw->text.total_lines >= tw->text.table_size) {
1225       if (tw->text.table_size < TABLE_INCREMENT)
1226 	tw->text.table_size *= 2;
1227       else
1228 	tw->text.table_size += TABLE_INCREMENT;
1229     }
1230 
1231     tw->text.line_table = (XmTextLineTable)
1232       XtRealloc((char *) tw->text.line_table,
1233 		tw->text.table_size * sizeof(XmTextLineTableRec));
1234   }
1235 }
1236 
1237 static void
AddLines(XmTextWidget tw,XmTextLineTable temp_table,unsigned int tmp_index,unsigned int current_index)1238 AddLines(XmTextWidget tw,
1239 	 XmTextLineTable temp_table,
1240 	 unsigned int tmp_index,
1241 	 unsigned int current_index)
1242 {
1243   register unsigned int i;
1244   register unsigned int size_needed;
1245   register unsigned int cur_index;
1246   register unsigned int temp_index;
1247 
1248   cur_index = current_index;
1249   temp_index = tmp_index;
1250   size_needed = tw->text.total_lines + temp_index;
1251 
1252   /* make sure table is big enough to handle the additional lines */
1253   if (tw->text.table_size < size_needed) {
1254     while (tw->text.table_size < size_needed)
1255       if (tw->text.table_size < TABLE_INCREMENT)
1256 	tw->text.table_size *= 2;
1257       else
1258 	tw->text.table_size += TABLE_INCREMENT;
1259     tw->text.line_table = (XmTextLineTable)
1260       XtRealloc((char *) tw->text.line_table,
1261 		tw->text.table_size * sizeof(XmTextLineTableRec));
1262   }
1263 
1264   /* move the existing lines at the end of the buffer */
1265   if (tw->text.total_lines > cur_index)
1266     memmove((void *) &tw->text.line_table[cur_index + temp_index],
1267 	    (void *) &tw->text.line_table[cur_index],
1268 	    (size_t) ((tw->text.total_lines - cur_index) *
1269 		      sizeof (XmTextLineTableRec)));
1270 
1271   tw->text.total_lines += temp_index;
1272 
1273   /* Add the lines from the temp table */
1274   if (temp_table)
1275     for (i = 0; i < temp_index; i++, cur_index++)
1276       tw->text.line_table[cur_index] = temp_table[i];
1277 }
1278 
1279 void
_XmTextRealignLineTable(XmTextWidget tw,XmTextLineTable * temp_table,int * temp_table_size,register unsigned int cur_index,register XmTextPosition cur_start,register XmTextPosition cur_end)1280 _XmTextRealignLineTable(XmTextWidget tw,
1281 			XmTextLineTable *temp_table,
1282 			int *temp_table_size,
1283 			register unsigned int cur_index,
1284 			register XmTextPosition cur_start,
1285 			register XmTextPosition cur_end)
1286 
1287 {
1288   register int table_size;
1289   register XmTextPosition line_end;
1290   register XmTextPosition next_start;
1291   XmTextLineTable line_table;
1292 
1293   if (temp_table) {
1294     line_table = *temp_table;
1295     table_size = *temp_table_size;
1296   } else {
1297     line_table = tw->text.line_table;
1298     table_size = tw->text.table_size;
1299   }
1300 
1301   line_table[cur_index].start_pos = next_start = cur_start;
1302   cur_index++;
1303 
1304   line_end = (*tw->text.source->Scan)(tw->text.source, cur_start,
1305 					  XmSELECT_LINE, XmsdRight, 1, TRUE);
1306   while (next_start < cur_end) {
1307     if (_XmTextShouldWordWrap(tw))
1308       next_start = _XmTextFindLineEnd(tw, cur_start, NULL);
1309     else {
1310       if (cur_start != line_end)
1311 	next_start = line_end;
1312       else
1313 	next_start = PASTENDPOS;
1314     }
1315     if (next_start == PASTENDPOS || next_start == cur_end) break;
1316     if (next_start == cur_start)
1317       next_start = (*tw->text.source->Scan) (tw->text.source,
1318 						 cur_start, XmSELECT_POSITION,
1319 						 XmsdRight, 1, TRUE);
1320     if (cur_index >= table_size) {
1321       if (table_size < TABLE_INCREMENT)
1322 	table_size *= 2;
1323       else
1324 	table_size += TABLE_INCREMENT;
1325 
1326       line_table = (XmTextLineTable) XtRealloc((char *)line_table,
1327 					       table_size *
1328 					       sizeof(XmTextLineTableRec));
1329     }
1330     line_table[cur_index].start_pos = (unsigned int) next_start;
1331     if (line_end == next_start) {
1332       line_table[cur_index].virt_line = 0;
1333       line_end = (*tw->text.source->Scan)(tw->text.source,
1334 					      next_start, XmSELECT_LINE,
1335 					      XmsdRight, 1, TRUE);
1336     } else
1337       line_table[cur_index].virt_line = 1;
1338     cur_index++;
1339     cur_start = next_start;
1340   }
1341 
1342   if (temp_table) {
1343     *temp_table = line_table;
1344     *temp_table_size = cur_index;
1345   } else {
1346     tw->text.total_lines = cur_index;
1347     tw->text.line_table = line_table;
1348     tw->text.table_size = table_size;
1349   }
1350 }
1351 
1352 static void
InitializeLineTable(XmTextWidget tw,register int size)1353 InitializeLineTable(XmTextWidget tw,
1354 		    register int size)
1355 {
1356   register unsigned int t_index;
1357   register XmTextLineTable line_table;
1358 
1359   line_table = (XmTextLineTable) XtMalloc(size * sizeof(XmTextLineTableRec));
1360 
1361   for (t_index = 0; t_index < size; t_index++) {
1362     line_table[t_index].start_pos = 0;
1363     line_table[t_index].virt_line = 0;
1364   }
1365 
1366   tw->text.line_table = line_table;
1367   tw->text.table_index = 0;
1368   tw->text.table_size = size;
1369 }
1370 
1371 unsigned int
_XmTextGetTableIndex(XmTextWidget tw,XmTextPosition pos)1372 _XmTextGetTableIndex(XmTextWidget tw,
1373 		     XmTextPosition pos)
1374 {
1375   register XmTextLineTable line_table;
1376   register unsigned int cur_index;
1377   register unsigned int max_index;
1378   register XmTextPosition position;
1379 
1380   position = pos;
1381   max_index = tw->text.total_lines - 1;
1382   line_table = tw->text.line_table;
1383   cur_index = tw->text.table_index;
1384 
1385   /* look forward to find the current record */
1386   if (line_table[cur_index].start_pos < (unsigned int) position) {
1387     while (cur_index < max_index &&
1388 	   line_table[cur_index].start_pos < (unsigned int) position)
1389       cur_index++;
1390     /* if over shot it by one */
1391     if ((unsigned int) position < line_table[cur_index].start_pos) cur_index--;
1392   } else
1393     /* look backward to find the current record */
1394     while (cur_index &&
1395 	   line_table[cur_index].start_pos > (unsigned int) position)
1396       cur_index--;
1397 
1398   return (cur_index);
1399 }
1400 
1401 
1402 
1403 void
_XmTextUpdateLineTable(Widget widget,XmTextPosition start,XmTextPosition end,XmTextBlock block,int update)1404 _XmTextUpdateLineTable(Widget widget,
1405 		       XmTextPosition start,
1406 		       XmTextPosition end,
1407 		       XmTextBlock block,
1408 #if NeedWidePrototypes
1409 		       int update)
1410 #else
1411                        Boolean update)
1412 #endif /* NeedWidePrototypes */
1413 {
1414   register unsigned int cur_index;
1415   register unsigned int begin_index;
1416   register unsigned int end_index;
1417   register XmTextLineTable line_table;
1418   register unsigned int max_index;
1419   register int lines_avail;
1420   register int length;
1421   register long delta;
1422   unsigned int start_index;
1423   unsigned int top_index;
1424   XmTextWidget tw = (XmTextWidget) widget;
1425   Boolean word_wrap = _XmTextShouldWordWrap(tw);
1426   XmTextPosition cur_start, cur_end;
1427   int diff = 0;
1428   int block_num_chars = 0;
1429   int char_size = 0;
1430 
1431   lines_avail = 0;
1432   max_index = tw->text.total_lines - 1;
1433   if (tw->text.char_size != 1)
1434     block_num_chars = _XmTextCountCharacters(block->ptr, block->length);
1435   else
1436     block_num_chars = block->length;
1437   delta = block_num_chars - (end - start);
1438   length = block_num_chars;
1439 
1440   if (tw->text.line_table == NULL)
1441   {
1442     if (tw->text.edit_mode == XmSINGLE_LINE_EDIT)
1443     {
1444       InitializeLineTable(tw, 1);
1445     }
1446     else
1447     {
1448       InitializeLineTable(tw, INIT_TABLE_SIZE);
1449     }
1450   }
1451   /* if there is no change or we expect RelignLineTable()
1452      to be called before the line table is necessary */
1453   if ((start == end && length == 0) ||
1454       (word_wrap && !XtIsRealized(widget)
1455        && XmIsScrolledWindow(XtParent(widget))
1456        && XtIsShell(XtParent(XtParent(widget))))) {
1457     return;
1458   }
1459 
1460   line_table = tw->text.line_table;
1461 
1462   cur_index = _XmTextGetTableIndex(tw, start);
1463   top_index = _XmTextGetTableIndex(tw, tw->text.top_character);
1464 
1465   begin_index = start_index = end_index = cur_index;
1466 
1467   if (word_wrap && delta > 0)
1468     cur_end = end + delta;
1469   else
1470     cur_end = end;
1471 
1472   /* Find the cur_end position.
1473      Count the number of lines that were deleted. */
1474   if (end > start) {
1475     if (end_index < tw->text.total_lines) {
1476       while (end_index < max_index &&
1477 	     line_table[end_index + 1].start_pos <= (unsigned int) cur_end) {
1478 	end_index++;
1479 	lines_avail++;
1480       }
1481     } else if (line_table[end_index].start_pos > (unsigned int) start &&
1482 	       line_table[end_index].start_pos <= (unsigned int) cur_end) {
1483       lines_avail++;
1484     }
1485   }
1486 
1487   cur_index = end_index;
1488 
1489   if (word_wrap) {
1490     register int i;
1491     XmTextLineTable temp_table = NULL;
1492     int temp_table_size = 0;
1493 
1494     if (line_table[start_index].virt_line) start_index--;
1495 
1496     begin_index = start_index;
1497 
1498     /* get the start position of the line at the start index. */
1499     cur_start = line_table[begin_index].start_pos;
1500 
1501     /* If we are not at the end of the table, */
1502     if (cur_index < max_index) {
1503 
1504       /* find the next non-wordwrapped line. */
1505       while (cur_index < max_index) {
1506 	cur_index++;
1507 	if (!line_table[cur_index].virt_line) break;
1508       }
1509 
1510       /* Continue only if we have found a non-wordwrapped line. */
1511       if (!line_table[cur_index].virt_line) {
1512 
1513 	  /* Set the cur_end position to the position of
1514 	     the next non-wordwrapped line. */
1515 	  cur_end = line_table[cur_index].start_pos;
1516 	  /* estimate the temp table size - in number of lines */
1517 	  temp_table_size = cur_index - begin_index;
1518 	  /* make sure the size is not zero */
1519 	  if (!temp_table_size) temp_table_size++;
1520 	  /* do initial allocation of the temp_table */
1521 	  temp_table = (XmTextLineTable) XtMalloc(temp_table_size *
1522 						  sizeof(XmTextLineTableRec));
1523 	  /* Determine the lines that have changed. */
1524 	  _XmTextRealignLineTable(tw, &temp_table, &temp_table_size,
1525 				  0, cur_start, cur_end + delta);
1526 
1527 	  /* Compute the difference in the number of lines that have changed */
1528 	  diff = temp_table_size - (cur_index - begin_index);
1529 
1530 	  /* if new/wrapped lines were added, push line down*/
1531 	  if (diff > 0)
1532 	      AddLines(tw, NULL, diff, cur_index);
1533 	  /* if new/wrapped lines were deleted, move line up */
1534 	  else
1535 	      RemoveLines(tw, -diff, cur_index);
1536 
1537 	  /*
1538 	   * The line table may have been realloc'd in any of the three
1539 	   * previous function calls, so it must be reassigned to prevent
1540 	   * a stale pointer.
1541 	   */
1542 	  line_table = tw->text.line_table;
1543 
1544 	  /* Bypass the first entry in the temp_table */
1545 	  begin_index++;
1546 
1547 	  /* Add the lines from the temp table */
1548 	  for (i = 1; i < temp_table_size; i++, begin_index++)
1549 	      line_table[begin_index] = temp_table[i];
1550 
1551 	  /* Free temp table */
1552 	  XtFree((char *)temp_table);
1553 
1554 	  /* Adjust the cur_index by the number of lines that changed. */
1555 	  cur_index += diff;
1556 	  max_index += diff;
1557 
1558 	  /* Adjust start values in table by the amount of change */
1559 	  while (cur_index <= max_index) {
1560 	      line_table[cur_index].start_pos += delta;
1561 	      cur_index++;
1562 	  }
1563       } else
1564 	  /* we are at the end of the table */
1565 	  _XmTextRealignLineTable(tw, NULL, 0, begin_index,
1566 				  cur_start, PASTENDPOS);
1567 
1568     } else
1569       /* add lines to the end */
1570       _XmTextRealignLineTable(tw, NULL, 0, begin_index,
1571 			      cur_start, PASTENDPOS);
1572   } else {
1573     register char *ptr;
1574     register XmTextLineTable temp_table;
1575     register int temp_table_size;
1576     register int temp_index;
1577 
1578     temp_table = NULL;
1579     temp_table_size = 0;
1580     temp_index = 0;
1581     ptr = block->ptr;
1582     cur_start = start;
1583 
1584     while (cur_index < max_index) {
1585       cur_index++;
1586       line_table[cur_index].start_pos += delta;
1587     }
1588 
1589     if (tw->text.char_size == 1) {
1590       char *nl;
1591       while (length > 0 && (nl = (char *)memchr(ptr, '\012', length)) != NULL) {
1592 	nl++;
1593 	cur_start += (nl - ptr);
1594 	length -= (nl - ptr);
1595 	ptr = nl;
1596 	if (lines_avail && begin_index < tw->text.total_lines) {
1597 	  begin_index++;
1598 	  lines_avail--;
1599 	  line_table[begin_index].start_pos = (unsigned int)cur_start;
1600 	} else {
1601 	  if (temp_index >= temp_table_size) {
1602 	    if (!temp_table_size) {
1603 	      if (tw->text.output->data->columns > 1) {
1604 		temp_table_size = length /
1605 		  (tw->text.output->data->columns / 2);
1606 		if (!temp_table_size) temp_table_size = 1;
1607 	      } else {
1608 		if (length)
1609 		  temp_table_size = length;
1610 		else
1611 		  temp_table_size = 1;
1612 	      }
1613 	    } else
1614 	      temp_table_size *= 2;
1615 	    temp_table = (XmTextLineTable)XtRealloc((char*)temp_table,
1616 				  temp_table_size * sizeof(XmTextLineTableRec));
1617 	  }
1618 	  temp_table[temp_index].start_pos = (unsigned int) cur_start;
1619 	  temp_table[temp_index].virt_line = (unsigned int) 0;
1620 	  temp_index++;
1621 	}
1622       }
1623     } else {
1624       while (length--) {
1625 #ifndef NO_MULTIBYTE
1626 	char_size = mblen(ptr, tw->text.char_size);
1627 	if (char_size < 0) break; /* error */
1628 #else
1629 	char_size = *ptr ? 1 : 0;
1630 #endif
1631 	cur_start++;
1632 	if (char_size == 1 && *ptr == '\012') {
1633 	  ptr++;
1634 	  if (lines_avail && begin_index < tw->text.total_lines) {
1635 	    begin_index++;
1636 	    lines_avail--;
1637 	    line_table[begin_index].start_pos = (unsigned int)cur_start;
1638 	  } else {
1639 	    if (temp_index >= temp_table_size) {
1640 	      if (!temp_table_size) {
1641 		if (tw->text.output->data->columns > 1) {
1642 		  temp_table_size = length /
1643 		    (tw->text.output->data->columns / 2);
1644 		  if (!temp_table_size) temp_table_size = 1;
1645 		} else {
1646 		  if (length)
1647 		    temp_table_size = length;
1648 		  else
1649 		    temp_table_size = 1;
1650 		}
1651 	      } else
1652 		temp_table_size *= 2;
1653 	      temp_table =(XmTextLineTable)XtRealloc((char*)temp_table,
1654                                temp_table_size * sizeof(XmTextLineTableRec));
1655 	    }
1656 	    temp_table[temp_index].start_pos = (unsigned int) cur_start;
1657 	    temp_table[temp_index].virt_line = (unsigned int) 0;
1658 	    temp_index++;
1659 	  }
1660 	} else {
1661 	  ptr += char_size;
1662 	}
1663       }
1664     }
1665 
1666     /* add a block of lines to the line table */
1667     if (temp_index) {
1668       AddLines(tw, temp_table, temp_index, begin_index + 1);
1669     }
1670 
1671     /* remove lines that are no longer necessary */
1672     if (lines_avail) {
1673       RemoveLines(tw, lines_avail, end_index + 1);
1674     }
1675 
1676     /*
1677      * The line table may have been realloc'd in any of the three
1678      * previous function calls, so it must be reassigned to prevent
1679      * a stale pointer.
1680      */
1681     line_table = tw->text.line_table;
1682 
1683     diff = temp_index - lines_avail;
1684 
1685     if (temp_table) XtFree((char *)temp_table);
1686   }
1687 
1688   if (update) {
1689     if (start < tw->text.top_character) {
1690       if (end < tw->text.top_character) {
1691 	tw->text.top_line += diff;
1692 	tw->text.new_top = tw->text.top_character + delta;
1693       } else {
1694 	int adjusted;
1695 	if (diff < 0)
1696 	  adjusted = diff + (top_index - start_index);
1697 	else
1698 	  adjusted = diff - (top_index - start_index);
1699 	tw->text.top_line += adjusted;
1700 	if (adjusted + (int) start_index <= 0) {
1701 	  tw->text.new_top = 0;
1702 	} else if (adjusted + start_index > max_index) {
1703 	  tw->text.new_top = line_table[max_index].start_pos;
1704 	} else {
1705 	  tw->text.new_top = line_table[start_index + adjusted].start_pos;
1706 	}
1707       }
1708       tw->text.top_character = tw->text.new_top;
1709       tw->text.forget_past = MIN(tw->text.forget_past, tw->text.new_top);
1710 
1711       tw->text.top_line = _XmTextGetTableIndex(tw, tw->text.new_top);
1712 
1713       if (tw->text.top_line < 0)
1714 	tw->text.top_line = 0;
1715 
1716       if (tw->text.top_line > tw->text.total_lines)
1717 	tw->text.top_line = tw->text.total_lines - 1;
1718     }
1719 
1720     if (tw->text.table_index > tw->text.total_lines)
1721       tw->text.table_index = tw->text.total_lines;
1722 
1723 #ifdef FIX_1367
1724     if (tw->text.on_or_off == on) {
1725       XmTextPosition cursorPos = tw->text.cursor_position;
1726       if (start < tw->text.cursor_position) {
1727         if (tw->text.cursor_position < end) {
1728 	  if (tw->text.cursor_position - start <= block_num_chars)
1729 	    cursorPos = tw->text.cursor_position;
1730 	  else
1731 	    cursorPos = start + block_num_chars;
1732         } else {
1733 	  cursorPos = tw->text.cursor_position - (end - start) + block_num_chars;
1734         }
1735         _XmTextSetCursorPosition(widget, cursorPos);
1736       } else if (start == tw->text.cursor_position && tw->text.auto_show_cursor_position) {
1737         _XmTextShowPosition((Widget)tw, cursorPos);
1738       }
1739     }
1740 #else
1741     if (start < tw->text.cursor_position && tw->text.on_or_off == on) {
1742       XmTextPosition cursorPos = tw->text.cursor_position;
1743       if (tw->text.cursor_position < end) {
1744 	if (tw->text.cursor_position - start <= block_num_chars)
1745 	  cursorPos = tw->text.cursor_position;
1746 	else
1747 	  cursorPos = start + block_num_chars;
1748       } else {
1749 	cursorPos = tw->text.cursor_position - (end - start) +
1750 	  block_num_chars;
1751       }
1752       _XmTextSetCursorPosition(widget, cursorPos);
1753     }
1754 #endif
1755   }
1756 }
1757 
1758 
1759 /*
1760  * Compare the old_highlight list and the highlight list, determine what
1761  * changed, and call AddRedraw with the changed areas.
1762  */
1763 static void
FindHighlightingChanges(XmTextWidget tw)1764 FindHighlightingChanges(XmTextWidget tw)
1765 {
1766   int n1 = tw->text.old_highlight.number;
1767   int n2 = tw->text.highlight.number;
1768   _XmHighlightRec *l1 = tw->text.old_highlight.list;
1769   _XmHighlightRec *l2 = tw->text.highlight.list;
1770   int i1, i2;
1771   XmTextPosition next1, next2, last_position;
1772 
1773   i1 = i2 = 0;
1774   last_position = 0;
1775   while (i1 < n1 && i2 < n2) {
1776     if (i1 < n1-1) next1 = l1[i1+1].position;
1777     else next1 = tw->text.last_position;
1778     if (i2 < n2-1) next2 = l2[i2+1].position;
1779     else next2 = tw->text.last_position;
1780     if (l1[i1].mode != l2[i2].mode) {
1781       AddRedraw(tw, last_position, MIN(next1, next2));
1782     }
1783     last_position = MIN(next1, next2);
1784     if (next1 <= next2) i1++;
1785     if (next1 >= next2) i2++;
1786   }
1787 }
1788 
1789 /*
1790  * Actually do some work.  This routine gets called to actually paint all the
1791  * stuff that has been pending. Prevent recursive calls and text redisplays
1792  * during destroys
1793  */
1794 static void
Redisplay(XmTextWidget tw)1795 Redisplay(XmTextWidget tw)
1796 {
1797    /* Prevent recursive calls or text redisplay during detroys. */
1798   if (tw->text.in_redisplay || tw->core.being_destroyed ||
1799       tw->text.disable_depth != 0 || !XtIsRealized((Widget)tw)) return;
1800 
1801   EraseInsertionPoint(tw);
1802 
1803   tw->text.in_redisplay = TRUE;
1804 
1805   if (tw->text.needs_refigure_lines) RefigureLines(tw);
1806   tw->text.needs_redisplay = FALSE;
1807 
1808   if (tw->text.highlight_changed) {
1809     FindHighlightingChanges(tw);
1810     tw->text.highlight_changed = FALSE;
1811   }
1812 
1813   RedrawChanges(tw);
1814 
1815   /* Can be caused by auto-horiz scrolling... */
1816   if (tw->text.needs_redisplay) {
1817     RedrawChanges(tw);
1818     tw->text.needs_redisplay = FALSE;
1819   }
1820   tw->text.in_redisplay = FALSE;
1821 
1822   TextDrawInsertionPoint(tw);
1823 }
1824 
1825 
1826 
1827 /****************************************************************
1828  *
1829  * Definitions exported to output.
1830  *
1831  ****************************************************************/
1832 
1833 /*
1834  * Mark the given range of text to be redrawn.
1835  */
1836 
1837 void
_XmTextMarkRedraw(XmTextWidget tw,XmTextPosition left,XmTextPosition right)1838 _XmTextMarkRedraw(XmTextWidget tw,
1839 		  XmTextPosition left,
1840 		  XmTextPosition right)
1841 {
1842   if (left < right) {
1843     AddRedraw(tw, left, right);
1844     tw->text.needs_redisplay = TRUE;
1845     if (tw->text.disable_depth == 0) Redisplay(tw);
1846   }
1847 }
1848 
1849 
1850 /*
1851  * Return the number of lines in the linetable.
1852  */
1853 LineNum
_XmTextNumLines(XmTextWidget tw)1854 _XmTextNumLines(XmTextWidget tw)
1855 {
1856   if (tw->text.needs_refigure_lines) RefigureLines(tw);
1857   return tw->text.number_lines;
1858 }
1859 
1860 void
_XmTextLineInfo(XmTextWidget tw,LineNum line,XmTextPosition * startpos,LineTableExtra * extra)1861 _XmTextLineInfo(XmTextWidget tw,
1862 		LineNum line,
1863 		XmTextPosition *startpos,
1864 		LineTableExtra *extra)
1865 {
1866   if (tw->text.needs_refigure_lines) RefigureLines(tw);
1867   if (tw->text.number_lines >= line) {
1868     if (startpos) *startpos = tw->text.line[line].start;
1869     if (extra) *extra = tw->text.line[line].extra;
1870   } else {
1871     if (startpos) {
1872       unsigned int cur_index =
1873 	_XmTextGetTableIndex(tw, tw->text.line[line - 1].start);
1874       if (cur_index < tw->text.total_lines - 1)
1875 	*startpos = tw->text.line_table[cur_index + 1].start_pos;
1876       else
1877 	*startpos = tw->text.last_position;
1878     }
1879     if (extra) *extra = NULL;
1880   }
1881 }
1882 
1883 /*
1884  * Return the line number containing the given position.  If text currently
1885  * knows of no line containing that position, returns NOLINE.
1886  */
1887 LineNum
_XmTextPosToLine(XmTextWidget tw,XmTextPosition position)1888 _XmTextPosToLine(XmTextWidget tw,
1889 		 XmTextPosition position)
1890 {
1891   int i;
1892   if (tw->text.needs_refigure_lines) RefigureLines(tw);
1893   if (position < tw->text.top_character ||
1894       position  > tw->text.bottom_position)
1895     return NOLINE;
1896   for (i=0; i<tw->text.number_lines; i++)
1897     if (tw->text.line[i+1].start > position) return i;
1898   if (position == tw->text.line[tw->text.number_lines].start)
1899     return tw->text.number_lines;
1900   return NOLINE;  /* Couldn't find line with given position */
1901 }
1902 
1903 
1904 
1905 /****************************************************************
1906  *
1907  * Definitions exported to sources.
1908  *
1909  ****************************************************************/
1910 void
_XmTextInvalidate(XmTextWidget tw,XmTextPosition position,XmTextPosition topos,long delta)1911 _XmTextInvalidate(XmTextWidget tw,
1912 		  XmTextPosition position,
1913 		  XmTextPosition topos,
1914 		  long delta)
1915 {
1916   LineNum l;
1917   int i;
1918   XmTextPosition p, endpos;
1919   int shift = 0;
1920   int shift_start = 0;
1921 
1922 #define ladjust(p) \
1923   if ((p > position && p != PASTENDPOS) ||	                            \
1924       (p == position && delta < 0)) {		                            \
1925     p += delta;					                            \
1926     if (p < tw->text.first_position) p = tw->text.first_position;   \
1927     if (p > tw->text.last_position) p = tw->text.last_position;     \
1928   }
1929 
1930 #define radjust(p) \
1931   if ((p > position && p != PASTENDPOS) ||		                    \
1932       (p == position && delta > 0)) {			                    \
1933     p += delta;					       		            \
1934     if (p < tw->text.first_position) p = tw->text.first_position;   \
1935     if (p > tw->text.last_position) p = tw->text.last_position;     \
1936   }
1937 
1938   tw->text.first_position =
1939     (*tw->text.source->Scan)(tw->text.source, 0,
1940 				 XmSELECT_ALL, XmsdLeft, 1, FALSE);
1941     tw->text.last_position =
1942       (*tw->text.source->Scan)(tw->text.source,  0,
1943 				   XmSELECT_ALL, XmsdRight, 1, FALSE);
1944   if (delta == NODELTA) {
1945     if (tw->text.top_character == topos && position != topos) {
1946       tw->text.pending_scroll = -1;
1947       tw->text.forget_past = MIN(tw->text.forget_past, position);
1948     }
1949     if (tw->text.top_character > position &&
1950 	tw->text.bottom_position < topos) {
1951       tw->text.new_top = position;
1952       tw->text.pending_scroll = -1;
1953       tw->text.forget_past = MIN(tw->text.forget_past, position);
1954     }
1955 
1956     if (tw->text.in_resize && tw->text.line_table != NULL) {
1957       unsigned int top_index, last_index, next_index;
1958       int index_offset, lines_used;
1959 
1960       top_index = tw->text.top_line;
1961       last_index = _XmTextGetTableIndex(tw, tw->text.last_position);
1962 
1963       lines_used = (last_index - top_index) + 1;
1964 
1965       if (top_index != 0 &&
1966 	  tw->text.output->data->number_lines > lines_used) {
1967 	index_offset = tw->text.output->data->number_lines-lines_used;
1968 	if (index_offset < tw->text.total_lines - lines_used)
1969 	  next_index = top_index - index_offset;
1970 	else
1971 	  next_index = 0;
1972 	tw->text.new_top = tw->text.top_character =
1973 	  tw->text.line_table[next_index].start_pos;
1974       }
1975     }
1976 
1977     tw->text.forget_past = MIN(tw->text.forget_past, position);
1978   } else {
1979     for (i=0; i<tw->text.repaint.number; i++) {
1980       radjust(tw->text.repaint.range[i].from);
1981       ladjust(tw->text.repaint.range[i].to);
1982     }
1983     for (i=1; i < tw->text.highlight.number; i++) {
1984       if (delta < 0 &&
1985 	  tw->text.highlight.list[i].position >= position - delta)
1986 	ladjust(tw->text.highlight.list[i].position);
1987       if (delta > 0 &&
1988 	  ((tw->text.highlight.list[i].position > position) ||
1989 	   ((tw->text.highlight.list[i].position == position) &&
1990 	    (tw->text.highlight.list[i].mode != XmHIGHLIGHT_NORMAL))))
1991 	radjust(tw->text.highlight.list[i].position);
1992     }
1993     for (i=1; i<tw->text.old_highlight.number; i++) {
1994       if (delta < 0 &&
1995 	  tw->text.old_highlight.list[i].position >= position - delta)
1996 	ladjust(tw->text.old_highlight.list[i].position);
1997       if (delta > 0 &&
1998 	  ((tw->text.old_highlight.list[i].position > position) ||
1999 	   ((tw->text.old_highlight.list[i].position == position) &&
2000 	    (tw->text.old_highlight.list[i].mode != XmHIGHLIGHT_NORMAL))))
2001 	radjust(tw->text.old_highlight.list[i].position);
2002     }
2003     for (i=0; i <= tw->text.number_lines &&
2004 	 tw->text.line[i].start != PASTENDPOS; i++) {
2005       if (delta > 0) {
2006 	radjust(tw->text.line[i].start);
2007       } else {
2008 	if (tw->text.line[i].start > position &&
2009 	    tw->text.line[i].start <= topos) {
2010 	  if (i != 0 && shift_start == 0)
2011 	    shift_start = i;
2012 	  shift++;
2013 	} else {
2014 	  radjust(tw->text.line[i].start);
2015 	}
2016       }
2017       if (tw->text.line[i].changed) {
2018 	radjust(tw->text.line[i].changed_position);
2019       }
2020     }
2021     if (shift) {
2022       for (i=shift_start; i < tw->text.number_lines; i++) {
2023 	if ((i < (shift_start + shift)) && tw->text.line[i].extra)
2024 	  XtFree((char *)tw->text.line[i].extra);
2025 	if (i + shift < tw->text.number_lines) {
2026 	  tw->text.line[i].start = tw->text.line[i+shift].start;
2027 	  tw->text.line[i].extra = tw->text.line[i+shift].extra;
2028 	} else {
2029 	  tw->text.line[i].start = PASTENDPOS;
2030 	  tw->text.line[i].extra = NULL;
2031 	}
2032 	tw->text.line[i].changed = TRUE;
2033 	if (tw->text.line[i].start != PASTENDPOS)
2034 	  tw->text.line[i].changed_position =
2035 	    tw->text.line[i + 1].start - 1;
2036 	else
2037 	  tw->text.line[i].changed_position = PASTENDPOS;
2038       }
2039     }
2040     ladjust(tw->text.bottom_position);
2041     tw->text.output->data->refresh_ibeam_off = True;
2042     endpos = topos;
2043     radjust(endpos);
2044 
2045     /* Force _XmTextPosToLine to not bother trying to recalculate. */
2046     tw->text.needs_refigure_lines = FALSE;
2047     for (l = _XmTextPosToLine(tw, position), p = position;
2048 	 l < tw->text.number_lines &&
2049 	 tw->text.line[l].start <= endpos;
2050 	 l++, p = tw->text.line[l].start) {
2051       if (l != NOLINE) {
2052 	if (tw->text.line[l].changed) {
2053 	  tw->text.line[l].changed_position =
2054 	    MIN(p, tw->text.line[l].changed_position);
2055 	} else {
2056 	  tw->text.line[l].changed_position = p;
2057 	  tw->text.line[l].changed = TRUE;
2058 	}
2059       }
2060     }
2061   }
2062   (*tw->text.output->Invalidate)(tw, position, topos, delta);
2063   (*tw->text.input->Invalidate)(tw, position, topos, delta);
2064   tw->text.needs_refigure_lines = tw->text.needs_redisplay = TRUE;
2065   if (tw->text.disable_depth == 0) Redisplay(tw);
2066 }
2067 
2068 static void
InsertHighlight(XmTextWidget tw,XmTextPosition position,XmHighlightMode mode)2069 InsertHighlight(XmTextWidget tw,
2070 		XmTextPosition position,
2071 		XmHighlightMode mode)
2072 {
2073   _XmHighlightRec *l1;
2074   _XmHighlightRec *l = tw->text.highlight.list;
2075   int i, j;
2076 
2077   l1 = FindHighlight(tw, position, XmsdLeft);
2078   if (l1->position == position && position != 0)
2079     l1->mode = mode;
2080   else {
2081     i = (l1 - l) + 1;
2082     tw->text.highlight.number++;
2083     if (tw->text.highlight.number > tw->text.highlight.maximum) {
2084       tw->text.highlight.maximum = tw->text.highlight.number;
2085       l = tw->text.highlight.list = (_XmHighlightRec *)
2086 	XtRealloc((char *) l, tw->text.highlight.maximum *
2087 		  sizeof(_XmHighlightRec));
2088     }
2089     for (j=tw->text.highlight.number-1; j>i; j--)
2090       l[j] = l[j-1];
2091     l[i].position = position;
2092     l[i].mode = mode;
2093   }
2094 }
2095 
2096 /****************************************************************
2097  *
2098  * Creation definitions.
2099  *
2100  ****************************************************************/
2101 /*
2102  * Create the text widget.  To handle default condition of the core
2103  * height and width after primitive has already reset it's height and
2104  * width, use request values and reset height and width to original
2105  * height and width state.
2106  */
2107 /* ARGSUSED */
2108 static void
Initialize(Widget rw,Widget nw,ArgList args,Cardinal * num_args)2109 Initialize(Widget rw,
2110 	   Widget nw,
2111 	   ArgList args,
2112 	   Cardinal *num_args)
2113 {
2114   XmTextWidget req = (XmTextWidget) rw;
2115   XmTextWidget newtw = (XmTextWidget) nw;
2116 
2117   if (MB_CUR_MAX > 0)
2118     newtw->text.char_size = (char)MB_CUR_MAX;
2119   else
2120     newtw->text.char_size = 1;
2121 
2122   if (req->core.width == 0) newtw->core.width = req->core.width;
2123   if (req->core.height == 0) newtw->core.height = req->core.height;
2124 
2125   /* Flag used in losing focus verification to indicate that a traversal
2126      key was pressed.  Must be initialized to False */
2127   newtw->text.traversed = False;
2128 
2129   newtw->text.total_lines = 1;
2130   newtw->text.top_line = 0;
2131   newtw->text.vsbar_scrolling = False;
2132   newtw->text.hsbar_scrolling = False;
2133   newtw->text.in_setvalues = False;
2134 
2135   if (newtw->text.output_create == NULL)
2136     newtw->text.output_create = _XmTextOutputCreate;
2137   if (newtw->text.input_create == NULL)
2138     newtw->text.input_create = _XmTextInputCreate;
2139 
2140   /*  The following resources are defaulted to invalid values to indicate    */
2141   /*  that it was not set by the application.  If it gets to this point      */
2142   /*  and they are still invalid then set them to their appropriate default. */
2143 
2144   if (!XmRepTypeValidValue(XmRID_EDIT_MODE,
2145 			   newtw->text.edit_mode, nw)) {
2146     newtw->text.edit_mode = XmSINGLE_LINE_EDIT;
2147   }
2148 
2149    /* All 8 buffers must be created to be able to rotate the cut buffers */
2150    _XmCreateCutBuffers(nw);
2151 
2152    if (newtw->text.verify_bell == (Boolean) XmDYNAMIC_BOOL) {
2153      if (_XmGetAudibleWarning(nw) == XmBELL)
2154        newtw->text.verify_bell = True;
2155      else
2156        newtw->text.verify_bell = False;
2157    }
2158 
2159    /*
2160     * Initialize on-the-spot data
2161     */
2162    newtw->text.onthespot = (OnTheSpotDataTW) XtMalloc(sizeof(OnTheSpotDataRecTW)
2163 );
2164    newtw->text.onthespot->start = newtw->text.onthespot->end =
2165    newtw->text.onthespot->cursor = newtw->text.onthespot->over_len =
2166    newtw->text.onthespot->over_maxlen = 0;
2167    newtw->text.onthespot->over_str = NULL;
2168    newtw->text.onthespot->under_preedit = False;
2169    newtw->text.onthespot->under_verify_preedit = False;
2170    newtw->text.onthespot->verify_commit = False;
2171    newtw->text.tm_table = (XtTranslations)NULL;
2172 }
2173 
2174 /*
2175  * Create a text widget.  Note that most of the standard stuff is actually
2176  * to be done by the output create routine called here, since output is in
2177  * charge of window handling.
2178  */
2179 static void
InitializeHook(Widget wid,ArgList args,Cardinal * num_args_ptr)2180 InitializeHook(Widget wid,
2181 	       ArgList args,
2182 	       Cardinal *num_args_ptr)
2183 {
2184   register XmTextWidget tw;
2185   Cardinal num_args = *num_args_ptr;
2186   XmTextSource source;
2187   XmTextPosition top_character;
2188   XmTextBlockRec block;
2189   Position dummy;
2190   Boolean used_source = False;
2191 
2192   tw = (XmTextWidget) wid;
2193 
2194   /* If text.wc_value is set, it overrides. Call _Xm..Create with it. */
2195   if (tw->text.source == nullsourceptr) {
2196     if (tw->text.wc_value != NULL) {
2197       source = _XmStringSourceCreate((char*)tw->text.wc_value, True);
2198       tw->text.value = NULL;
2199       tw->text.wc_value = NULL;
2200     } else {
2201       source = _XmStringSourceCreate(tw->text.value, False);
2202       tw->text.value = NULL;
2203     }
2204   } else {
2205     source = tw->text.source;
2206     if (tw->text.wc_value != NULL) {
2207       char * tmp_value;
2208       int num_chars, n_bytes;
2209 
2210       for (num_chars=0; tw->text.wc_value[num_chars]!=0L; num_chars++)
2211 	/*EMPTY*/;
2212 
2213       tmp_value = XtMalloc((unsigned)
2214 			   (num_chars + 1) * (int)tw->text.char_size);
2215       n_bytes = wcstombs(tmp_value, tw->text.wc_value,
2216 			 (num_chars + 1) * (int)tw->text.char_size);
2217       if (n_bytes == -1) n_bytes = 0;
2218       tmp_value[n_bytes] = 0;  /* NULL terminate the string */
2219       _XmStringSourceSetValue(tw, tmp_value);
2220       XtFree(tmp_value);
2221       tw->text.wc_value = NULL;
2222     } else if (tw->text.value != NULL) {
2223       /* Default value or argument ? */
2224       int i;
2225       for (i = 0; i < num_args; i++)
2226 	if (tw->text.value == (char *)args[i].value &&
2227 	    (args[i].name == XmNvalue ||
2228 	     strcmp(args[i].name, XmNvalue) == 0)) {
2229 	  _XmStringSourceSetValue(tw, tw->text.value);
2230 	  break;
2231 	}
2232     }
2233     tw->text.value = NULL;
2234     used_source = True;
2235   }
2236 
2237   tw->text.disable_depth = 1;
2238   tw->text.first_position = 0;
2239   tw->text.last_position = 0;
2240   tw->text.dest_position = 0;
2241 
2242   tw->text.needs_refigure_lines = tw->text.needs_redisplay = TRUE;
2243   tw->text.number_lines = 0;
2244   tw->text.maximum_lines = 1;
2245   tw->text.line = (Line) XtMalloc(sizeof(LineRec));
2246   tw->text.line->start = PASTENDPOS;
2247   tw->text.line->changed = False;
2248   tw->text.line->changed_position = PASTENDPOS;
2249   tw->text.line->past_end = False;
2250   tw->text.line->extra = NULL;
2251   tw->text.repaint.number = tw->text.repaint.maximum = 0;
2252   tw->text.repaint.range = (RangeRec *) XtMalloc(sizeof(RangeRec));
2253   tw->text.highlight.number = tw->text.highlight.maximum = 1;
2254   tw->text.highlight.list = (_XmHighlightRec *)
2255     XtMalloc(sizeof(_XmHighlightRec));
2256   tw->text.highlight.list[0].position = 0;
2257   tw->text.highlight.list[0].mode = XmHIGHLIGHT_NORMAL;
2258   tw->text.old_highlight.number = 0;
2259   tw->text.old_highlight.maximum = 1;
2260   tw->text.old_highlight.list = (_XmHighlightRec *)
2261     XtMalloc(sizeof(_XmHighlightRec));
2262   tw->text.highlight_changed = FALSE;
2263   tw->text.on_or_off = on;
2264   tw->text.force_display = -1;
2265   tw->text.in_redisplay = tw->text.in_refigure_lines = FALSE;
2266   tw->text.in_resize = FALSE;
2267   tw->text.in_expose = FALSE;
2268   tw->text.pending_scroll = 0;
2269   tw->text.new_top = tw->text.top_character;
2270   tw->text.bottom_position = 0;
2271   tw->text.add_mode = False;
2272   tw->text.pendingoff = True;
2273   tw->text.forget_past = 0;
2274 
2275   /* Translation table overwrite */
2276   if (XmDirectionMatch(XmPrim_layout_direction(tw),
2277 		       XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
2278     char *vevent_bindings;
2279 
2280     vevent_bindings =
2281 		(String)XtMalloc(strlen(_XmTextIn_XmTextVEventBindings) + 1);
2282     strcpy(vevent_bindings, _XmTextIn_XmTextVEventBindings);
2283     tw->text.tm_table = (XtTranslations)XtParseTranslationTable(vevent_bindings);
2284     XtFree(vevent_bindings);
2285     XtOverrideTranslations(wid, tw->text.tm_table);
2286   }
2287 
2288   /* Initialize table */
2289   if (tw->text.edit_mode == XmSINGLE_LINE_EDIT)
2290     InitializeLineTable(tw, 1);
2291   else
2292     InitializeLineTable(tw, INIT_TABLE_SIZE);
2293 
2294   (*tw->text.source->RemoveWidget)(tw->text.source, tw);
2295   tw->text.source = source;
2296   (*tw->text.source->AddWidget)(tw->text.source, tw);
2297   (*tw->text.output_create)(wid, args, num_args);
2298 
2299   _XmTextSetEditable(wid, tw->text.editable);
2300   _XmStringSourceSetMaxLength(GetSrc(tw), tw->text.max_length);
2301 
2302   (*tw->text.input_create)(wid, args, num_args);
2303 
2304   tw->text.first_position =
2305     (*tw->text.source->Scan)(tw->text.source, 0,
2306 				 XmSELECT_ALL, XmsdLeft, 1, FALSE);
2307   tw->text.last_position =
2308     (*tw->text.source->Scan)(tw->text.source, 0,
2309 				 XmSELECT_ALL, XmsdRight, 1, FALSE);
2310 
2311   if (tw->text.cursor_position < 0)
2312     tw->text.cursor_position = 0;
2313 
2314   if (tw->text.cursor_position > tw->text.last_position)
2315     tw->text.cursor_position = tw->text.last_position;
2316 
2317   tw->text.dest_position = tw->text.cursor_position;
2318 
2319   if (!tw->text.editable || !XtIsSensitive(wid))
2320     _XmTextSetDestinationSelection(wid, 0, False, (Time)NULL);
2321 
2322   if (tw->text.edit_mode == XmMULTI_LINE_EDIT)
2323     top_character = (*tw->text.source->Scan)(tw->text.source,
2324                                                  tw->text.top_character,
2325 						 XmSELECT_LINE, XmsdLeft, 1,
2326 						 FALSE);
2327   else
2328     top_character = tw->text.top_character;
2329 
2330   tw->text.new_top = top_character;
2331   tw->text.top_character = 0;
2332   _XmTextInvalidate(tw, top_character, top_character, NODELTA);
2333   if (tw->text.disable_depth == 0)
2334     Redisplay(tw);
2335 
2336   /*
2337    * Fix for CR 5704 - If the source has already been created, do not use
2338    *                   the original code - it has already been processed and
2339    *                   the gaps are not where they were the first time
2340    *                   through for this source.  Instead, use
2341    *                   code similar to that used in XmTextSetSource().
2342    */
2343   if (!used_source) {
2344     tw->text.source->data->gap_start[0] = '\0'; /*Hack to utilize initial
2345 						  value when setting line
2346 						  table - saves a malloc
2347 						  and free. */
2348     if (tw->text.char_size == 1) {
2349       block.ptr = tw->text.source->data->ptr;
2350       if (block.ptr == NULL) block.length = 0;
2351       else block.length = strlen(block.ptr);
2352     } else
2353       (void)(*tw->text.source->ReadSource)(source, 0, source->data->length,
2354 					       &block);
2355   } else
2356     (void)(*tw->text.source->ReadSource)(source, 0, source->data->length,
2357 					     &block);
2358 
2359   _XmTextUpdateLineTable(wid, 0, 0, &block, False);
2360 
2361   _XmStringSourceSetGappedBuffer(source->data, tw->text.cursor_position);
2362 
2363   tw->text.forget_past = tw->text.first_position;
2364 
2365   tw->text.disable_depth = 0;
2366   (*tw->text.output->PosToXY)(tw, tw->text.cursor_position,
2367 				  &(tw->text.cursor_position_x), &dummy);
2368 }
2369 
2370 static void
Realize(Widget w,XtValueMask * valueMask,XSetWindowAttributes * attributes)2371 Realize(Widget w,
2372         XtValueMask *valueMask,
2373         XSetWindowAttributes *attributes)
2374 {
2375   XmTextWidget tw = (XmTextWidget) w;
2376   Position dummy;
2377   Arg im_args[20];
2378   XIMCallback xim_cb[4];
2379   Cardinal n = 0;
2380 
2381   (*tw->text.output->realize)(w, valueMask, attributes);
2382   (*tw->text.output->PosToXY)(tw, tw->text.cursor_position,
2383 			      &(tw->text.cursor_position_x), &dummy);
2384 
2385   if (tw->text.editable) {
2386   /*
2387    * Register on the spot callbacks.
2388    */
2389     xim_cb[0].client_data = (XPointer)tw;
2390     xim_cb[0].callback = (XIMProc)PreeditStart;
2391     xim_cb[1].client_data = (XPointer)tw;
2392     xim_cb[1].callback = (XIMProc)PreeditDone;
2393     xim_cb[2].client_data = (XPointer)tw;
2394     xim_cb[2].callback = (XIMProc)PreeditDraw;
2395     xim_cb[3].client_data = (XPointer)tw;
2396     xim_cb[3].callback = (XIMProc)PreeditCaret;
2397     XtSetArg(im_args[n], XmNpreeditStartCallback, &xim_cb[0]); n++;
2398     XtSetArg(im_args[n], XmNpreeditDoneCallback, &xim_cb[1]); n++;
2399     XtSetArg(im_args[n], XmNpreeditDrawCallback, &xim_cb[2]); n++;
2400     XtSetArg(im_args[n], XmNpreeditCaretCallback, &xim_cb[3]); n++;
2401     XmImSetValues(w, im_args, n);
2402   }
2403 }
2404 
2405 
2406 /****************************************************************
2407  *
2408  * Semi-public definitions.
2409  *
2410  ****************************************************************/
2411 static void
Destroy(Widget w)2412 Destroy(Widget w)
2413 {
2414   XmTextWidget tw = (XmTextWidget) w;
2415   int j;
2416 
2417   (*tw->text.source->RemoveWidget)(tw->text.source, tw);
2418   if (tw->text.input->destroy) (*tw->text.input->destroy)(w);
2419   if (tw->text.output->destroy) (*tw->text.output->destroy)(w);
2420 
2421   for (j = 0; j < tw->text.number_lines; j++) {
2422     if (tw->text.line[j].extra)
2423       XtFree((char *)tw->text.line[j].extra);
2424   }
2425 
2426   XtFree((char *)tw->text.line);
2427 
2428   XtFree((char *)tw->text.repaint.range);
2429   XtFree((char *)tw->text.highlight.list);
2430   XtFree((char *)tw->text.old_highlight.list);
2431 
2432   if (tw->text.line_table != NULL)
2433     XtFree((char *)tw->text.line_table);
2434 
2435   if (tw->text.onthespot != NULL)
2436     XtFree((char *)tw->text.onthespot);
2437 
2438   if (tw->text.tm_table != NULL)
2439     XtFree((char *)tw->text.tm_table);
2440 }
2441 
2442 static void
Resize(Widget w)2443 Resize(Widget w)
2444 {
2445   XmTextWidget tw = (XmTextWidget) w;
2446 
2447   /* this flag prevents resize requests */
2448   tw->text.in_resize = True;
2449 
2450   if (_XmTextShouldWordWrap(tw))
2451     _XmTextRealignLineTable(tw, NULL, 0, 0, 0, PASTENDPOS);
2452 
2453   (*(tw->text.output->resize))(w, FALSE);
2454 
2455   tw->text.in_resize = False;
2456 }
2457 
2458 static void
DoExpose(Widget w,XEvent * event,Region region)2459 DoExpose(Widget w,
2460 	 XEvent *event,
2461 	 Region region)
2462 {
2463   XmTextWidget tw = (XmTextWidget) w;
2464 
2465   /* this flag prevents resize requests */
2466   tw->text.in_expose = True;
2467 
2468   (*(tw->text.output->expose))(w, event, region);
2469 
2470   tw->text.in_expose = False;
2471 }
2472 
2473 static void
GetValuesHook(Widget w,ArgList args,Cardinal * num_args_ptr)2474 GetValuesHook(Widget w,
2475 	      ArgList args,
2476 	      Cardinal *num_args_ptr)
2477 {
2478   XmTextWidget tw = (XmTextWidget) w;
2479   Cardinal num_args = *num_args_ptr;
2480   int i;
2481 
2482   XtGetSubvalues((XtPointer) tw,
2483 		 resources, XtNumber(resources), args, num_args);
2484 
2485   for (i = 0; i < num_args; i++) {
2486     if (!strcmp(args[i].name, XmNvalue)) {
2487       *((XtPointer *)args[i].value) =
2488 	(XtPointer)_XmStringSourceGetValue(GetSrc(tw), False);
2489     }
2490   }
2491 
2492   for (i = 0; i < num_args; i++) {
2493     if (!strcmp(args[i].name, XmNvalueWcs)) {
2494       *((XtPointer *)args[i].value) =
2495 	(XtPointer)_XmStringSourceGetValue(GetSrc(tw), True);
2496     }
2497   }
2498 
2499   (*tw->text.output->GetValues)(w, args, num_args);
2500   (*tw->text.input->GetValues)(w, args, num_args);
2501 }
2502 
2503 void
_XmTextSetTopCharacter(Widget widget,XmTextPosition top_character)2504 _XmTextSetTopCharacter(Widget widget,
2505 		       XmTextPosition top_character)
2506 {
2507   XmTextWidget tw = (XmTextWidget) widget;
2508   LineNum line_num;
2509 
2510   if (tw->text.edit_mode != XmSINGLE_LINE_EDIT) {
2511     line_num = _XmTextGetTableIndex(tw, top_character);
2512     top_character = tw->text.line_table[line_num].start_pos;
2513   }
2514 
2515   if (top_character != tw->text.new_top) {
2516     EraseInsertionPoint(tw);
2517     tw->text.new_top = top_character;
2518     tw->text.pending_scroll = 0;
2519     tw->text.needs_refigure_lines = tw->text.needs_redisplay = TRUE;
2520     if (XmSINGLE_LINE_EDIT == tw->text.edit_mode)
2521 	tw->text.output->data->hoffset = 0;
2522     if (tw->text.disable_depth == 0)
2523       Redisplay(tw);
2524     TextDrawInsertionPoint(tw);
2525   }
2526   /*
2527    * Fixes CDExc23645 and CDExc23898
2528    */
2529   else if (tw->text.auto_show_cursor_position &&
2530 	   tw->text.edit_mode == XmSINGLE_LINE_EDIT)
2531     _XmTextShowPosition(widget, top_character);
2532 }
2533 
2534 static void
LosingFocus(XmTextWidget tw)2535 LosingFocus(XmTextWidget tw)
2536 {
2537   XmTextVerifyCallbackStruct  cbdata;
2538 
2539   cbdata.reason = XmCR_LOSING_FOCUS;
2540   cbdata.event = NULL;
2541   cbdata.doit = True;
2542   cbdata.currInsert = tw->text.cursor_position;
2543   cbdata.newInsert = tw->text.cursor_position;
2544   cbdata.startPos = tw->text.cursor_position;
2545   cbdata.endPos = tw->text.cursor_position;
2546   cbdata.text = NULL;
2547   XtCallCallbackList((Widget)tw, tw->text.losing_focus_callback,
2548 		     (XtPointer) &cbdata);
2549   tw->text.source->data->take_selection = True;
2550 }
2551 
2552 /* ARGSUSED */
2553 static Boolean
SetValues(Widget oldw,Widget reqw,Widget new_w,ArgList args,Cardinal * num_args)2554 SetValues(Widget oldw,
2555 	  Widget reqw,
2556 	  Widget new_w,
2557 	  ArgList args,
2558 	  Cardinal *num_args)
2559 {
2560   XmTextWidget old = (XmTextWidget) oldw;
2561   XmTextWidget newtw = (XmTextWidget) new_w;
2562   XmTextPosition new_cursor_pos;
2563   Boolean o_redisplay;
2564   Position dummy;
2565   Boolean need_new_cursorPos = False;
2566   Boolean need_text_redisplay = False;
2567   Boolean new_source = (newtw->text.source != old->text.source);
2568   XmTextSource cache_source = NULL;
2569 
2570   if (newtw->core.being_destroyed)
2571   {
2572       return False;
2573   }
2574 
2575   _XmTextResetIC(oldw);
2576 
2577   newtw->text.in_setvalues = True;
2578 
2579   if (newtw->text.cursor_position<0)
2580   {
2581         newtw->text.cursor_position=0;
2582     }
2583 
2584   /* It is unfortunate that the rest of the Text widget code, particularly the
2585   ** redisplay code, assumes that the current source is valid; in fact, it may
2586   ** have been changed by a set-values call. Ideally, we would be able to
2587   ** handle before anything else a change in the XmNsource resource of the
2588   ** widget; in practice, the changes would be extensive.
2589   ** Compromise by temporarily restoring the old value for those pieces of
2590   ** code which affect the display of the old source; then restore the new
2591   ** value for the display of the current source. That is, deal with the old
2592   ** value for just this one line of code.
2593   */
2594   if (new_source) {
2595       cache_source = newtw->text.source;
2596       newtw->text.source = old->text.source;
2597   }
2598 
2599   EraseInsertionPoint(newtw); /* assumes newtw->text.source matches values */
2600 
2601   if (new_source)
2602       newtw->text.source = cache_source;
2603 
2604   _XmTextDisableRedisplay(newtw, TRUE);
2605 
2606   /* set cursor_position to a known acceptable value (0 is always acceptable)
2607    */
2608   new_cursor_pos = newtw->text.cursor_position;
2609   newtw->text.cursor_position = 0;
2610 
2611   if (! XtIsSensitive(new_w) &&
2612       newtw->text.input->data->has_destination) {
2613     _XmTextSetDestinationSelection(new_w, 0, True,
2614 				   XtLastTimestampProcessed(XtDisplay(new_w)));
2615   }
2616 
2617   if (!XmRepTypeValidValue(XmRID_EDIT_MODE,
2618 			     newtw->text.edit_mode, new_w)) {
2619     newtw->text.edit_mode = old->text.edit_mode;
2620   }
2621 
2622   if ((old->text.top_character != newtw->text.top_character) &&
2623       (newtw->text.top_character != newtw->text.new_top)) {
2624     XmTextPosition new_top;
2625     if (newtw->text.output->data->resizeheight &&
2626      !(newtw->text.output->data->scrollvertical &&
2627      XmIsScrolledWindow(XtParent((Widget)newtw))) )
2628       new_top = 0;
2629     else
2630       new_top = newtw->text.top_character;
2631 
2632     newtw->text.top_character = old->text.top_character;
2633     _XmTextSetTopCharacter(new_w, new_top);
2634     if (newtw->text.needs_refigure_lines)
2635       newtw->text.top_character = new_top;
2636   }
2637 
2638   if (old->text.source != newtw->text.source) {
2639     XmTextSource source = newtw->text.source;
2640     newtw->text.source = old->text.source;
2641     o_redisplay = newtw->text.needs_redisplay;
2642     XmTextSetSource(new_w, source, old->text.top_character, 0);
2643     need_text_redisplay = newtw->text.needs_redisplay;
2644     newtw->text.needs_redisplay = o_redisplay;
2645   }
2646 
2647   if (old->text.editable != newtw->text.editable) {
2648     Boolean editable = newtw->text.editable;
2649     newtw->text.editable = old->text.editable;
2650     _XmTextSetEditable(new_w, editable);
2651   }
2652 
2653   _XmStringSourceSetMaxLength(GetSrc(newtw), newtw->text.max_length);
2654 
2655   /* Four cases to handle for value:
2656    *   1. user set both XmNvalue and XmNwcValue.
2657    *   2. user set the opposite resource (i.e. value is a char*
2658    *      and user set XmNwcValue, or vice versa).
2659    *   3. user set the corresponding resource (i.e. value is a char*
2660    *      and user set XmNValue, or vice versa).
2661    *   4. user set neither XmNValue nor XmNwcValue
2662    */
2663 
2664   /* OSF says:  if XmNvalueWcs set, it overrides all else */
2665 
2666   if (newtw->text.wc_value != NULL) {
2667     /* user set XmNvalueWcs resource - it rules ! */
2668     wchar_t * wc_value;
2669     char * tmp_value;
2670     int num_chars, n_bytes;
2671 
2672     num_chars = n_bytes = 0;
2673 
2674     for (num_chars = 0, wc_value = newtw->text.wc_value;
2675 	 wc_value[num_chars] != 0L;) num_chars++;
2676 
2677     tmp_value = XtMalloc((unsigned)
2678 			 (num_chars + 1) * (int)newtw->text.char_size);
2679     n_bytes = wcstombs(tmp_value, newtw->text.wc_value,
2680 		       (num_chars + 1) * (int)newtw->text.char_size);
2681     if (n_bytes == -1) n_bytes = 0;
2682     tmp_value[n_bytes] = 0;  /* NULL terminate the string */
2683     o_redisplay = newtw->text.needs_redisplay;
2684     newtw->text.wc_value = NULL;
2685     newtw->text.value = NULL;
2686     _XmStringSourceSetValue(newtw, tmp_value);
2687     need_text_redisplay = newtw->text.needs_redisplay;
2688     newtw->text.needs_redisplay = o_redisplay;
2689     XtFree(tmp_value);
2690     need_new_cursorPos = True;
2691   } else if (newtw->text.value != NULL) {
2692     char * tmp_value;
2693 
2694     newtw->text.pendingoff = TRUE;
2695     o_redisplay = newtw->text.needs_redisplay;
2696     tmp_value = newtw->text.value;
2697     newtw->text.value = NULL;
2698     _XmStringSourceSetValue(newtw, tmp_value);
2699     need_text_redisplay = newtw->text.needs_redisplay;
2700     newtw->text.needs_redisplay = o_redisplay;
2701     need_new_cursorPos = True;
2702   }
2703 
2704   /* return cursor_position to it's original changed value */
2705   newtw->text.cursor_position = new_cursor_pos;
2706 
2707   if (old->text.cursor_position != newtw->text.cursor_position) {
2708     XmTextPosition new_position = newtw->text.cursor_position;
2709     newtw->text.cursor_position = old->text.cursor_position;
2710 
2711     if (new_position > newtw->text.source->data->length)
2712       _XmTextSetCursorPosition(new_w, newtw->text.source->data->length);
2713     else
2714       _XmTextSetCursorPosition(new_w, new_position);
2715   } else if (need_new_cursorPos) {
2716     XmTextPosition cursorPos = -1;
2717     int ix;
2718 
2719     for (ix = 0; ix < *num_args; ix++)
2720       if (strcmp(args[ix].name, XmNcursorPosition) == 0) {
2721 	cursorPos = (XmTextPosition)args[ix].value;
2722 	break;
2723       }
2724     if (cursorPos == -1)
2725       cursorPos = (*newtw->text.source->Scan)(newtw->text.source,
2726 					      newtw->text.cursor_position,
2727 					      XmSELECT_ALL, XmsdLeft, 1, TRUE);
2728     _XmTextSetCursorPosition(new_w, cursorPos);
2729   } else
2730     if (newtw->text.cursor_position > newtw->text.source->data->length) {
2731       _XmTextSetCursorPosition(new_w, newtw->text.source->data->length);
2732     }
2733 
2734 
2735   o_redisplay = (*newtw->text.output->SetValues)
2736     (oldw, reqw, new_w, args, num_args);
2737   (*newtw->text.input->SetValues)(oldw, reqw, new_w, args, num_args);
2738   newtw->text.forget_past = 0;
2739   newtw->text.disable_depth--;   /* _XmTextEnableRedisplay() is not called
2740 				    because we don't want a repaint yet */
2741   TextDrawInsertionPoint(newtw); /* increment cursor_on stack in lieu of
2742 				    _XmTextEnableRedisplay() call. */
2743   (*newtw->text.output->PosToXY)(newtw, newtw->text.cursor_position,
2744 				 &(newtw->text.cursor_position_x), &dummy);
2745 
2746   if (o_redisplay) newtw->text.needs_redisplay = True;
2747 
2748   TextDrawInsertionPoint(newtw);
2749 
2750   if (XtIsSensitive(new_w) != XtIsSensitive(oldw)) {
2751     if (XtIsSensitive(new_w)) {
2752       EraseInsertionPoint(newtw);
2753       newtw->text.output->data->blinkstate = off;
2754       TextDrawInsertionPoint(newtw);
2755     } else {
2756       if (newtw->text.output->data->hasfocus) {
2757 	newtw->text.output->data->hasfocus = False;
2758 	_XmTextChangeBlinkBehavior(newtw, False);
2759 	EraseInsertionPoint(newtw);
2760 	newtw->text.output->data->blinkstate = on;
2761 	TextDrawInsertionPoint(newtw);
2762         XmImUnsetFocus(new_w);
2763       }
2764     }
2765     if (newtw->text.source->data->length > 0)
2766       newtw->text.needs_redisplay = True;
2767   }
2768 
2769   if ((!newtw->text.editable || !XtIsSensitive(new_w)) &&
2770       _XmTextHasDestination(new_w))
2771     _XmTextSetDestinationSelection(new_w, 0, False, (Time)NULL);
2772 
2773   /* don't shrink to nothing */
2774   if (newtw->core.width == 0) newtw->core.width = old->core.width;
2775   if (newtw->core.height == 0) newtw->core.height = old->core.height;
2776 
2777   /* Optimization for the case when only XmNvalue changes.
2778      This considerably reduces flashing due to unneeded redraws */
2779   if (need_text_redisplay &&
2780       !newtw->text.needs_redisplay &&
2781       newtw->text.disable_depth == 0) {
2782     EraseInsertionPoint(newtw);
2783     newtw->text.disable_depth++;
2784     newtw->text.needs_redisplay = True;
2785     _XmTextEnableRedisplay(newtw);
2786     newtw->text.needs_redisplay = False;
2787   }
2788 
2789   newtw->text.in_setvalues = newtw->text.needs_redisplay;
2790 
2791   return newtw->text.needs_redisplay;
2792 }
2793 
2794 static XtGeometryResult
QueryGeometry(Widget w,XtWidgetGeometry * intended,XtWidgetGeometry * reply)2795 QueryGeometry(Widget w,
2796 	      XtWidgetGeometry *intended,
2797 	      XtWidgetGeometry *reply)
2798 {
2799   XmTextWidget tw = (XmTextWidget) w;
2800 
2801   if (GMode (intended) & (~(CWWidth | CWHeight)))
2802     return(XtGeometryNo);
2803 
2804   reply->request_mode = (CWWidth | CWHeight);
2805 
2806   (*tw->text.output->GetPreferredSize)(w, &reply->width, &reply->height);
2807   if ((GMode(intended) != GMode(reply)) ||
2808       (reply->width != intended->width) ||
2809       (reply->height != intended->height))
2810     return (XtGeometryAlmost);
2811   else {
2812     reply->request_mode = 0;
2813     return (XtGeometryYes);
2814   }
2815 }
2816 
2817 static void
_XmTextSetString(Widget widget,char * value)2818 _XmTextSetString(Widget widget,
2819 		 char *value)
2820 {
2821   XmTextWidget tw = (XmTextWidget) widget;
2822 
2823   _XmTextResetIC(widget);
2824 
2825   tw->text.pendingoff = TRUE;
2826   if (value == NULL) value = "";
2827   _XmStringSourceSetValue(tw, value);
2828 
2829   /* after set, move insertion cursor to beginning of string. */
2830   _XmTextSetCursorPosition(widget, 0);
2831 }
2832 
2833 void
_XmTextSetCursorPosition(Widget widget,XmTextPosition position)2834 _XmTextSetCursorPosition(Widget widget,
2835 			 XmTextPosition position)
2836 {
2837   XmTextWidget tw = (XmTextWidget) widget;
2838   XmTextSource source;
2839   XmTextVerifyCallbackStruct cb;
2840   Position dummy;
2841   int n = 0;
2842   XPoint xmim_point;
2843   XRectangle xmim_area;
2844   Arg args[10];
2845 
2846   if (position < 0) {
2847     position = 0;
2848   }
2849 
2850   if (position > tw->text.last_position) {
2851     position = tw->text.last_position;
2852   }
2853 
2854   source = GetSrc(tw);
2855 
2856   /* if position hasn't changed, don't call the modify verify callback */
2857   if (position != tw->text.cursor_position) {
2858     /* Call Motion Verify Callback before Cursor Changes Positon */
2859     cb.reason = XmCR_MOVING_INSERT_CURSOR;
2860     cb.event  = NULL;
2861     cb.currInsert = tw->text.cursor_position;
2862     cb.newInsert = position;
2863     cb.doit = True;
2864     XtCallCallbackList (widget, tw->text.motion_verify_callback,
2865 			(XtPointer) &cb);
2866 
2867     /* Cancel action upon application request */
2868     if (!cb.doit) {
2869       if (tw->text.verify_bell) XBell(XtDisplay(widget), 0);
2870       return;
2871     }
2872   }
2873 
2874   /* Erase insert cursor prior to move */
2875   EraseInsertionPoint(tw);
2876   tw->text.cursor_position = position;
2877 
2878   /*
2879    * If not in add_mode and pending delete state is on reset
2880    * the selection.
2881    */
2882   if (!tw->text.add_mode && tw->text.pendingoff &&
2883       _XmStringSourceHasSelection(source))
2884     (*source->SetSelection)(source, position, position,
2885 			    XtLastTimestampProcessed(XtDisplay(widget)));
2886 
2887   /* ensure that IBeam at new location will be displayed correctly */
2888   _XmTextMovingCursorPosition(tw, position); /*correct GC for new location */
2889 
2890   if (tw->text.auto_show_cursor_position)
2891     _XmTextShowPosition(widget, position);
2892   if (tw->text.needs_redisplay && tw->text.disable_depth == 0)
2893     Redisplay(tw);
2894 
2895   (*tw->text.output->PosToXY) (tw, position, &(tw->text.cursor_position_x),
2896 			       &dummy);
2897 
2898   tw->text.output->data->refresh_ibeam_off = True; /* update IBeam off area
2899 						    * before drawing IBeam */
2900 
2901   (*tw->text.output->PosToXY)(tw, position, &xmim_point.x, &xmim_point.y);
2902   (void)_XmTextGetDisplayRect((Widget)tw, &xmim_area);
2903   n = 0;
2904   XtSetArg(args[n], XmNspotLocation, &xmim_point); n++;
2905   XtSetArg(args[n], XmNarea, &xmim_area); n++;
2906   XmImSetValues((Widget)tw, args, n);
2907   TextDrawInsertionPoint(tw);
2908 }
2909 
2910 /* ARGSUSED */
2911 void
_XmTextDisableRedisplay(XmTextWidget widget,int losesbackingstore)2912 _XmTextDisableRedisplay(XmTextWidget widget,
2913 #if NeedWidePrototypes
2914 			int losesbackingstore)
2915 #else
2916                         Boolean losesbackingstore)
2917 #endif /* NeedWidePrototypes */
2918 {
2919   widget->text.disable_depth++;
2920   EraseInsertionPoint(widget);
2921 }
2922 
2923 void
_XmTextEnableRedisplay(XmTextWidget widget)2924 _XmTextEnableRedisplay(XmTextWidget widget)
2925 {
2926   if (widget->text.disable_depth) widget->text.disable_depth--;
2927   if (widget->text.disable_depth == 0 && widget->text.needs_redisplay)
2928     Redisplay(widget);
2929 
2930   /* If this is a scrolled widget, better update the scroll bars to reflect
2931    * any changes that have occured while redisplay has been disabled.  */
2932 
2933   if (widget->text.disable_depth == 0) {
2934     if (XmDirectionMatch(XmPrim_layout_direction(widget),
2935 			 XmTOP_TO_BOTTOM_RIGHT_TO_LEFT)) {
2936       if (widget->text.output->data->scrollvertical &&
2937 #ifdef FIX_1147
2938 	  XmIsScrolledWindow(XtParent(widget)))
2939 #else
2940 	  XtClass(widget->core.parent) == xmScrolledWindowWidgetClass)
2941 #endif
2942 	_XmRedisplayVBar(widget);
2943       if (widget->text.output->data->scrollhorizontal &&
2944 #ifdef FIX_1147
2945 	  XmIsScrolledWindow(XtParent(widget)) &&
2946 #else
2947 	  XtClass(widget->core.parent) == xmScrolledWindowWidgetClass &&
2948 #endif
2949 	  !widget->text.hsbar_scrolling)
2950 	_XmChangeHSB(widget);
2951     } else {
2952       if (widget->text.output->data->scrollvertical &&
2953 #ifdef FIX_1147
2954 	  XmIsScrolledWindow(XtParent(widget)) &&
2955 #else
2956 	  XtClass(widget->core.parent) == xmScrolledWindowWidgetClass &&
2957 #endif
2958 	  !widget->text.vsbar_scrolling)
2959 	_XmChangeVSB(widget);
2960       if (widget->text.output->data->scrollhorizontal &&
2961 #ifdef FIX_1147
2962 	  XmIsScrolledWindow(XtParent(widget)))
2963 #else
2964 	  XtClass(widget->core.parent) == xmScrolledWindowWidgetClass)
2965 #endif
2966 	_XmRedisplayHBar(widget);
2967     }
2968   }
2969 
2970   TextDrawInsertionPoint(widget);
2971 }
2972 
2973 /* Count the number of characters represented in the char* str.  By
2974  * definition, if MB_CUR_MAX == 1 then num_count_bytes == number of characters.
2975  * Otherwise, use mblen to calculate. */
2976 
2977 int
_XmTextCountCharacters(char * str,int num_count_bytes)2978 _XmTextCountCharacters(char *str,
2979 		       int num_count_bytes)
2980 {
2981   char * bptr;
2982   int count = 0;
2983   int char_size = 0;
2984 
2985   if (num_count_bytes <= 0)
2986     return 0;
2987 
2988 #ifndef NO_MULTIBYTE
2989   if (MB_CUR_MAX == 1 || MB_CUR_MAX == 0) /* Sun sets MB_CUR_MAX to 0, Argg!!*/
2990 #endif
2991     return num_count_bytes;
2992 
2993   for (bptr = str; num_count_bytes > 0; count++, bptr+= char_size) {
2994     char_size = mblen(bptr, MB_CUR_MAX);
2995     if (char_size <= 0) break; /* error */
2996     num_count_bytes -= char_size;
2997   }
2998   return count;
2999 }
3000 
3001 void
_XmTextSetEditable(Widget widget,int editable)3002 _XmTextSetEditable(Widget widget,
3003 #if NeedWidePrototypes
3004 		  int editable)
3005 #else
3006                   Boolean editable)
3007 #endif /* NeedWidePrototypes */
3008 {
3009   Arg args[20];
3010   XIMCallback xim_cb[4];
3011   Cardinal n = 0;
3012   XPoint xmim_point;
3013   XRectangle xmim_area;
3014   XmTextWidget tw = (XmTextWidget) widget;
3015 
3016   if (!tw->text.editable && editable) {
3017     OutputData o_data = tw->text.output->data;
3018 
3019     XmImRegister(widget, (unsigned int) NULL);
3020 
3021     (*tw->text.output->PosToXY)(tw, tw->text.cursor_position,
3022 				&xmim_point.x, &xmim_point.y);
3023     (void)_XmTextGetDisplayRect((Widget)tw, &xmim_area);
3024     n = 0;
3025     XtSetArg(args[n], XmNfontList, o_data->fontlist); n++;
3026     XtSetArg(args[n], XmNbackground, widget->core.background_pixel); n++;
3027     XtSetArg(args[n], XmNforeground, tw->primitive.foreground); n++;
3028     XtSetArg(args[n], XmNbackgroundPixmap,
3029 	     widget->core.background_pixmap); n++;
3030     XtSetArg(args[n], XmNspotLocation, &xmim_point); n++;
3031     XtSetArg(args[n], XmNarea, &xmim_area); n++;
3032     XtSetArg(args[n], XmNlineSpace, o_data->lineheight); n++;
3033 
3034    /*
3035     * 	Register on the spot callbacks.
3036     */
3037 
3038    xim_cb[0].client_data = (XPointer)tw;
3039    xim_cb[0].callback = (XIMProc)PreeditStart;
3040    xim_cb[1].client_data = (XPointer)tw;
3041    xim_cb[1].callback = (XIMProc)PreeditDone;
3042    xim_cb[2].client_data = (XPointer)tw;
3043    xim_cb[2].callback = (XIMProc)PreeditDraw;
3044    xim_cb[3].client_data = (XPointer)tw;
3045    xim_cb[3].callback = (XIMProc)PreeditCaret;
3046    XtSetArg(args[n], XmNpreeditStartCallback, &xim_cb[0]); n++;
3047    XtSetArg(args[n], XmNpreeditDoneCallback, &xim_cb[1]); n++;
3048    XtSetArg(args[n], XmNpreeditDrawCallback, &xim_cb[2]); n++;
3049    XtSetArg(args[n], XmNpreeditCaretCallback, &xim_cb[3]); n++;
3050 
3051    if (o_data->hasfocus)
3052       XmImSetFocusValues(widget, args, n);
3053    else
3054       XmImSetValues(widget, args, n);
3055   } else if (tw->text.editable && !editable) {
3056     XmImUnregister(widget);
3057   }
3058 
3059   tw->text.editable = editable;
3060 
3061   n = 0;
3062 
3063   if (editable) {
3064     XtSetArg(args[n], XmNdropSiteActivity, XmDROP_SITE_ACTIVE); n++;
3065   } else {
3066     XtSetArg(args[n], XmNdropSiteActivity, XmDROP_SITE_INACTIVE); n++;
3067   }
3068 
3069   XmDropSiteUpdate(widget, args, n);
3070 
3071   _XmStringSourceSetEditable(GetSrc(tw), editable);
3072 }
3073 
3074 void
_XmTextSetHighlight(Widget w,XmTextPosition left,XmTextPosition right,XmHighlightMode mode)3075 _XmTextSetHighlight(Widget w,
3076 		   XmTextPosition left,
3077 		   XmTextPosition right,
3078 		   XmHighlightMode mode)
3079 {
3080   XmTextWidget tw = (XmTextWidget)w;
3081   _XmHighlightRec *l;
3082   XmHighlightMode endmode;
3083   int i, j;
3084   _XmWidgetToAppContext(w);
3085 
3086   _XmAppLock(app);
3087 
3088   /* If right position is out-bound, change it to the last position. */
3089   if (right > tw->text.last_position)
3090     right = tw->text.last_position;
3091 
3092   /* If left is out-bound, don't do anything. */
3093   if (left >= right || right <= 0) {
3094     _XmAppUnlock(app);
3095     return;
3096   }
3097 
3098   if (left < 0)
3099     left = 0;
3100 
3101   EraseInsertionPoint(tw);
3102   if (!tw->text.highlight_changed) {
3103     tw->text.highlight_changed = TRUE;
3104     if (tw->text.old_highlight.maximum < tw->text.highlight.number) {
3105       tw->text.old_highlight.maximum = tw->text.highlight.number;
3106       tw->text.old_highlight.list = (_XmHighlightRec *)
3107 	XtRealloc((char *)tw->text.old_highlight.list,
3108 		  tw->text.old_highlight.maximum *
3109 		  sizeof(_XmHighlightRec));
3110     }
3111     tw->text.old_highlight.number = tw->text.highlight.number;
3112     memcpy((void *) tw->text.old_highlight.list,
3113 	   (void *) tw->text.highlight.list,
3114 	   (size_t) tw->text.old_highlight.number *
3115 	   sizeof(_XmHighlightRec));
3116   }
3117   endmode = FindHighlight(tw, right, XmsdLeft)->mode;
3118   InsertHighlight(tw, left, mode);
3119   InsertHighlight(tw, right, endmode);
3120   l = tw->text.highlight.list;
3121   i = 1;
3122   while (i < tw->text.highlight.number) {
3123     if (l[i].position >= left && l[i].position < right)
3124       l[i].mode = mode;
3125     if (l[i].mode == l[i-1].mode) {
3126       tw->text.highlight.number--;
3127       for (j=i; j<tw->text.highlight.number; j++)
3128 	l[j] = l[j+1];
3129     } else i++;
3130   }
3131   /* Force the image GC to be updated based on the new highlight record */
3132   _XmTextMovingCursorPosition(tw, tw->text.cursor_position);
3133   tw->text.needs_redisplay = TRUE;
3134   if (tw->text.disable_depth == 0)
3135     Redisplay(tw);
3136 
3137   tw->text.output->data->refresh_ibeam_off = True;
3138   TextDrawInsertionPoint(tw);
3139 
3140   _XmAppUnlock(app);
3141 }
3142 
3143 void
_XmTextShowPosition(Widget widget,XmTextPosition position)3144 _XmTextShowPosition(Widget widget,
3145 		    XmTextPosition position)
3146 {
3147   XmTextWidget tw = (XmTextWidget) widget;
3148   _XmWidgetToAppContext(widget);
3149 
3150   _XmAppLock(app);
3151 
3152   if (!tw->text.needs_refigure_lines &&
3153       (position < 0 || (position >= tw->text.top_character &&
3154 			position < tw->text.bottom_position))) {
3155     (*tw->text.output->MakePositionVisible)(tw, position);
3156     _XmAppUnlock(app);
3157     return;
3158   }
3159   tw->text.force_display = position;
3160   tw->text.needs_refigure_lines = tw->text.needs_redisplay = TRUE;
3161 
3162   if (tw->text.disable_depth == 0) Redisplay(tw);
3163 
3164   _XmAppUnlock(app);
3165 }
3166 
3167 /* Why is this here? It's never used */
3168 int
_XmTextGetTotalLines(Widget widget)3169 _XmTextGetTotalLines(Widget widget)
3170 {
3171   return(((XmTextWidget)widget)->text.total_lines);
3172 }
3173 
3174 
3175 /* Why is this here? It's never used */
3176 XmTextLineTable
_XmTextGetLineTable(Widget widget,int * total_lines)3177 _XmTextGetLineTable(Widget widget,
3178 		    int *total_lines)
3179 {
3180   XmTextWidget tw = (XmTextWidget) widget;
3181   XmTextLineTable line_table;
3182 
3183   *total_lines = tw->text.total_lines;
3184   line_table = (XmTextLineTable) XtMalloc((unsigned) *total_lines *
3185 					  sizeof(XmTextLineTableRec));
3186 
3187   memcpy((void *) line_table, (void *) tw->text.line_table,
3188 	 *total_lines * sizeof(XmTextLineTableRec));
3189 
3190   return line_table;
3191 }
3192 
3193 
3194 /********************************************
3195  * AccessTextual trait method implementation
3196  ********************************************/
3197 
3198 static XtPointer
TextGetValue(Widget w,int format)3199 TextGetValue(Widget w,
3200 	     int format)
3201 {
3202   char *str;
3203   XmString tmp;
3204 
3205   switch(format) {
3206   case XmFORMAT_XmSTRING:
3207     str = XmTextGetString(w);
3208     tmp = XmStringCreateLocalized(str);
3209     if (str != NULL) XtFree(str);
3210     return((XtPointer) tmp);
3211   case XmFORMAT_MBYTE:
3212     return((XtPointer) XmTextGetString(w));
3213   case XmFORMAT_WCS:
3214     return((XtPointer) XmTextGetStringWcs(w));
3215   }
3216 
3217   return(NULL);
3218 }
3219 
3220 static void
TextSetValue(Widget w,XtPointer s,int format)3221 TextSetValue(Widget w,
3222 	     XtPointer s,
3223 	     int format)
3224 {
3225   char *str;
3226 
3227   switch(format) {
3228   case XmFORMAT_XmSTRING:
3229     str = (char*) _XmStringUngenerate((XmString)s, NULL,
3230 				      XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT);
3231     XmTextSetString(w, str);
3232     if (str != NULL) XtFree(str);
3233     break;
3234   case XmFORMAT_MBYTE:
3235     XmTextSetString(w, (char*) s);
3236     break;
3237   case XmFORMAT_WCS:
3238     XmTextSetStringWcs(w, (wchar_t *) s);
3239   }
3240 }
3241 
3242 /*ARGSUSED*/
3243 static int
TextPreferredValue(Widget w)3244 TextPreferredValue(Widget w)	/* unused */
3245 {
3246   return(XmFORMAT_MBYTE);
3247 }
3248 
3249 /**
3250  ** New functions for the on the spot support.
3251  **/
3252 
3253 /*
3254  * This function and _XmTextSetCursorPosition are almost the same.
3255  * The difference is that this function doesn't call any user's
3256  * callbacks like XmNmotionVerifyCallback
3257  */
3258 static void
_XmTextPreeditSetCursorPosition(Widget widget,XmTextPosition position)3259 _XmTextPreeditSetCursorPosition(Widget widget,
3260                                 XmTextPosition position)
3261 {
3262   XmTextWidget tw = (XmTextWidget) widget;
3263   XmTextSource source;
3264   Position dummy;
3265 
3266   if (position < 0) {
3267     position = 0;
3268   }
3269 
3270   if (position > tw->text.last_position) {
3271     position = tw->text.last_position;
3272   }
3273 
3274   source = GetSrc(tw);
3275 
3276   /* Erase insert cursor prior to move */
3277   EraseInsertionPoint(tw);
3278   tw->text.cursor_position = position;
3279 
3280   /* ensure that IBeam at new location will be displayed correctly */
3281   _XmTextMovingCursorPosition(tw, position); /*correct GC for new location */
3282   (*tw->text.output->PosToXY) (tw, position, &(tw->text.cursor_position_x),
3283                                &dummy);
3284   if (tw->text.auto_show_cursor_position)
3285     XmTextShowPosition(widget, position);
3286   if (tw->text.needs_redisplay && tw->text.disable_depth == 0)
3287     Redisplay(tw);
3288 
3289   _XmTextResetClipOrigin(tw, position, False); /* move clip origin */
3290   tw->text.output->data->refresh_ibeam_off = True; /* update IBeam off area
3291                                                     * before drawing IBeam */
3292 
3293   TextDrawInsertionPoint(tw);
3294 }
3295 
PreeditVerifyReplace(Widget w,XmTextPosition frompos,XmTextPosition topos,char * mb,XmTextPosition cursor,Boolean * end_preedit)3296 static void PreeditVerifyReplace(Widget w,
3297 			 XmTextPosition frompos,
3298 			 XmTextPosition topos,
3299 			 char *mb,
3300 			 XmTextPosition cursor,
3301 			 Boolean *end_preedit)
3302 {
3303   XmTextWidget tw = (XmTextWidget)w;
3304 
3305   UnderVerifyPreedit(tw) = True;
3306   _XmTextReplace(w, frompos, topos, mb, False);
3307   UnderVerifyPreedit(tw) = False;
3308   if (VerifyCommitNeeded(tw)) {
3309     _XmTextResetIC(w);
3310     *end_preedit = True;
3311   }
3312   _XmTextSetCursorPosition(w, cursor);
3313 }
3314 
3315 
3316 
3317 /*
3318  * This is the function set to XNPreeditStartCallback resource.
3319  * This function is called when the preedit process starts.
3320  * Initialize the preedit data and also treat pending delete.
3321  */
3322 static int
PreeditStart(XIC xic,XPointer client_data,XPointer call_data)3323 PreeditStart(XIC xic,
3324              XPointer client_data,
3325              XPointer call_data)
3326 {
3327   XmTextPosition left, right, lastPos;
3328   Widget w = (Widget) client_data;
3329   XmTextWidget tw = (XmTextWidget) client_data;
3330 
3331   if (PreUnder(tw))
3332     return 0;
3333 
3334   /* check editable */
3335   if (!tw->text.source->data->editable){
3336     PreUnder(tw) = False;
3337     return 0;
3338   }
3339 
3340   PreOverLen(tw) = PreOverMaxLen(tw) = 0L;
3341   PreOverStr(tw) = NULL;
3342 
3343   /* Treat Pending delete */
3344   if (_XmTextNeedsPendingDeleteDis(tw, &left, &right, False))
3345     _XmTextReplace(w, left, right, NULL, False);
3346 
3347   PreStartTW(tw) = PreEndTW(tw) = PreCursorTW(tw) = XmTextGetCursorPosition(w);
3348   PreUnder(tw) = True;
3349 
3350   /* when overstrike mode, stock text buffer */
3351   if (tw->text.input->data->overstrike){
3352     lastPos = (*(tw->text.source->Scan))(tw->text.source,
3353                                          PreCursorTW(tw),
3354                                          XmSELECT_LINE, XmsdRight, 1, TRUE);
3355     PreOverLen(tw) = lastPos - PreCursorTW(tw);
3356     PreOverStr(tw) = _XmStringSourceGetString(tw, PreCursorTW(tw),
3357                                               lastPos, False);
3358   }
3359 
3360   return (-1);
3361 }
3362 
3363 /*
3364  * This is the function set to XNPreeditDoneCallback resource.
3365  * This function is called when the preedit process is finished.
3366  */
3367 static void
PreeditDone(XIC xic,XPointer client_data,XPointer call_data)3368 PreeditDone(XIC xic,
3369             XPointer client_data,
3370             XPointer call_data)
3371 {
3372   char *mb;
3373   XmTextBlockRec block;
3374   XmTextWidget tw = (XmTextWidget)client_data;
3375   Widget w = (Widget)client_data;
3376   int size, num_bytes = 0;
3377   Widget p = w;
3378   Boolean need_verify, end_preedit = False;
3379 
3380   if (!PreUnder(tw))
3381     return;
3382 
3383   while (!XtIsShell(p))
3384     p = XtParent(p);
3385   XtVaGetValues(p, XmNverifyPreedit, &need_verify, NULL);
3386 
3387   /*
3388    * Delete preedit string
3389    */
3390   if (PreEndTW(tw) > PreStartTW(tw)) {
3391     if (need_verify) {
3392 	PreeditVerifyReplace(w, PreStartTW(tw), PreEndTW(tw), NULL,
3393 				PreStartTW(tw), &end_preedit);
3394 	if (end_preedit) return;
3395     }
3396     else {
3397     	block.ptr = NULL;
3398     	block.length = 0;
3399     	block.format = XmFMT_8_BIT;
3400     	(*tw->text.source->Replace)(tw, NULL, &PreStartTW(tw), &PreEndTW(tw),
3401 				&block, False);
3402     }
3403   }
3404 
3405   if (tw->text.input->data->overstrike && PreOverMaxLen(tw) > 0){
3406     if (PreOverMaxLen(tw) == PreOverLen(tw))
3407       mb = PreOverStr(tw);
3408     else {
3409         mb = XtMalloc((PreOverMaxLen(tw)+1)*tw->text.char_size);
3410         for (size = PreOverMaxLen(tw); size >0; size--)
3411            num_bytes +=mblen(PreOverStr(tw)+num_bytes, tw->text.char_size);
3412         memmove (mb, PreOverStr(tw), num_bytes);
3413         mb[num_bytes] = 0;
3414     }
3415 
3416     if (need_verify) {
3417 	PreeditVerifyReplace(w, PreStartTW(tw), PreStartTW(tw), mb,
3418                                 PreStartTW(tw), &end_preedit);
3419         if (end_preedit) return;
3420     }
3421     else {
3422 	(*tw->text.output->DrawInsertionPoint)(tw, tw->text.cursor_position,
3423                                                                 off);
3424     	block.ptr = mb;
3425     	block.length = strlen(block.ptr);
3426     	block.format = XmFMT_8_BIT;
3427 
3428     	(*tw->text.source->Replace)(tw, NULL, &PreStartTW(tw), &PreStartTW(tw),
3429 				&block, False);
3430     	_XmTextPreeditSetCursorPosition(w, PreStartTW(tw));
3431 	(*tw->text.output->DrawInsertionPoint)(tw, tw->text.cursor_position,
3432                                                                 on);
3433     }
3434 
3435     if (PreOverMaxLen(tw) != PreOverLen(tw))
3436       XtFree(mb);
3437     PreOverMaxLen(tw) = PreOverLen(tw) = 0;
3438     XtFree((char *)PreOverStr(tw));
3439   }
3440 
3441   PreStartTW(tw) = PreEndTW(tw) = PreCursorTW(tw) = 0;
3442   PreUnder(tw) = False;
3443 }
3444 
3445 /*
3446  * This function shows the correspondence of rendition data between
3447  * the input server and XmTextField.
3448  */
3449 static XmHighlightMode
_XimFeedbackToXmHighlightMode(XIMFeedback fb)3450 _XimFeedbackToXmHighlightMode(XIMFeedback fb)
3451 {
3452   switch (fb) {
3453   case XIMReverse:
3454     return(XmHIGHLIGHT_SELECTED);
3455   case XIMUnderline:
3456     return(XmHIGHLIGHT_SECONDARY_SELECTED);
3457   case XIMHighlight:
3458     return(XmHIGHLIGHT_NORMAL);
3459   case XIMPrimary:
3460     return(XmHIGHLIGHT_SELECTED);
3461   case XIMSecondary:
3462     return(XmHIGHLIGHT_SECONDARY_SELECTED);
3463   case XIMTertiary:
3464     return(XmHIGHLIGHT_SELECTED);
3465   default:
3466     return(XmHIGHLIGHT_NORMAL);
3467   }
3468 }
3469 
3470 /*
3471  * This function treats the rendition data.
3472  */
3473 static void
PreeditSetRendition(Widget w,XIMPreeditDrawCallbackStruct * data)3474 PreeditSetRendition(Widget w,
3475                     XIMPreeditDrawCallbackStruct* data)
3476 {
3477   XIMText *text = data->text;
3478   unsigned short cnt;
3479   XIMFeedback fb;
3480   XmTextPosition prestart = PreStartTW((XmTextWidget)w)+data->chg_first, left, right;
3481   XmHighlightMode mode;
3482 
3483   if (!text->length)
3484     return;
3485 
3486   if (!text->feedback)
3487     return;
3488 
3489   fb = text->feedback[0];                       /* initial feedback */
3490   left = right = prestart;                      /* mode start/end position */
3491   mode = _XimFeedbackToXmHighlightMode(fb);     /* mode */
3492   cnt = 1;                                      /* counter initialize */
3493 
3494   while (cnt < text->length) {
3495     if (fb != text->feedback[cnt]) {
3496       right = prestart + cnt;
3497       XmTextSetHighlight(w, left, right, mode);
3498 
3499       left = right;                             /* start position update */
3500       fb = text->feedback[cnt];                 /* feedback update */
3501       mode = _XimFeedbackToXmHighlightMode(fb);
3502     }
3503     cnt++;                                      /* counter increment */
3504   }
3505   XmTextSetHighlight(w, left, (prestart + cnt), mode);
3506                                                 /* for the last segment */
3507 }
3508 
3509 #define TEXT_MAX_INSERT_SIZE 512
3510 
3511 /*
3512  * This is the function set to XNPreeditDrawCallback resource.
3513  * This function is called when the input server requests XmText
3514  * to draw a preedit string.
3515  */
3516 static void
PreeditDraw(XIC xic,XPointer client_data,XIMPreeditDrawCallbackStruct * call_data)3517 PreeditDraw(XIC xic,
3518             XPointer client_data,
3519             XIMPreeditDrawCallbackStruct *call_data)
3520 {
3521   Widget w = (Widget) client_data;
3522   XmTextWidget tw = (XmTextWidget) client_data;
3523   InputData data = tw->text.input->data;
3524   XmTextPosition startPos, endPos, rest_len, tmp_end;
3525   char *mb, *over_mb;
3526   XmTextBlockRec block;
3527   unsigned short insert_length=0;
3528   int i;
3529   int total_mb_len;
3530   int recover_len = 0;
3531   char *ptr;
3532   OutputData o_data = tw->text.output->data;
3533   XFontStruct *font = o_data->font;
3534   XRectangle overall_ink;
3535   int escapement;
3536   size_t mb_siz;
3537   Widget p =w;
3538   Boolean need_verify, end_preedit = False;
3539 
3540   if (!PreUnder(tw))
3541     return;
3542 
3543   /* if no data in callback structs simply return - nothing to do */
3544   if (!call_data->caret && !call_data->chg_first && !call_data->chg_length
3545       && !call_data->text)
3546     return;
3547 
3548   /* have we exceeded max size of preedit buffer? - then punt */
3549   if (call_data->text &&
3550       ((insert_length = call_data->text->length) > TEXT_MAX_INSERT_SIZE))
3551     return;
3552 
3553   if (call_data->chg_length>PreEndTW(tw)-PreStartTW(tw))
3554     call_data->chg_length = PreEndTW(tw)-PreStartTW(tw);
3555 
3556   /* loop to determine parent shell widget id */
3557   while (!XtIsShell(p))
3558     p = XtParent(p);
3559 
3560   /* determine whether verify preedit is set in shell widget */
3561   XtVaGetValues(p, XmNverifyPreedit, &need_verify, NULL);
3562 
3563   /* turn cursor off */
3564   (*tw->text.output->DrawInsertionPoint)(tw, tw->text.cursor_position, off);
3565   XmTextSetHighlight(w, PreStartTW(tw)+call_data->chg_first,
3566                 PreStartTW(tw) + call_data->chg_first + call_data->chg_length,
3567                 XmHIGHLIGHT_NORMAL);
3568 
3569   /* preedit deletion */
3570   if (!data->overstrike && (!call_data->text || !insert_length)){
3571     startPos = PreStartTW(tw) + call_data->chg_first;
3572     endPos = startPos + call_data->chg_length;
3573     PreCursorTW(tw) = startPos;
3574     PreEndTW(tw) -= endPos - startPos;
3575 
3576     if (need_verify) {
3577       PreeditVerifyReplace(w, startPos, endPos, NULL, startPos, &end_preedit);
3578       if (end_preedit) {
3579 	(*tw->text.output->DrawInsertionPoint)(tw, tw->text.cursor_position,
3580 					       on);
3581 	return;
3582       }
3583     }
3584     else {
3585       block.ptr = NULL;
3586       block.length = 0;
3587       block.format = XmFMT_8_BIT;
3588 
3589       if ((*tw->text.source->Replace)(tw, NULL, &startPos, &endPos,
3590 				      &block, False) != EditDone) {
3591       	  XBell(XtDisplay(tw), 0);
3592 	  return;
3593       }
3594       else
3595       	_XmTextPreeditSetCursorPosition(w, PreCursorTW(tw));
3596     }
3597     (*tw->text.output->DrawInsertionPoint)(tw, tw->text.cursor_position, on);
3598     return;
3599   }
3600 
3601   /* sanity check data to make sure its *really* there */
3602   if (call_data->text)
3603     if ((call_data->text->encoding_is_wchar &&
3604 	 !call_data->text->string.wide_char) ||
3605 	(!call_data->text->encoding_is_wchar &&
3606 	 !call_data->text->string.multi_byte)){
3607 
3608       PreeditSetRendition(w, call_data);
3609       (*tw->text.output->DrawInsertionPoint)(tw, tw->text.cursor_position, on);
3610       return;
3611     }
3612 
3613   /* convert text data to char - it may be wchar or char */
3614   if (insert_length > 0){
3615     if (o_data->use_fontset) {
3616       if (call_data->text->encoding_is_wchar){
3617         mb = XtMalloc((insert_length+1)*tw->text.char_size);
3618         mb_siz = wcstombs(mb, call_data->text->string.wide_char,
3619                   insert_length);
3620       }
3621       else {
3622 	mb = XtMalloc((insert_length+1)*tw->text.char_size);
3623         strcpy(mb,call_data->text->string.multi_byte);
3624       }
3625 
3626       /* set TextExtents for preedit data, if unable, punt */
3627       escapement = XmbTextExtents((XFontSet)font, mb, strlen(mb),
3628                                   &overall_ink, NULL );
3629       if (escapement == 0 && overall_ink.width == 0 &&
3630           strchr(mb, '\t') == 0 ) {
3631 
3632         XtFree(mb);
3633 	(*tw->text.output->DrawInsertionPoint)(tw, tw->text.cursor_position,
3634 					       on);
3635         return;
3636       }
3637     }
3638     else {
3639       (*tw->text.output->DrawInsertionPoint)(tw, tw->text.cursor_position, on);
3640       return;
3641     }
3642   }
3643   else {
3644     mb = XtMalloc(4);
3645     mb[0] = '\0';
3646   }
3647 
3648   /* setup overstrike buffers and data */
3649   if (data->overstrike) {
3650     startPos = PreStartTW(tw) + call_data->chg_first;
3651     tmp_end = (XmTextPosition)(PreEndTW(tw) + insert_length -
3652                                call_data->chg_length);
3653     if (PreOverMaxLen(tw) < tmp_end - PreStartTW(tw)){
3654       if (tmp_end - PreStartTW(tw) > PreOverLen(tw)){
3655         endPos = startPos + call_data->chg_length;
3656         PreOverMaxLen(tw) = PreOverLen(tw);
3657       }
3658       else {
3659         endPos = PreEndTW(tw) + tmp_end - PreStartTW(tw) - PreOverMaxLen(tw);
3660         PreOverMaxLen(tw) = tmp_end - PreStartTW(tw);
3661       }
3662     }
3663     else {
3664       if (PreOverMaxLen(tw) > tmp_end - PreStartTW(tw)){
3665 	endPos = PreEndTW(tw);
3666 	recover_len = PreOverMaxLen(tw) - tmp_end + PreStartTW(tw);
3667 	PreOverMaxLen(tw) = tmp_end - PreStartTW(tw);
3668       }
3669       else
3670 	endPos = startPos + call_data->chg_length;
3671     }
3672 
3673     rest_len = PreEndTW(tw) - PreStartTW(tw) - call_data->chg_first -
3674       call_data->chg_length;
3675     if (rest_len) {
3676       over_mb = _XmStringSourceGetString(tw, (XmTextPosition)
3677 		  (PreStartTW(tw)+call_data->chg_first+call_data->chg_length),
3678 		  PreEndTW(tw), False);
3679       mb = XtRealloc(mb, strlen(mb)+strlen(over_mb)+1);
3680       strcat(mb, over_mb);
3681       XtFree(over_mb);
3682     }
3683 
3684     if (recover_len > 0) {
3685       mb = XtRealloc(mb, strlen(mb) + (recover_len + 1 ) * tw->text.char_size);
3686       ptr = PreOverStr(tw);
3687       for (i=0; i<PreOverMaxLen(tw); i++)
3688 	ptr += mblen(ptr, 4);
3689       total_mb_len = 0;
3690       for (i=0; i<recover_len; i++)
3691 	total_mb_len += mblen(ptr + total_mb_len, 4);
3692       i = strlen(mb);
3693       strncat(mb, ptr, total_mb_len);
3694       mb[i+total_mb_len] = '\0';
3695     }
3696   }
3697   else {
3698     startPos = PreStartTW(tw) + call_data->chg_first;
3699     endPos = startPos + call_data->chg_length;
3700   }
3701 
3702   if (data->overstrike)
3703       PreEndTW(tw) = startPos + insert_length;
3704   else
3705       PreEndTW(tw) += insert_length - endPos + startPos;
3706   PreCursorTW(tw) = PreStartTW(tw) + call_data->caret;
3707 
3708   /* verify preedit set, so call PreeditVerifyReplace */
3709   if (need_verify) {
3710     PreeditVerifyReplace(w, startPos, endPos, mb,
3711 			 PreCursorTW(tw), &end_preedit);
3712     if (end_preedit) {
3713       (*tw->text.output->DrawInsertionPoint)(tw, tw->text.cursor_position, on);
3714       return;
3715     }
3716   }
3717   /* no need to verify, just insert text into buffer */
3718   else {
3719     block.ptr = mb;
3720     block.length = strlen(mb);
3721     block.format = XmFMT_8_BIT;
3722     if ((*tw->text.source->Replace)(tw, NULL, &startPos, &endPos,
3723 				    &block, False) != EditDone) {
3724       XBell(XtDisplay(tw), 0);
3725       return;
3726     }
3727     else
3728       _XmTextPreeditSetCursorPosition(w, PreCursorTW(tw));
3729   }
3730 
3731   /* set feedback */
3732   if (insert_length>0)
3733     PreeditSetRendition(w, call_data);
3734 
3735   /* turn cursor back on */
3736   (*tw->text.output->DrawInsertionPoint)(tw, tw->text.cursor_position, on);
3737   if (mb)
3738     XtFree(mb);
3739 }
3740 
3741 /*
3742  * This is the function set to XNPreeditCaretCallback resource.
3743  * This function is called when the input server requests XmText to move
3744  * the caret.
3745  */
3746 static void
PreeditCaret(XIC xic,XPointer client_data,XIMPreeditCaretCallbackStruct * call_data)3747 PreeditCaret(XIC xic,
3748              XPointer client_data,
3749              XIMPreeditCaretCallbackStruct *call_data)
3750 {
3751   XmTextWidget tw = (XmTextWidget) client_data;
3752   XmSourceData data = tw->text.source->data;
3753   Widget w = (Widget) client_data;
3754   XmTextPosition new_position, start = 0;
3755   Widget p = (Widget) tw;
3756   Boolean need_verify;
3757 
3758   (*tw->text.output->DrawInsertionPoint)(tw, tw->text.cursor_position, off);
3759   while (!XtIsShell(p))
3760     p = XtParent(p);
3761   XtVaGetValues(p, XmNverifyPreedit, &need_verify, NULL);
3762 
3763   switch (call_data->direction) {
3764   case XIMForwardChar:
3765     new_position = PreCursorTW(tw) + 1 - PreStartTW(tw);
3766     break;
3767   case XIMBackwardChar:
3768     new_position = PreCursorTW(tw) - 1 - PreStartTW(tw);
3769     break;
3770   case XIMAbsolutePosition:
3771     new_position = (XmTextPosition) call_data->position;
3772     break;
3773   default:
3774     new_position = PreCursorTW(tw) - PreStartTW(tw);
3775   }
3776 
3777   _XmTextValidate(&start, &new_position, data->length);
3778   PreCursorTW(tw) = PreStartTW(tw) + new_position;
3779 
3780   if (need_verify) {
3781     UnderVerifyPreedit(tw) = True;
3782     _XmTextSetCursorPosition (w, PreCursorTW(tw));
3783     UnderVerifyPreedit(tw) = False;
3784   }
3785   else
3786     _XmTextPreeditSetCursorPosition(w, PreCursorTW(tw));
3787 
3788   (*tw->text.output->DrawInsertionPoint)(tw, tw->text.cursor_position, on);
3789 }
3790 
3791 static void
ResetUnder(XmTextWidget tw)3792 ResetUnder(XmTextWidget tw)
3793 {
3794     if (XmImGetXICResetState((Widget)tw) != XIMPreserveState)
3795         PreUnder(tw) = False;
3796 }
3797 
3798 /*
3799  * Resets input method context.
3800  *
3801  * 1. Call XmImMbResetIC to reset the input method and get the current
3802  *    preedit string.
3803  * 2. Set the string to XmText
3804  */
3805 void
_XmTextResetIC(Widget widget)3806 _XmTextResetIC(Widget widget)
3807 {
3808   int escapement, n, size;
3809   char *mb, *tmp_mb;
3810   XRectangle overall_ink;
3811   XmTextPosition cursorPos, beginPos, nextPos, lastPos;
3812   XmTextWidget tw = (XmTextWidget) widget;
3813   InputData data = tw->text.input->data;
3814   OutputData o_data = tw->text.output->data;
3815   XFontStruct *font = o_data->font;
3816 
3817   if (!PreUnder((XmTextWidget) widget))
3818     return;
3819 
3820   if (VerifyCommitNeeded(tw)) {
3821     VerifyCommitNeeded(tw) = False;
3822     mb = _XmStringSourceGetString(tw, PreStartTW(tw), PreEndTW(tw), False);
3823     XmImMbResetIC(widget, &tmp_mb);
3824     if (tmp_mb) XtFree(tmp_mb);
3825   }
3826   else
3827     XmImMbResetIC(widget, &mb);
3828 
3829   if (!mb) {
3830     ResetUnder(tw);
3831     return;
3832   }
3833   n = strlen(mb);
3834 
3835   if (n > TEXT_MAX_INSERT_SIZE) {
3836     ResetUnder(tw);
3837     return;
3838   }
3839 
3840   if (n > 0) {
3841     (*tw->text.output->DrawInsertionPoint)(tw, tw->text.cursor_position, off);
3842     mb[n]='\0';
3843     if (o_data->use_fontset) {
3844       escapement = XmbTextExtents((XFontSet)font, mb, n, &overall_ink, NULL );
3845       if (escapement == 0 && overall_ink.width == 0 &&
3846           strchr(mb, '\t') == 0 ) {
3847         (*tw->text.output->DrawInsertionPoint)(tw,
3848                                                tw->text.cursor_position, on);
3849         ResetUnder(tw);
3850         return;
3851       }
3852     } else {
3853       (*tw->text.output->DrawInsertionPoint)(tw,
3854                                              tw->text.cursor_position, on);
3855       ResetUnder(tw);
3856       return;
3857     }
3858     beginPos = nextPos = XmTextGetCursorPosition(widget);
3859 
3860     if (data->overstrike) {
3861       tmp_mb = XtMalloc((n+1)*tw->text.char_size);
3862       size = _XmTextBytesToCharacters(tmp_mb, mb, n, False,
3863                                       tw->text.char_size);
3864       nextPos += size;
3865       XtFree(tmp_mb);
3866       lastPos = (*(tw->text.source->Scan))(tw->text.source,
3867                                            beginPos, XmSELECT_LINE,
3868                                            XmsdRight, 1, TRUE);
3869       if (nextPos > lastPos) nextPos = lastPos;
3870     }
3871     else if (PreUnder(tw) && PreStartTW(tw) < PreEndTW(tw)) {
3872       beginPos = PreStartTW(tw);
3873       nextPos = PreEndTW(tw);
3874       XmTextSetHighlight((Widget)tw, beginPos, nextPos, XmHIGHLIGHT_NORMAL);
3875     }
3876 
3877     _XmTextReplace(widget, beginPos, nextPos, mb, False);
3878     (*tw->text.output->DrawInsertionPoint)(tw,
3879                                              tw->text.cursor_position, on);
3880 
3881     XtFree(mb);
3882   }
3883   ResetUnder(tw);
3884 }
3885 
3886 XmTextPosition
_XmTextSetPreeditPosition(Widget w,XmTextPosition position)3887 _XmTextSetPreeditPosition(Widget w,
3888                           XmTextPosition position)
3889 {
3890   XmTextWidget tw = (XmTextWidget)w;
3891   XmTextPosition cursorPos = position;
3892   if (tw != NULL && tw->text.onthespot) {
3893     if (PreUnder(tw) && PreStartTW(tw) < PreEndTW(tw)) {
3894       int diff = PreEndTW(tw) - PreStartTW(tw);
3895       PreStartTW(tw) = cursorPos;
3896       cursorPos += diff;
3897       PreEndTW(tw) = PreCursorTW(tw) = cursorPos;
3898     }
3899     else {
3900       PreStartTW(tw) = PreEndTW(tw) = PreCursorTW(tw) =
3901         cursorPos;
3902     }
3903   }
3904   return cursorPos;
3905 }
3906 
3907 
3908 /****************************************************************
3909  *
3910  * Public definitions.
3911  *
3912  ****************************************************************/
3913 
3914 char *
XmTextGetString(Widget widget)3915 XmTextGetString(Widget widget)
3916 {
3917   char *text_copy = NULL;
3918   _XmWidgetToAppContext(widget);
3919 
3920   _XmAppLock(app);
3921   if (XmIsTextField(widget)) {
3922     XmAccessTextualTrait textT;
3923     textT = (XmAccessTextualTrait)
3924       XmeTraitGet((XtPointer) XtClass(widget), XmQTaccessTextual);
3925     if (textT)
3926       text_copy = (char*) textT->getValue(widget, XmFORMAT_MBYTE);
3927   } else
3928     text_copy = _XmStringSourceGetValue(GetSrc(widget), False);
3929 
3930   _XmAppUnlock(app);
3931   return (text_copy);
3932 }
3933 
3934 
3935 wchar_t *
XmTextGetStringWcs(Widget widget)3936 XmTextGetStringWcs(Widget widget)
3937 {
3938   wchar_t *text_copy = NULL;
3939   _XmWidgetToAppContext(widget);
3940 
3941   _XmAppLock(app);
3942   if (XmIsTextField(widget)){
3943     XmAccessTextualTrait textT;
3944     textT = (XmAccessTextualTrait)
3945       XmeTraitGet((XtPointer) XtClass(widget), XmQTaccessTextual);
3946     if (textT)
3947       text_copy = (wchar_t *) textT->getValue(widget, XmFORMAT_WCS);
3948   }
3949   else
3950     text_copy = (wchar_t *) _XmStringSourceGetValue(GetSrc(widget), True);
3951   _XmAppUnlock(app);
3952   return (text_copy);
3953 }
3954 
3955 void
XmTextSetString(Widget widget,char * value)3956 XmTextSetString(Widget widget,
3957 		char *value)
3958 {
3959   _XmWidgetToAppContext(widget);
3960 
3961   _XmAppLock(app);
3962   if (XmIsTextField(widget)) {
3963     XmAccessTextualTrait textT;
3964     textT = (XmAccessTextualTrait)
3965       XmeTraitGet((XtPointer) XtClass(widget), XmQTaccessTextual);
3966     if (textT)
3967       textT->setValue(widget, (XtPointer)value, XmFORMAT_MBYTE);
3968   } else
3969     _XmTextSetString(widget, value);
3970 
3971   _XmAppUnlock(app);
3972 }
3973 
3974 void
XmTextSetStringWcs(Widget widget,wchar_t * wc_value)3975 XmTextSetStringWcs(Widget widget,
3976 		   wchar_t *wc_value)
3977 {
3978   char * tmp;
3979   int num_chars = 0;
3980   int result;
3981   XmTextWidget tw = (XmTextWidget) widget;
3982   _XmWidgetToAppContext(widget);
3983 
3984   _XmAppLock(app);
3985   if(XmIsTextField(widget)) {
3986     XmAccessTextualTrait textT;
3987     textT = (XmAccessTextualTrait)
3988       XmeTraitGet((XtPointer) XtClass(widget), XmQTaccessTextual);
3989     if (textT)
3990       textT->setValue(widget, (XtPointer)wc_value, XmFORMAT_WCS);
3991   } else {
3992 
3993     for (num_chars = 0; wc_value[num_chars] != (wchar_t)0L; num_chars++)
3994       /*EMPTY*/;
3995 
3996     tmp = XtMalloc((unsigned) (num_chars + 1) * (int)tw->text.char_size);
3997     result = wcstombs(tmp, wc_value,
3998 		      (num_chars + 1) * (int)tw->text.char_size);
3999 
4000     if (result == (size_t) -1) {/* if wcstombs fails, it returns (size_t) -1 */
4001       XtFree(tmp);              /* if invalid data, pass in the empty string */
4002       _XmTextSetString(widget, "");
4003     } else {
4004       _XmTextSetString(widget, tmp);
4005       XtFree(tmp);
4006     }
4007   }
4008   _XmAppUnlock(app);
4009 }
4010 
4011 XmTextPosition
XmTextGetTopCharacter(Widget widget)4012 XmTextGetTopCharacter(Widget widget)
4013 {
4014   XmTextWidget tw = (XmTextWidget) widget;
4015   XmTextPosition ret_val;
4016   _XmWidgetToAppContext(widget);
4017 
4018   _XmAppLock(app);
4019   if (tw->text.needs_refigure_lines)
4020     RefigureLines(tw);
4021   ret_val = tw->text.top_character;
4022   _XmAppUnlock(app);
4023   return ret_val;
4024 }
4025 
4026 
4027 void
XmTextSetTopCharacter(Widget widget,XmTextPosition top_character)4028 XmTextSetTopCharacter(Widget widget,
4029 		      XmTextPosition top_character)
4030 {
4031   XmTextWidget tw = (XmTextWidget) widget;
4032   _XmWidgetToAppContext(widget);
4033 
4034   _XmAppLock(app);
4035    if (tw->text.output->data->resizeheight &&
4036        !(tw->text.output->data->scrollvertical &&
4037        XmIsScrolledWindow(XtParent(widget))) ) {
4038     if (tw->text.top_character == 0) {
4039       _XmAppUnlock(app);
4040       return;
4041     }
4042     else
4043       top_character = 0;
4044   }
4045 
4046   _XmTextSetTopCharacter(widget, top_character);
4047   _XmAppUnlock(app);
4048 }
4049 
4050 
4051 XmTextSource
XmTextGetSource(Widget widget)4052 XmTextGetSource(Widget widget)
4053 {
4054   XmTextWidget tw = (XmTextWidget) widget;
4055   XmTextSource ret_val;
4056   _XmWidgetToAppContext(widget);
4057 
4058   _XmAppLock(app);
4059   ret_val = tw->text.source;
4060   _XmAppUnlock(app);
4061   return ret_val;
4062 }
4063 
4064 void
XmTextSetSource(Widget widget,XmTextSource source,XmTextPosition top_character,XmTextPosition cursor_position)4065 XmTextSetSource(Widget widget,
4066 		XmTextSource source,
4067 		XmTextPosition top_character,
4068 		XmTextPosition cursor_position)
4069 {
4070   XmTextWidget tw = (XmTextWidget) widget;
4071   XmTextPosition pos = 0;
4072   XmTextPosition last_pos = 0;
4073   XmTextPosition old_pos = 0;
4074   XmTextBlockRec block;
4075   int n = 0;
4076   XPoint xmim_point;
4077   XRectangle xmim_area;
4078   Arg args[10];
4079   _XmWidgetToAppContext(widget);
4080 
4081   _XmAppLock(app);
4082 
4083   _XmTextResetIC(widget);
4084   EraseInsertionPoint(tw);
4085   if (source == NULL) {
4086     XmeWarning(widget, MESSAGE2);
4087     _XmAppUnlock(app);
4088     return;
4089   }
4090 
4091   /* zero out old line table */
4092   block.ptr = NULL;
4093   block.length = 0;
4094   _XmTextUpdateLineTable(widget, 0, 0, &block, False);
4095   tw->text.total_lines = 1;
4096 
4097   (*tw->text.source->RemoveWidget)(tw->text.source, tw);
4098   tw->text.source = source;
4099 
4100   if (cursor_position > source->data->length)
4101     cursor_position = source->data->length;
4102   else if (cursor_position < 0)
4103     cursor_position = 0;
4104 
4105   tw->text.cursor_position = cursor_position;
4106   _XmTextMovingCursorPosition(tw, cursor_position); /*correct GC for
4107 						     * new location */
4108   tw->text.output->data->refresh_ibeam_off = True;
4109   (*tw->text.source->AddWidget)(tw->text.source, tw);
4110   _XmStringSourceSetGappedBuffer(source->data, cursor_position);
4111   if (tw->text.edit_mode == XmMULTI_LINE_EDIT)
4112     top_character = (*tw->text.source->Scan)(tw->text.source, top_character,
4113 					     XmSELECT_LINE, XmsdLeft, 1,
4114 					     FALSE);
4115 
4116   tw->text.new_top = top_character;
4117   tw->text.top_character = 0;
4118 
4119   /* reset line table with new source */
4120   last_pos = (XmTextPosition) source->data->length;
4121   while (pos < last_pos) {
4122     pos = (*tw->text.source->ReadSource)(source, pos, last_pos, &block);
4123     if (block.length == 0)
4124       break;
4125     _XmTextUpdateLineTable(widget, old_pos, old_pos, &block, False);
4126     old_pos = pos;
4127   }
4128 
4129   _XmTextInvalidate(tw, top_character, top_character, NODELTA);
4130   if (tw->text.disable_depth == 0)
4131     Redisplay(tw);
4132 
4133   /* Tell the input method the new x,y location of the cursor */
4134   (*tw->text.output->PosToXY)(tw, cursor_position, &xmim_point.x,
4135 			      &xmim_point.y);
4136   (void)_XmTextGetDisplayRect((Widget)tw, &xmim_area);
4137   n = 0;
4138   XtSetArg(args[n], XmNspotLocation, &xmim_point); n++;
4139   XtSetArg(args[n], XmNarea, &xmim_area); n++;
4140   XmImSetValues((Widget)tw, args, n);
4141 
4142   TextDrawInsertionPoint(tw);
4143 
4144   _XmAppUnlock(app);
4145 }
4146 
4147 
4148 void
XmTextScroll(Widget widget,int n)4149 XmTextScroll(Widget widget,
4150 	     int n)
4151 {
4152   XmTextWidget tw = (XmTextWidget) widget;
4153   _XmWidgetToAppContext(widget);
4154 
4155   _XmAppLock(app);
4156 
4157   tw->text.pending_scroll += n;
4158   tw->text.needs_refigure_lines = tw->text.needs_redisplay = TRUE;
4159 
4160   if (tw->text.disable_depth == 0) Redisplay(tw);
4161 
4162   _XmAppUnlock(app);
4163 }
4164 
4165 void
XmTextDisableRedisplay(Widget widget)4166 XmTextDisableRedisplay(Widget widget)
4167 {
4168   _XmWidgetToAppContext(widget);
4169 
4170   _XmAppLock(app);
4171   _XmTextDisableRedisplay((XmTextWidget)widget, False);
4172   _XmAppUnlock(app);
4173 }
4174 
4175 void
XmTextEnableRedisplay(Widget widget)4176 XmTextEnableRedisplay(Widget widget)
4177 {
4178   _XmWidgetToAppContext(widget);
4179 
4180   _XmAppLock(app);
4181   _XmTextEnableRedisplay((XmTextWidget)widget);
4182   _XmAppUnlock(app);
4183 }
4184 
4185 Widget
XmCreateScrolledText(Widget parent,char * name,ArgList arglist,Cardinal argcount)4186 XmCreateScrolledText(Widget parent,
4187 		     char *name,
4188 		     ArgList arglist,
4189 		     Cardinal argcount)
4190 {
4191   Widget swindow;
4192   Widget stext;
4193   Arg args_cache[30];
4194   ArgList merged_args;
4195   int n;
4196   char s_cache[30];
4197   char *s;
4198   Cardinal s_size;
4199   Cardinal arg_size = argcount + 5;
4200   _XmWidgetToAppContext(parent);
4201 
4202   _XmAppLock(app);
4203   s_size = ((name) ? strlen(name) : 0) + 3;
4204 
4205   s = (char *) XmStackAlloc(s_size, s_cache);  /* Name + NULL + "SW" */
4206   if (name) {
4207     strcpy(s, name);
4208     strcat(s, "SW");
4209   } else {
4210     strcpy(s, "SW");
4211   }
4212 
4213   /*
4214    * merge the application arglist with the required preset arglist, for
4215    * creating the scrolled window portion of the scroll text.
4216    */
4217   merged_args = (ArgList)XmStackAlloc(arg_size*sizeof(Arg), args_cache);
4218   for (n=0; n < argcount; n++) {
4219     merged_args[n].name = arglist[n].name;
4220     merged_args[n].value = arglist[n].value;
4221   }
4222   XtSetArg(merged_args[n], XmNscrollingPolicy,
4223 	   (XtArgVal) XmAPPLICATION_DEFINED); n++;
4224   XtSetArg(merged_args[n], XmNvisualPolicy, (XtArgVal)XmVARIABLE); n++;
4225   XtSetArg(merged_args[n], XmNscrollBarDisplayPolicy, (XtArgVal)XmSTATIC); n++;
4226   XtSetArg(merged_args[n], XmNshadowThickness, (XtArgVal) 0); n++;
4227 
4228   swindow = XtCreateManagedWidget(s, xmScrolledWindowWidgetClass, parent,
4229 				  merged_args, n);
4230   XmStackFree(s, s_cache);
4231   XmStackFree((char *)merged_args, args_cache);
4232 
4233   /* Create Text widget.  */
4234   stext = XtCreateWidget(name, xmTextWidgetClass, swindow, arglist, argcount);
4235 
4236   /* Add callback to destroy ScrolledWindow parent. */
4237   XtAddCallback (stext, XmNdestroyCallback, _XmDestroyParentCallback, NULL);
4238 
4239   _XmAppUnlock(app);
4240   /* Return Text.*/
4241   return (stext);
4242 }
4243 
4244 Widget
XmCreateText(Widget parent,char * name,ArgList arglist,Cardinal argcount)4245 XmCreateText(Widget parent,
4246 	     char *name,
4247 	     ArgList arglist,
4248 	     Cardinal argcount)
4249 {
4250   return XtCreateWidget(name, xmTextWidgetClass, parent, arglist, argcount);
4251 }
4252 Widget
XmVaCreateText(Widget parent,char * name,...)4253 XmVaCreateText(
4254         Widget parent,
4255         char *name,
4256         ...)
4257 {
4258     register Widget w;
4259     va_list var;
4260     int count;
4261 
4262     Va_start(var,name);
4263     count = XmeCountVaListSimple(var);
4264     va_end(var);
4265 
4266 
4267     Va_start(var, name);
4268     w = XmeVLCreateWidget(name,
4269                          xmTextWidgetClass,
4270                          parent, False,
4271                          var, count);
4272     va_end(var);
4273     return w;
4274 
4275 }
4276 Widget
XmVaCreateManagedText(Widget parent,char * name,...)4277 XmVaCreateManagedText(
4278         Widget parent,
4279         char *name,
4280         ...)
4281 {
4282     Widget w = NULL;
4283     va_list var;
4284     int count;
4285 
4286     Va_start(var, name);
4287     count = XmeCountVaListSimple(var);
4288     va_end(var);
4289 
4290     Va_start(var, name);
4291     w = XmeVLCreateWidget(name,
4292                          xmTextWidgetClass,
4293                          parent, True,
4294                          var, count);
4295     va_end(var);
4296     return w;
4297 
4298 }
4299