1 /**
2  *
3  * $Header: /cvsroot/lesstif/lesstif/lib/Xm-2.1/Text.c,v 1.3 2005/03/29 15:28:00 dannybackx Exp $
4  *
5  * Copyright (C) 1997 Free Software Foundation, Inc.
6  * Copyright � 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005 LessTif Development Team
7  *
8  * This file is part of the GNU LessTif Library.
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public
21  * License along with this library; if not, write to the Free
22  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  **/
25 
26 static const char rcsid[] = "$Header: /cvsroot/lesstif/lesstif/lib/Xm-2.1/Text.c,v 1.3 2005/03/29 15:28:00 dannybackx Exp $";
27 
28 #define VERBOSE
29 
30 #include <LTconfig.h>
31 
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <stddef.h>    /* for  wchar_t */
36 #include <limits.h>    /* for INT_MAX */
37 #ifdef HAVE_WCHAR_H
38 #include <wchar.h>
39 #endif
40 
41 #include <Xm/XmP.h>
42 #include <Xm/TextP.h>
43 #include <Xm/TextOutP.h>
44 #include <Xm/TextF.h>
45 #include <Xm/VendorSEP.h>   /* for _XmGetAudibleWarning() only */
46 #include <Xm/CutPaste.h>
47 #include <Xm/TransltnsP.h>
48 #include <Xm/ScrolledW.h>
49 #include <Xm/XmIm.h>
50 #include <Xm/TraitP.h>
51 #include <Xm/AccTextT.h>
52 
53 #include <XmI/XmI.h>
54 
55 #include <Xm/AtomMgr.h>
56 #include <Xm/DragC.h>
57 #include <Xm/DropSMgr.h>
58 #include <Xm/DropTrans.h>
59 #include <XmI/AtomMgrI.h>
60 #include <XmI/DragDropI.h>
61 #include <X11/Xatom.h>
62 
63 #include <XmI/DebugUtil.h>
64 
65 
66 /* Forward Declarations */
67 
68 static void ClassInitialize(void);
69 static void ClassPartInitialize(WidgetClass widget_class);
70 static void Initialize(Widget request, Widget new_w,
71 		       ArgList args, Cardinal *num_args);
72 static void Destroy(Widget w);
73 static void Resize(Widget w);
74 static void Realize(Widget w, XtValueMask *value_mask,
75 		    XSetWindowAttributes *attributes);
76 static void DoExpose(Widget w, XEvent *event, Region region);
77 static XtGeometryResult query_geometry(Widget w,
78 				      XtWidgetGeometry *proposed,
79 				      XtWidgetGeometry *answer);
80 static void _XmTextSetEditable(Widget w, Boolean e);
81 static Boolean SetValues(Widget current, Widget request, Widget new_w,
82 			 ArgList args, Cardinal *num_args);
83 static void RefigureLines(XmTextWidget w);
84 static void InitializeLineTable(XmTextWidget w);
85 static Cardinal GetSecResData(WidgetClass wc,
86 			      XmSecondaryResourceData **resdata);
87 static OutputCreateProc output_create = _XmTextOutputCreate;
88 static InputCreateProc input_create = _XmTextInputCreate;
89 void _XmTextInvalidate(XmTextWidget w, XmTextPosition position,
90 		       XmTextPosition topos, long delta);
91 void _XmTextExportValue(Widget w, int offset, XtArgVal *value);
92 static void TextGetValues(Widget w, ArgList args, Cardinal *num_args);
93 
94 
95 static XtPointer _XmText_TraitGetValue(Widget w, int format);
96 static void _XmText_TraitSetValue(Widget w, XtPointer value, int format);
97 static int _XmText_TraitPreferredFormat(Widget w);
98 
99 /* Trait record */
100 XmAccessTextualTraitRec _XmTextTraitRec =
101 	{       /* version */		0,
102 		/* getValue */		_XmText_TraitGetValue,
103 		/* setValue */		_XmText_TraitSetValue,
104 		/* preferredFormat */	_XmText_TraitPreferredFormat,
105 	};
106 
107 #define Offset(_name) XtOffsetOf(XmTextRec, text._name)
108 
109 /* Resources for the Text  class */
110 static XtResource resources[] =
111 {
112     {
113 	XmNsource, XmCSource, XmRPointer,
114 	sizeof(XmTextSource), Offset(source),
115 	XmRPointer, (XtPointer)NULL
116     },
117     {
118 	XmNactivateCallback, XmCCallback, XmRCallback,
119 	sizeof(XtCallbackList), Offset(activate_callback),
120 	XmRCallback, (XtPointer)NULL
121     },
122     {
123 	XmNfocusCallback, XmCCallback, XmRCallback,
124 	sizeof(XtCallbackList), Offset(focus_callback),
125 	XmRCallback, (XtPointer)NULL
126     },
127     {
128 	XmNlosingFocusCallback, XmCCallback, XmRCallback,
129 	sizeof(XtCallbackList), Offset(losing_focus_callback),
130 	XmRCallback, (XtPointer)NULL
131     },
132     {
133 	XmNvalueChangedCallback, XmCCallback, XmRCallback,
134 	sizeof(XtCallbackList), Offset(value_changed_callback),
135 	XmRCallback, (XtPointer)NULL
136     },
137     {
138 	XmNmodifyVerifyCallback, XmCCallback, XmRCallback,
139 	sizeof(XtCallbackList), Offset(modify_verify_callback),
140 	XmRCallback, (XtPointer)NULL
141     },
142     {
143 	XmNmodifyVerifyCallbackWcs, XmCCallback, XmRCallback,
144 	sizeof(XtCallbackList), Offset(wcs_modify_verify_callback),
145 	XmRCallback, (XtPointer)NULL
146     },
147     {
148 	XmNmotionVerifyCallback, XmCCallback, XmRCallback,
149 	sizeof(XtCallbackList), Offset(motion_verify_callback),
150 	XmRCallback, (XtPointer)NULL
151     },
152     {
153 	XmNgainPrimaryCallback, XmCCallback, XmRCallback,
154 	sizeof(XtCallbackList), Offset(gain_primary_callback),
155 	XmRCallback, (XtPointer)NULL
156     },
157     {
158 	XmNlosePrimaryCallback, XmCCallback, XmRCallback,
159 	sizeof(XtCallbackList), Offset(lose_primary_callback),
160 	XmRCallback, (XtPointer)NULL
161     },
162     {
163 	XmNvalue, XmCValue, XmRString,
164 	sizeof(String), Offset(value),
165 	XmRString, (XtPointer)NULL
166     },
167     {
168 	XmNvalueWcs, XmCValueWcs, XmRValueWcs,
169 	sizeof(wchar_t *), Offset(wc_value),
170 	XmRString, (XtPointer)NULL
171     },
172     {
173 	XmNmaxLength, XmCMaxLength, XmRInt,
174 	sizeof(int), Offset(max_length),
175 	XmRImmediate, (XtPointer)INT_MAX
176     },
177     {
178 	XmNmarginHeight, XmCMarginHeight, XmRVerticalDimension,
179 	sizeof(Dimension), Offset(margin_height),
180 	XmRImmediate, (XtPointer)5
181     },
182     {
183 	XmNmarginWidth, XmCMarginWidth, XmRHorizontalDimension,
184 	sizeof(Dimension), Offset(margin_width),
185 	XmRImmediate, (XtPointer)5
186     },
187     {
188 	XmNoutputCreate, XmCOutputCreate, XmRFunction,
189 	sizeof(OutputCreateProc), Offset(output_create),
190 	XmRFunction, (XtPointer)&output_create
191     },
192     {
193 	XmNinputCreate, XmCInputCreate, XmRFunction,
194 	sizeof(InputCreateProc), Offset(input_create),
195 	XmRFunction, (XtPointer)&input_create
196     },
197     {
198 	XmNtopCharacter, XmCTopCharacter, XmRTextPosition,
199 	sizeof(XmTextPosition), Offset(top_character),
200 	XmRImmediate, (XtPointer)0
201     },
202     {
203 	XmNcursorPosition, XmCCursorPosition, XmRTextPosition,
204 	sizeof(XmTextPosition), Offset(cursor_position),
205 	XmRImmediate, (XtPointer)0
206     },
207     {
208 	XmNeditMode, XmCEditMode, XmREditMode,
209 	sizeof(int), Offset(edit_mode),
210 	XmRImmediate, (XtPointer)XmSINGLE_LINE_EDIT
211     },
212     {
213 	XmNautoShowCursorPosition, XmCAutoShowCursorPosition, XmRBoolean,
214 	sizeof(Boolean), Offset(auto_show_cursor_position),
215 	XmRImmediate, (XtPointer)True
216     },
217     {
218 	XmNeditable, XmCEditable, XmRBoolean,
219 	sizeof(Boolean), Offset(editable),
220 	XmRImmediate, (XtPointer)True
221     },
222     {
223 	XmNverifyBell, XmCVerifyBell, XmRBoolean,
224 	sizeof(Boolean), Offset(verify_bell),
225 	XtRImmediate, (XtPointer)((unsigned char)XmUNSPECIFIED)
226     },
227     {
228 	XmNnavigationType, XmCNavigationType, XmRNavigationType,
229     sizeof(XmNavigationType), XtOffsetOf(XmTextRec, primitive.navigation_type),
230 	XmRImmediate, (XtPointer)XmTAB_GROUP
231     }
232 };
233 
234 static XmSyntheticResource syn_resources[] =
235 {
236     {
237 	XmNmarginWidth,
238 	sizeof(Dimension), Offset(margin_width),
239 	_XmFromHorizontalPixels, _XmToHorizontalPixels
240     },
241     {
242 	XmNmarginHeight,
243 	sizeof(Dimension), Offset(margin_height),
244 	_XmFromVerticalPixels, _XmToVerticalPixels
245     },
246     {
247 	XmNvalue,
248 	sizeof(String), Offset(value),
249 	_XmTextExportValue, NULL
250     }
251 };
252 #undef Offset
253 
254 static XmBaseClassExtRec textBaseClassExtRec = {
255     /* next_extension            */ NULL,
256     /* record_type               */ NULLQUARK,
257     /* version                   */ XmBaseClassExtVersion,
258     /* size                      */ sizeof(XmBaseClassExtRec),
259     /* initialize_prehook        */ XmInheritInitializePrehook,
260     /* set_values_prehook        */ XmInheritSetValuesPrehook,
261     /* initialize_posthook       */ XmInheritInitializePosthook,
262     /* set_values_posthook       */ XmInheritSetValuesPosthook,
263     /* secondary_object_class    */ NULL, /* FIX ME */
264     /* secondary_object_create   */ XmInheritSecObjectCreate,
265     /* get_secondary_resources   */ GetSecResData,
266     /* fast_subclass             */ { 0 },
267     /* get_values_prehook        */ XmInheritGetValuesPrehook,
268     /* get_values_posthook       */ XmInheritGetValuesPosthook,
269     /* class_part_init_prehook   */ XmInheritClassPartInitPrehook,
270     /* class_part_init_posthook  */ XmInheritClassPartInitPosthook,
271     /* ext_resources             */ NULL,
272     /* compiled_ext_resources    */ NULL,
273     /* num_ext_resources         */ 0,
274     /* use_sub_resources         */ False,
275     /* widget_navigable          */ XmInheritWidgetNavigable,
276     /* focus_change              */ XmInheritFocusChange,
277     /* wrapper_data              */ NULL
278 };
279 
280 XmPrimitiveClassExtRec _XmTextPrimClassExtRec =
281 {
282     /* next_extension      */ NULL,
283     /* record_type         */ NULLQUARK,
284     /* version             */ XmPrimitiveClassExtVersion,
285     /* record_size         */ sizeof(XmPrimitiveClassExtRec),
286     /* widget_baseline     */ _XmTextGetBaselines,
287     /* widget_display_rect */ _XmTextGetDisplayRect,
288     /* widget_margins      */ _XmTextMarginsProc
289 };
290 
291 XmTextClassRec xmTextClassRec =
292 {
293     /* Core class part */
294   {
295 	/* superclass            */ (WidgetClass) & xmPrimitiveClassRec,
296 	/* class_name            */ "XmText",
297 	/* widget_size           */ sizeof(XmTextRec),
298 	/* class_initialize      */ ClassInitialize,
299 	/* class_part_initialize */ ClassPartInitialize,
300 	/* class_inited          */ False,
301 	/* initialize            */ Initialize,
302 	/* initialize_hook       */ NULL,
303 	/* realize               */ Realize,
304 	/* actions               */ NULL, /* set in ClassInitialize */
305 	/* num_actions           */ 0, /* set in ClassInitialize */
306 	/* resources             */ resources,
307 	/* num_resources         */ XtNumber(resources),
308 	/* xrm_class             */ NULLQUARK,
309 	/* compress_motion       */ True,
310 	/* compress_exposure     */ XtExposeCompressMaximal,
311 	/* compress_enterleave   */ True,
312 	/* visible_interest      */ False,
313 	/* destroy               */ Destroy,
314 	/* resize                */ Resize,
315 	/* expose                */ DoExpose,
316 	/* set_values            */ SetValues,
317 	/* set_values_hook       */ NULL,
318 	/* set_values_almost     */ XtInheritSetValuesAlmost,
319 	/* get_values_hook       */ TextGetValues,
320 	/* accept_focus          */ NULL,
321 	/* version               */ XtVersion,
322 	/* callback offsets      */ NULL,
323 	/* tm_table              */ NULL,
324 	/* query_geometry        */ query_geometry,
325 	/* display_accelerator   */ NULL,
326 	/* extension             */ (XtPointer) & textBaseClassExtRec
327   },
328     /* Primitive Class part */
329   {
330 	/* border_highlight      */ XmInheritBorderHighlight,
331 	/* border_unhighlight    */ XmInheritBorderUnhighlight,
332 	/* translations          */ NULL,
333 	/* arm_and_activate_proc */ NULL,
334 	/* synthetic resources   */ syn_resources,
335 	/* num syn res           */ XtNumber(syn_resources),
336 	/* extension             */ (XtPointer) & _XmTextPrimClassExtRec,
337   },
338     /* Text Class part */
339   {
340 	/* extension */ NULL
341   }
342 };
343 
344 WidgetClass xmTextWidgetClass = (WidgetClass)&xmTextClassRec;
345 
346 
347 
348 /* Inner Widget--------------------------------------------------------------
349  * the base for the Output and Input objects
350  */
351 /*
352  * Is this function ever used ?
353  */
354 static void
InnerInitialize(Widget request,Widget new_w,ArgList args,Cardinal * num_args)355 InnerInitialize(Widget request, Widget new_w, ArgList args, Cardinal *num_args)
356 {
357     DEBUGOUT(_LtDebug(__FILE__, new_w,
358 		      "InnerInitialize: %i args\n"
359 		      "\trequest X %5i Y %5i W %5i H %5i\n"
360 		      "\t  new_w X %5i Y %5i W %5i H %5i\n",
361 		      *num_args,
362 		      XtX(request), XtY(request),
363 		      XtWidth(request), XtHeight(request),
364 		      XtX(new_w), XtY(new_w),
365 		      XtWidth(new_w), XtHeight(new_w)));
366     DEBUGOUT(_LtDebugPrintArgList(__FILE__, new_w, args, *num_args, False));
367 
368 }
369 
370 /*
371  * Is this function ever used ?
372  */
373 static void
InnerDestroy(Widget w)374 InnerDestroy(Widget w)
375 {
376     /* Destroy Output and Input */
377     /* Nah - already done in XmText's destroy method (Destroy). */
378     DEBUGOUT(_LtDebug(__FILE__, w, "InnerDestroy\n"));
379 }
380 
381 /*
382  * Is this function ever used ?
383  */
384 static Boolean
InnerSetValues(Widget old,Widget request,Widget new_w,ArgList args,Cardinal * num_args)385 InnerSetValues(Widget old, Widget request, Widget new_w,
386 	       ArgList args, Cardinal *num_args)
387 {
388     Boolean refresh_needed = False;
389 
390     DEBUGOUT(_LtDebug(__FILE__, new_w,
391 		      "InnerSetValues: %i args\n"
392 		      "\t    old X %5i Y %5i W %5i H %5i\n"
393 		      "\trequest X %5i Y %5i W %5i H %5i\n"
394 		      "\t  new_w X %5i Y %5i W %5i H %5i\n",
395 		      *num_args,
396 		      XtX(old), XtY(old),
397 		      XtWidth(old), XtHeight(old),
398 		      XtX(request), XtY(request),
399 		      XtWidth(request), XtHeight(request),
400 		      XtX(new_w), XtY(new_w),
401 		      XtWidth(new_w), XtHeight(new_w)));
402     DEBUGOUT(_LtDebugPrintArgList(__FILE__, new_w, args, *num_args, False));
403 
404     return refresh_needed;
405 }
406 
407 
408 XmTextInnerClassRec xmTextInnerClassRec =
409 {
410     /* core_class fields */
411     {
412     /* superclass               */ (WidgetClass)(&objectClassRec),
413     /* class_name               */ "XmTextInner",
414     /* widget_size              */ sizeof(XmTextInnerRec),
415     /* class_initialize         */ NULL,
416     /* class_part_initialize    */ NULL,
417     /* class_inited             */ False,
418     /* initialize               */ InnerInitialize,
419     /* initialize_hook          */ NULL,
420     /* obj1                     */ NULL,
421     /* obj2                     */ NULL,
422     /* obj3                     */ 0,
423     /* resources                */ NULL,
424     /* num_resources            */ 0,
425     /* xrm_class                */ NULLQUARK,
426     /* obj4                     */ False,
427     /* obj5                     */ False,
428     /* obj6                     */ False,
429     /* obj7                     */ False,
430     /* destroy                  */ InnerDestroy,
431     /* obj8                     */ NULL,
432     /* obj9                     */ NULL,
433     /* set_values               */ InnerSetValues,
434     /* set_values_hook          */ NULL,
435     /* obj10                    */ NULL,
436     /* get_values_hook          */ NULL,
437     /* obj11                    */ NULL,
438     /* version                  */ XtVersion,
439     /* callback_private         */ NULL,
440     /* obj12                    */ NULL,
441     /* obj13                    */ NULL,
442     /* obj14                    */ NULL,
443     /* extension                */ NULL
444     },
445     /* TextInner Class part */
446     {
447 	/* extension */ NULL
448     }
449 };
450 
451 WidgetClass xmTextInnerObjectClass = (WidgetClass)&xmTextInnerClassRec;
452 
453 
454 /* Text-----------------------------------------------------------------------
455 
456  * Widget methods
457  */
458 
459 
460 static void
ClassInitialize(void)461 ClassInitialize(void)
462 {
463     DEBUGOUT(_LtDebug(__FILE__, NULL, "ClassInitialize\n"));
464 
465     textBaseClassExtRec.record_type = XmQmotif;
466     xmTextClassRec.core_class.actions =
467 	(XtActionsRec *)_XmdefaultTextActionsTable;
468 
469     xmTextClassRec.core_class.num_actions = _XmdefaultTextActionsTableSize;
470 
471     if (!XmeTraitSet((XtPointer)xmTextWidgetClass, XmQTaccessTextual,
472                      (XtPointer) &_XmTextTraitRec)) {
473 	DEBUGOUT(_LtDebug(__FILE__, NULL,
474 		"ClassInitialize: XmeTraitSet failed\n"));
475     }
476 }
477 
478 
479 static void
ClassPartInitialize(WidgetClass widget_class)480 ClassPartInitialize(WidgetClass widget_class)
481 {
482     int len1 = strlen(_XmTextIn_XmTextEventBindings1);
483     int len2 = strlen(_XmTextIn_XmTextEventBindings2);
484     int len3 = strlen(_XmTextIn_XmTextEventBindings3);
485     char *buf = XtMalloc((unsigned)(len1 + len2 + len3 + 1));
486     char *cp = buf;
487 
488     DEBUGOUT(_LtDebug(__FILE__, NULL, "ClassPartInitialize\n"));
489 
490     /* Moved from ClassInitialize because the Xt routine
491      * CoreClassPartInitialize (Xt/Core.c) will overwrite
492      * the original core_class.tm_table, thus leaking any
493      * malloc'd buffer assigned to tm_table.
494      */
495     (void)strcpy(cp, _XmTextIn_XmTextEventBindings1);
496     cp += len1;
497     (void)strcpy(cp, _XmTextIn_XmTextEventBindings2);
498     cp += len2;
499     (void)strcpy(cp, _XmTextIn_XmTextEventBindings3);
500 
501     xmTextClassRec.core_class.tm_table = (String)XtParseTranslationTable(buf);
502 
503     XtFree(buf);
504 
505     _XmFastSubclassInit(widget_class, XmTEXT_BIT);
506 }
507 
508 
509 static void
Initialize(Widget request,Widget new_w,ArgList args,Cardinal * num_args)510 Initialize(Widget request, Widget new_w,
511 	   ArgList args, Cardinal *num_args)
512 {
513     XmTextWidget w = (XmTextWidget)new_w;
514     Boolean passedSourceAsArg;
515     Atom import_target[3];
516     Arg ds_args[6];
517     int n = 0;
518 
519     DEBUGOUT(_LtDebug(__FILE__, new_w,
520 		      "initialize: %i args\n"
521 		      "\trequest X %5i Y %5i W %5i H %5i\n"
522 		      "\t  new   X %5i Y %5i W %5i H %5i\n",
523 		      *num_args,
524 		      XtX(request), XtY(request),
525 		      XtWidth(request), XtHeight(request),
526 		      XtX(new_w), XtY(new_w),
527 		      XtWidth(new_w), XtHeight(new_w)));
528     DEBUGOUT(_LtDebugPrintArgList(__FILE__, new_w, args, *num_args, False));
529 
530     if (XtWidth(request) == 0)
531     {
532 	XtWidth(new_w) = 0;
533     }
534     if (XtHeight(request) == 0)
535     {
536 	XtHeight(new_w) = 0;
537     }
538 
539 #if 0
540     XtAugmentTranslations((Widget)w,
541 			  XtParseTranslationTable(_XmText_EventBindings2));
542 
543     XtAugmentTranslations((Widget)w,
544 			  XtParseTranslationTable(_XmText_EventBindings3));
545 #endif
546 
547     w->text.inner_widget = XtCreateWidget("inner", xmTextInnerObjectClass,
548 					  new_w, args, *num_args);
549 
550     /* initialize the inner to sane values before fetching resources */
551     memset((char *)(w->text.inner_widget) + XtOffsetOf(XmTextInnerRec, inner),
552 	   0, sizeof(XmTextInnerPart));
553 
554     Text_TableSize(w) = Text_TotalLines(w) = 0;
555     Text_LineTable(w) = NULL;
556     Text_Line(w) = NULL;
557     Text_LineMax(w) = Text_LineCount(w) = 0;
558     Text_DisableDepth(w) = 0;
559     Text_FirstPos(w) = Text_LastPos(w) = Text_TopPos(w) = 0;
560     Text_DestPosition(w) = Text_CursorPos(w);
561 
562     (*Text_OutputCreate(w)) ((Widget)w, args, *num_args);
563 
564     Text_CursorPositionX(w) = Text_OutputData(w)->leftmargin;
565     passedSourceAsArg = ( Text_Source(w) != 0 );
566 
567     (*Text_InputCreate(w)) ((Widget)w, args, *num_args);
568 
569     InitializeLineTable(w);
570     if ( Text_CursorPos(w) > GetSrc(w)->data->length )
571 	Text_CursorPos(w) = GetSrc(w)->data->length;
572 
573     Text_InRedisplay(w) = False;
574     Text_InRefigureLines(w) = False;
575     Text_InExpose(w) = False;
576     Text_InResize(w) = False;
577     Text_InSetValues(w) = False;
578     Text_NeedsRedisplay(w) = True;
579     Text_NeedsRefigureLines(w) = False;
580 
581 	/* The following seem to be the same as M*tif initializes */
582     Text_AddMode(w) = False;
583     Text_PendingOff(w) = True;
584     Text_ForgetPast(w) = PASTENDPOS;
585     Text_TotalLines(w) = 1;
586     Text_ForceDisplay(w) = -1;
587     Text_Traversed(w) = False;
588     Text_OnOrOff(w) = False;
589     Text_NewTop(w) = 0;
590     Text_LastTopChar(w) = 0;
591     Text_TopLine(w) = 0;
592     Text_VSBarScrolling(w) = 0;
593     Text_TableIndex(w) = 0;
594 
595     /* Highlight array */
596     Text_Highlight(w).list = (_XmHighlightRec *)XtCalloc(32,
597 				      sizeof(_XmHighlightRec));
598     Text_Highlight(w).maximum = 32;
599     Text_Highlight(w).number = 0;
600 
601 
602     Text_Highlight(w).list[ 0 ].position = 0;
603     Text_Highlight(w).list[ 0 ].mode = XmHIGHLIGHT_NORMAL;
604 
605     Text_OldHighlight(w).maximum = 1;
606     Text_OldHighlight(w).number = 0;
607     Text_OldHighlight(w).list = XtNew(_XmHighlightRec);
608 
609     Text_Repaint(w).number = 1;
610     Text_Repaint(w).maximum = 1;
611     Text_Repaint(w).range = XtNew(RangeRec);
612     Text_Repaint(w).range[0].from=PASTENDPOS;
613     Text_Repaint(w).range[0].to = 0;
614     Text_PendingScroll(w) = 0;
615     Text_HighlightChanged(w) = False;
616 	/* FIXME : when/how is char_size more than 1 */
617     Text_CharSize(w) = 1;
618 
619     if ( Text_VerifyBell(w) == (Boolean)XmUNSPECIFIED )
620 	{
621 	Widget vendor = XtParent(w);
622 	while ( vendor && !XmIsVendorShell( vendor ) )
623 	    vendor = XtParent( vendor );
624 	if ( vendor )
625 	    Text_VerifyBell(w) = _XmGetAudibleWarning(vendor);
626 	}
627 
628     if ( (Text_Value(w) && strlen(Text_Value(w))> 0) || passedSourceAsArg )
629 	{
630 	_XmTextUpdateLineTable( (Widget)w, 0, strlen( Text_Value(w) ),
631 		       NULL, True /* it is unused */ );
632 	Text_BottomPos(w) = Text_LineTable(w)[Text_LineCount(w)].start_pos;
633 	Text_Repaint(w).range[0].to = Text_BottomPos(w);
634 	}
635      Text_Value(w) = NULL; /* amai: FIX ME! We should check for value! */
636      Text_WcsValue(w) = NULL; /* amai: FIX ME! We should check for value! */
637 
638     /* initialize default DropSite */
639     import_target[0] = XmInternAtom(XtDisplay(new_w), _XA_COMPOUND_TEXT, False);
640     import_target[1] = XmInternAtom(XtDisplay(new_w), _XA_TEXT, False);
641     import_target[2] = XA_STRING;
642     XtSetArg(ds_args[n], XmNimportTargets, import_target); n++;
643     XtSetArg(ds_args[n], XmNnumImportTargets, 3); n++;
644     XtSetArg(ds_args[n], XmNdropSiteOperations, XmDROP_COPY|XmDROP_MOVE); n++;
645     XtSetArg(ds_args[n], XmNdropProc, _Lttext_process_drop); n++;
646 
647     XmDropSiteRegister(new_w, ds_args, n);
648 }
649 
650 
651 static void
Destroy(Widget w)652 Destroy(Widget w)
653 {
654     DEBUGOUT(_LtDebug(__FILE__, w, "Destroy\n"));
655 
656     XmImCloseXIM(w);
657 
658     /* rws 2 Oct 1998
659      * This is odd, I thought Xt should be taking care of this
660      *
661      * Danny 30 Nov 1998 : only if the parent widget (XmText) is a composite.
662      *   Otherwise (like here) Xt doesn't have the information.
663      */
664     (*Text_Input(w)->destroy) (w);
665     (*Text_Output(w)->destroy) (w);
666     XtDestroyWidget(((XmTextWidget)w)->text.inner_widget);
667 
668     /* rws 1 Apr 1999
669      */
670     XtFree((char *)Text_LineTable(w));
671     if(Text_Line(w)) XtFree((char *)Text_Line(w));
672     XtFree((char *)Text_Highlight(w).list);
673     XtFree((char *)Text_OldHighlight(w).list);
674     XtFree((char *)Text_Repaint(w).range);
675 
676     /* amai: not sure this is necessary ...
677              Check out the register calls for more info.
678     XmDropSiteUnregister(w); */
679 }
680 
681 
682 static Boolean
SetValues(Widget old,Widget request,Widget new_w,ArgList args,Cardinal * num_args)683 SetValues(Widget old, Widget request, Widget new_w,
684 	  ArgList args, Cardinal *num_args)
685 {
686     Boolean refresh_needed = False;
687     XmTextWidget nw = (XmTextWidget)new_w;
688     XmTextWidget ow = (XmTextWidget)old;
689 
690     DEBUGOUT(_LtDebug(__FILE__, new_w,
691 		      "set_values: %i args\n"
692 		      "\t    old X %5i Y %5i W %5i H %5i\n"
693 		      "\trequest X %5i Y %5i W %5i H %5i\n"
694 		      "\t  new   X %5i Y %5i W %5i H %5i\n",
695 		      *num_args,
696 		      XtX(old), XtY(old),
697 		      XtWidth(old), XtHeight(old),
698 		      XtX(request), XtY(request),
699 		      XtWidth(request), XtHeight(request),
700 		      XtX(new_w), XtY(new_w),
701 		      XtWidth(new_w), XtHeight(new_w)));
702     DEBUGOUT(_LtDebugPrintArgList(__FILE__, new_w, args, *num_args, False));
703 
704     Text_InSetValues(nw) = True;
705 
706 	if (nw->core.sensitive != ow->core.sensitive) {
707 		OutputData o = Text_OutputData(new_w);
708 		XGCValues	v;
709 		int		m;
710 
711 		if (! nw->core.sensitive) {
712 			m = GCFillStyle | GCStipple;
713 			v.fill_style = FillStippled;
714 			v.stipple = XmGetPixmapByDepth(XtScreen(new_w), "50_foreground", 1, 0, 1);
715 		} else {
716 			m = GCFillStyle;
717 			v.fill_style = FillSolid;
718 		}
719 
720 		if (XtIsRealized(new_w))
721 			XChangeGC(XtDisplay(new_w), Out_DrawGC(o), m, &v);
722 		refresh_needed = True;
723 	}
724 
725     if (Text_WcsValue(nw))
726     {
727 	XmTextSetStringWcs(new_w, Text_WcsValue(new_w));
728 	Text_WcsValue(nw) = NULL;
729 	refresh_needed = True;
730     } else if (Text_Value(nw))
731     {
732 	XmTextSetString(new_w, Text_Value(new_w));
733 	Text_Value(nw) = NULL;
734 	refresh_needed = True;
735     }
736 
737 
738     if (Text_Editable(nw) != Text_Editable(ow))
739     {
740 	_XmTextSetEditable(new_w, Text_Editable(nw));
741 	refresh_needed = True;
742     }
743 
744     /* Stuff that (hopefully) requires no further treatment,
745      * but does require redisplay */
746     if (Text_EditMode(nw) != Text_EditMode(ow) ||
747 	Text_AutoShowCursorPosition(nw) != Text_AutoShowCursorPosition(ow))
748     {
749 	refresh_needed = True;
750     }
751 
752     /* Call the SetValues in the input/output objects */
753     (*Text_Input(new_w)->SetValues) (old, request, new_w, args, num_args);
754 
755     if ((*Text_Output(new_w)->SetValues) (old, request, new_w, args, num_args))
756     {
757 	refresh_needed = True;
758     }
759 
760     /* FIX ME - lots more cases */
761     /*
762      * From include/Xm/TextP.h :
763      * XmTextSource source
764      * XtCallbackList activate_callback, focus_callback, losing_focus_callback,
765      *    value_changed_callback, modify_verify_callback,
766      *    wcs_modify_verify_callback, motion_verify_callback,
767      *    gain_primary_callback, lose_primary_callback
768      * Dimension margin_height, margin_width, cursor_position_x
769      * OutputCreateProc output_create
770      * InputCreateProc input_create;
771      *
772      * XmTextPosition top_character;
773      * XmTextPosition bottom_position;
774      * XmTextPosition cursor_position;
775      * int max_length;
776      * Boolean add_mode;
777      * Boolean traversed;
778      * Boolean highlight_changed;
779      * Boolean pendingoff;
780      * char char_size;
781      * OnOrOff on_or_off;
782      * Output output;
783      * Input input;
784      * XmTextPosition first_position;
785      * XmTextPosition last_position;
786      * XmTextPosition forget_past;
787      * XmTextPosition force_display;
788      * XmTextPosition new_top;
789      * XmTextPosition last_top_char;
790      * XmTextPosition dest_position;
791      * int disable_depth;
792      * int pending_scroll;
793      * int total_lines;
794      * int top_line;
795      * int vsbar_scrolling;
796      * Cardinal number_lines;
797      * Cardinal maximum_lines;
798      * Line line;
799      * Widget inner_widget;
800      * XmTextLineTable line_table;
801      * unsigned int table_size;
802      * unsigned int table_index;
803      */
804 
805     Text_InSetValues(nw) = False;
806     if ( refresh_needed ) /*CP: then we can "force" a complete RefigureLines call by: */
807 	Text_ForgetPast(nw) = 0;
808 
809     return refresh_needed;
810 }
811 
812 
813 static void
Realize(Widget aw,XtValueMask * value_mask,XSetWindowAttributes * attributes)814 Realize(Widget aw, XtValueMask *value_mask, XSetWindowAttributes *attributes)
815 {
816     XmTextWidget w = (XmTextWidget)aw;
817 
818     DEBUGOUT(_LtDebug(__FILE__, aw, "%s:Realize(%d) - valuemask 0x%X - %dx%d\n",
819     		__FILE__, __LINE__, *value_mask,
820     		XtWidth(aw), XtHeight(aw)));
821 
822 #define superclass (&xmPrimitiveClassRec)
823     (*superclass->core_class.realize) (aw, value_mask, attributes);
824 #undef superclass
825 
826     RefigureLines(w);
827 
828     (*Text_Output(w)->realize) (aw, value_mask, attributes);
829 
830     _XmTextSetEditable(aw, Text_Editable(w));
831 
832     XmTextShowPosition(aw, Text_CursorPos(w));
833 }
834 
835 
836 static void
DoExpose(Widget aw,XEvent * event,Region region)837 DoExpose(Widget aw, XEvent *event, Region region)
838 {
839     XmTextWidget w = (XmTextWidget)aw;
840 
841     if (XtWindow(aw) == 0)
842 	return;
843 
844     if (event == NULL)
845     {
846         XClearArea(XtDisplay(aw),XtWindow(aw),0,0,0,0,True);
847 	return;
848     }
849 
850     DEBUGOUT(_LtDebug(__FILE__, aw, "DoExpose\n"));
851     if (Text_DisableDepth(w) != 0)
852 	return;		/* Should we be doing this ? FIX ME */
853 
854     if (!XtIsRealized(w))
855     {
856 	return;
857     }
858 
859     if (Text_NeedsRefigureLines(w))
860     {
861 	RefigureLines(w);
862     }
863 
864     if ( Text_InExpose(w) )
865 	return;
866 
867     Text_InExpose(w)= True;
868 
869     (*Text_Output(w)->expose) (aw, event, region);
870     Text_InExpose(w)= False;
871 }
872 
873 
874 static void
Resize(Widget aw)875 Resize(Widget aw)
876 {
877     XmTextWidget w = (XmTextWidget)aw;
878 
879     DEBUGOUT(_LtDebug(__FILE__, aw, "%s:resize(%d) - %dx%d\n",
880     		__FILE__, __LINE__,
881     		XtWidth(aw), XtHeight(aw)));
882 
883     /* Resize can get called from XmScrolledWindowSetAreas before we actually
884      * made it through our initialize method.  Make sure not to die because
885      * of this
886      */
887     if (Text_Input(w) == NULL || Text_Output(w) == NULL)
888     {
889 	return;
890     }
891 
892     if ( Text_InResize( w ) )
893     	return;
894 
895     Text_ForgetPast(w) = 0; /*CP: so that we recalculate all lines again */
896     Text_InResize( w ) = True;
897 
898     (*Text_Output(w)->resize) (aw, True);
899 
900     Text_InResize( w ) = False;
901 
902     RefigureLines(w);
903 }
904 
905 
906 static XtGeometryResult
query_geometry(Widget w,XtWidgetGeometry * proposed,XtWidgetGeometry * answer)907 query_geometry(Widget w, XtWidgetGeometry *proposed, XtWidgetGeometry *answer)
908 {
909 #if 0
910     XmTextWidget tw = (XmTextWidget)w;
911     XtWidgetGeometry a;
912 
913 #define Wants(x)   (proposed->request_mode & x)
914     DEBUGOUT(_LtDebug(__FILE__, w,
915 		      "query_geometry proposed width=%d height=%d mode=%X\n",
916 		   proposed->width, proposed->height, proposed->request_mode));
917 
918     if (proposed->request_mode != 0)
919     {				/* NULL case should not yet end here ! */
920 	if ((!(Wants(CWWidth))) && (!Wants(CWHeight)))
921 	{
922 	    /* If they don't ask width/height, let them have what they like */
923 	    if (answer)
924 	    {
925 		*answer = *proposed;
926 	    }
927 
928 	    return XtGeometryYes;
929 	}
930     }
931 
932     a.request_mode = CWWidth | CWHeight;
933     a.width = XtWidth(tw);
934     a.height = XtHeight(tw);
935 
936     if (answer)
937     {
938 	*answer = a;
939     }
940 
941     /* NULL proposed -> return Width+Height */
942     if (proposed->request_mode == 0)
943     {
944 	return XtGeometryAlmost;
945     }
946 
947     if (proposed->width >= answer->width && proposed->height >= answer->height)
948     {
949 	return XtGeometryYes;
950     }
951     else if (answer->width == XtWidth(tw) && answer->height == XtHeight(tw))
952     {
953 	if (answer)
954 	{
955 	    answer->request_mode = 0;
956 	}
957 
958 	return XtGeometryNo;
959     }
960     else
961     {
962 	return XtGeometryAlmost;
963     }
964 #else
965     DEBUGOUT(_LtDebug(__FILE__, w,
966 		      "query_geometry proposed width=%d height=%d mode=%X\n",
967 		   proposed->width, proposed->height, proposed->request_mode));
968 
969     answer->width = XtWidth(w);
970     answer->height = XtHeight(w);
971 
972     return _XmGMReplyToQueryGeometry(w, proposed, answer);
973 #endif
974 }
975 
976 /* Drawing Routines ------------------------------------------------------- */
977 static void
Redisplay(XmTextWidget w)978 Redisplay(XmTextWidget w)
979 {
980     DEBUGOUT(_LtDebug(__FILE__, (Widget)w, "Redisplay\n"));
981 
982     if (Text_DisableDepth(w) != 0)
983 	return;
984 
985     if (!XtIsRealized((Widget)w))
986     {
987 	return;
988     }
989 
990     if ( Text_InRedisplay(w) )
991 	return;
992 
993     Text_InRedisplay(w) = True;
994 
995     Text_NeedsRedisplay(w) = False;
996 
997     if (Text_NeedsRefigureLines(w))
998     {
999 	RefigureLines(w);
1000     }
1001 
1002     _XmChangeVSB(w, Text_TopPos(w));
1003     {
1004     OutputData o = Text_OutputData(w);
1005 
1006     	_XmRedisplayHBar(w, Out_XOffset(o));
1007     }
1008 
1009     (*Text_Output(w)->expose) ((Widget)w, NULL, NULL);
1010     Text_InRedisplay(w) = False;
1011 }
1012 
1013 static Cardinal
GetSecResData(WidgetClass wc,XmSecondaryResourceData ** resdata)1014 GetSecResData(WidgetClass wc, XmSecondaryResourceData **resdata)
1015 {
1016     return 0;
1017 }
1018 
1019 
1020 /* Line Table Routines ---------------------------------------------------- */
1021 
1022 static void
LineIncrease(XmTextWidget w,LineNum num)1023 LineIncrease(XmTextWidget w, LineNum num)
1024 {
1025 	DEBUGOUT(_LtDebug(__FILE__, (Widget)w, "LineIncrease %d\n",num));
1026 	if (num > Text_LineMax(w)) {
1027 		LineNum start = Text_LineMax(w);
1028 		Cardinal i;
1029 
1030 		Text_Line(w) = (Line)XtRealloc((char *)Text_Line(w),
1031 				sizeof(LineRec) * num);
1032 		Text_LineMax(w) = num;
1033 
1034 		for (i = start; i < num; i++) {
1035 			Line line = &Text_Line(w)[i];
1036 			line->extra = NULL;
1037 		}
1038 	}
1039 }
1040 
1041 /*
1042  * Set up the entire line table, starting with the first visible position.
1043  *
1044  * Note that there is 1 extra line in the table.  This is so we can find
1045  * out what the last position in any line is by looking at the first
1046  * position of the next line.  Oh, the limitations of Motif compatibility!
1047  */
1048 /*
1049  * This new implementation of RefigureLines is necessary to implement
1050  * wrapping.
1051  * Inspection of the output of test/Xm/text/test6 reveals that Lines can
1052  * be built from the LineTable. As the LineTable has recently been reprogrammed
1053  * to contain wrapped lines, is seems logical to use that idea.
1054  * Some people will accuse me of NIH now :-)
1055  */
1056 static void
RefigureLines(XmTextWidget w)1057 RefigureLines(XmTextWidget w)
1058 {
1059     XmTextPosition pos, next;
1060     int nlines;
1061     Cardinal i;
1062     Line line = NULL;
1063     XmTextLineTable lte;
1064     LineTableExtra extra;
1065     Boolean more;
1066 
1067     DEBUGOUT(_LtDebug(__FILE__, (Widget)w, "RefigureLines\n"));
1068 /*
1069  * DisableDepth is meant to optimize frequent updates to XmText.
1070  * This probably means we shouldn't do anything here ...
1071  *
1072  * Not too sure about this. FIX ME.
1073  */
1074     if (Text_DisableDepth(w) != 0) {
1075 	Text_NeedsRefigureLines(w) = True;
1076 	return;
1077     }
1078 /* End unsure stuff */
1079 
1080     Text_NeedsRefigureLines(w) = False;
1081 
1082     /* Too verbose to stay on ... */
1083 #ifdef VERBOSE
1084     /* Show our input */
1085     for (i = 0;
1086 	 i < Text_TableSize(w) && (i == 0 ||
1087 				   Text_LineTable(w)[i].start_pos != 0);
1088 	 i++)
1089     {
1090 	DEBUGOUT(_LtDebug(__FILE__, (Widget)w,
1091 			  "RefigureLines: [%d] start_pos %d virt %d\n",
1092 			  i, Text_LineTable(w)[i].start_pos,
1093 			  Text_LineTable(w)[i].virt_line));
1094     }
1095 #endif
1096 
1097     pos = Text_TopPos(w);
1098     nlines = 0;
1099 
1100     /* Find line to start with */
1101     i = 0;
1102     lte = Text_LineTable(w);
1103 
1104     if (pos)
1105     {
1106 	for (i = 1, lte = Text_LineTable(w) + i;
1107 	     i < Text_TableSize(w) && lte->start_pos;
1108 	     i++, lte = Text_LineTable(w) + i)
1109 	{
1110 	    if (lte->start_pos >= pos)
1111 	    {
1112 		break;
1113 	    }
1114 	}
1115     }
1116 
1117     for (;
1118 	 i < Text_TableSize(w) && (lte->start_pos || i == 0);
1119 	 i++, lte = Text_LineTable(w) + i)
1120     {
1121 	if (nlines >= Text_LineMax(w))
1122 	{
1123 	    LineIncrease(w, nlines + 16);
1124 	}
1125 
1126 	line = &Text_Line(w)[nlines];
1127 
1128 	if (line->extra)
1129 	{
1130 	    XtFree((char *)line->extra);
1131 	}
1132 
1133 	extra = NULL;
1134 	more = (*Text_Output(w)->MeasureLine) ((XmTextWidget)w, nlines,
1135 					       pos, &next, &extra);
1136 
1137 	line->start = lte->start_pos;
1138 	line->changed = False;
1139 	line->changed_position = 0;
1140 	line->extra = extra;
1141 
1142 	pos = next;
1143 	nlines++;
1144     }
1145 
1146     Text_LineCount(w) = nlines;
1147     Text_TopLine(w) = _XmTextGetTableIndex(w, Text_TopPos(w));
1148 
1149     /* Not sure about this ...
1150      * Do we need to provide a line beyond the last real line in the text ?
1151      */
1152     if (nlines >= Text_LineMax(w))
1153     {
1154 	LineIncrease(w, nlines + 16);
1155     }
1156 
1157     line = &Text_Line(w)[nlines];
1158     if (line->extra)
1159     {
1160 	XtFree((char *)line->extra);
1161     }
1162 
1163     line->start = PASTENDPOS;	/* next wasn't good enough */
1164     line->changed = False;
1165     line->changed_position = 0;
1166     line->extra = NULL;
1167     /* End unsure part */
1168 
1169     if (Text_BottomPos(w) == 0)
1170     {
1171 	Text_BottomPos(w) = INT_MAX;
1172     }
1173 
1174     else
1175     {
1176 	Text_BottomPos(w) = line->start;
1177     }
1178 
1179     /* This is too verbose to stay on */
1180 #ifdef VERBOSE
1181     if (_LtDebugInDebug(__FILE__, (Widget)w))
1182     {
1183 	int i;
1184 
1185 	for (i = 0; i <= Text_LineCount(w); i++)
1186 	{
1187 	    Line line = &Text_Line(w)[i];
1188 
1189 	    if (line->extra)
1190 	    {
1191 		DEBUGOUT(_LtDebug(__FILE__, (Widget)w,
1192 				"RefigureLines: line[%d]: start=%d width=%d\n",
1193 				  i, line->start, line->extra->width));
1194 	    }
1195 	    else
1196 	    {
1197 		DEBUGOUT(_LtDebug(__FILE__, (Widget)w,
1198 				"RefigureLines: line[%d]: start=%d width=NA\n",
1199 				  i, line->start));
1200 	    }
1201 	}
1202     }
1203 
1204 #ifdef VERBOSE
1205     DEBUGOUT(_LtDebug(__FILE__, (Widget)w,
1206 		      "RefigureLines: top on line %d, bottompos %d\n",
1207 		      i, Text_BottomPos(w)));
1208 #endif
1209 #endif
1210 }
1211 
1212 /* Line-table functions (for the whole textstring)------------------------ */
1213 
1214 /* Running test/Xm/test6 (be sure to give it focus so something interesting
1215  * happens!) against Motif reveals that the line table is structured like this :
1216  *      - the size of its array (initially 64) is in table_size
1217  *      - table_index is NOT the highest used item; not sure what it's for
1218  *      - the array starts at the beginning of the text widget, not at the
1219  *        visible top. Therefore the first entry always contains 0,0.
1220  *      - the start_pos field obviously points to the first position of the line
1221  *      - the virt_line field is 1 if this is a line that's not really there in
1222  *        the text; it is however a line created by wrapping.
1223  *      - the final entry in the list has 0 start_pos.
1224  *
1225  * It also turns out that there's at least *three* places in the XmText
1226  *      record where stuff is stored for every line :
1227  *      - the text itself (in the source) as a normal string
1228  *      - an array of "Line"s
1229  *      - a LineTable
1230  */
1231 #define LINETABLE_INCREMENT	64
1232 
1233 
1234 /*
1235  * The block and update parameters are currently unused because I don't
1236  * know what they should be used for.
1237  */
1238 extern void
_XmTextUpdateLineTable(Widget w,XmTextPosition start,XmTextPosition end,XmTextBlock block,Boolean update)1239 _XmTextUpdateLineTable(Widget w,
1240 		       XmTextPosition start,
1241 		       XmTextPosition end,
1242 		       XmTextBlock block,
1243 		       Boolean update)
1244 {
1245 	Cardinal	i;
1246 	XmTextWidget	tw = (XmTextWidget)w;
1247 	XmTextPosition	next, ostart;
1248 	XmTextLineTable line;
1249 	unsigned int	index;
1250 	Boolean		wrap = _XmTextShouldWordWrap(tw), next_is_virtual;
1251 
1252     DEBUGOUT(_LtDebug(__FILE__, w, "_XmTextUpdateLineTable start %d end %d\n",
1253     		start, end));
1254     Text_NeedsRefigureLines(w) = True;
1255     Text_NeedsRedisplay(w) = True;
1256 
1257     /* This is a hack. Xinvest becomes happier */
1258     if (start == 0 && end == 0) {
1259 	/* We must initialize the whole line table; let's make sure it ends
1260 	 * with zeroes.
1261 	 */
1262 	for (index=0; index < Text_TableSize(tw); index++) {
1263 		Text_LineTable(tw)[index].start_pos = 0;
1264 		Text_LineTable(tw)[index].virt_line = False;
1265 	}
1266     }
1267 
1268     /* Initialize ourselves */
1269     if (start == 0)
1270     {
1271 	index = 0;
1272     }
1273     else
1274     {
1275 	index = _XmTextGetTableIndex(tw, start);
1276 	start = Text_LineTable(tw)[index].start_pos;
1277     }
1278 
1279     end = Text_LastPos(w);
1280 
1281     DEBUGOUT(_LtDebug(__FILE__, (Widget)w,
1282 		      "_XmTextUpdateLineTable(start %d end %d update %s) %s\n",
1283 		      start, end, _LtDebugBoolean2String(update),
1284 		      wrap ? "wrap" : ""));
1285 
1286 /* rws 10 Feb 1999
1287    text/test14, grok phone database, note field.
1288    I suspect that this should be done in TextOut.c not here, and somehow
1289    this thing should be able to shrink to some sort of minimum size as the
1290    text gets smaller.
1291  */
1292 /*CP:19 May 1999: The difference with GROK and other scrollable
1293    XmText widgets is that the scrollable window is created first and then
1294    the XmText widget is created (i.e. it does not use the convenience
1295    function XmCreateScrolledText ). When this happens then XmText
1296    does not have the XmScrolledWindow as it's parent and therefor
1297    all lines in the XmText must be drawn hence the need to increase
1298    the lines and column count of the output window.
1299    This way of creating scrollable XmText windows is not efficient!
1300    As Rick above states, I am also not sure that this should not be in
1301    TextOut.c.
1302 */
1303     if(!XmIsScrolledWindow(XtParent(w)))
1304         {
1305         int max_lines = 1;
1306         int max_cols = 0;
1307         int col = 0;
1308         int index;
1309         String value = XmTextGetString(w);
1310         OutputData od = Text_OutputData(w);
1311         Arg args[2];
1312         int n,len;
1313 
1314         len=Text_LastPos(w);
1315     	for (index = 0; index < len; index++)
1316     	{
1317     		switch (value[index])
1318     		{
1319     		case '\n':
1320     			max_lines++;
1321     			col = 0;
1322     			break;
1323     		default:
1324     			col++;
1325     			break;
1326     		}
1327 		if (col > max_cols)
1328 		{
1329 		    max_cols = col;
1330 		}
1331     	}
1332 	max_cols = max_cols < Out_ColumnsSet(od) ? Out_ColumnsSet(od) : max_cols;
1333 	max_lines = max_lines < Out_RowsSet(od) ? Out_RowsSet(od) : max_lines;
1334 
1335 	DEBUGOUT(_LtDebug(__FILE__, (Widget)w,
1336 		      "_XmTextUpdateLineTable - %d %d %d %d\n",
1337 		      max_lines, max_cols, Out_Rows(od), Out_Columns(od)));
1338     	XtFree(value);
1339     	n = 0;
1340     	if (!wrap && !Out_ScrollHorizontal(od) && max_cols != Out_Columns(od))
1341     	{
1342 	    XtSetArg(args[n], XmNcolumns, max_cols); n++;
1343     	}
1344     	if (!Out_ScrollVertical(od) && max_lines != Out_Rows(od))
1345     	{
1346 	    XtSetArg(args[n], XmNrows, max_lines); n++;
1347     	}
1348     	if (n > 0)
1349     	{
1350 	    XtSetValues(w, args, n);
1351     	}
1352     }
1353 
1354     if (wrap)
1355     {
1356 	/*
1357 	 * Word-wrapping is on.
1358 	 */
1359 	while (end >= start)
1360 	{
1361 	    if (index >= Text_TableSize(w))
1362 	    {
1363 		i = Text_TableSize(w);
1364 
1365 #if 0
1366 		Text_TableSize(w) += LINETABLE_INCREMENT;
1367 #else
1368 		if (Text_TableSize(w) <= LINETABLE_INCREMENT)
1369 			Text_TableSize(w) = 2 * LINETABLE_INCREMENT;
1370 		else
1371 			Text_TableSize(w) *= 2;
1372 #endif
1373 		Text_LineTable(w) = (XmTextLineTable)
1374 		    XtRealloc((char *)Text_LineTable(w),
1375 			      sizeof(XmTextLineTableRec) * Text_TableSize(w));
1376 
1377 		for (; i < Text_TableSize(w); i++)
1378 		{
1379 		    Text_LineTable(w)[i].start_pos = 0;
1380 		    Text_LineTable(w)[i].virt_line = False;
1381 		}
1382 	    }
1383 
1384 	    /*
1385 	     * So we have ourselves a line of text. We may have to split it up
1386 	     * visually, wrapping around at word boundaries.
1387 	     *
1388 	     * This first line is never a virtual one. If we pass through this
1389 	     * inner loop a second time (or more), then those lines are
1390 	     * virtual ones.
1391 	     */
1392 	    next_is_virtual = False;
1393 	    if (start < 0)
1394 	    {
1395 		start = 0;
1396 		break;
1397 	    }
1398 	    else
1399 	    {
1400 		do
1401 		{
1402 		    ostart = start;
1403 
1404 		    /* FIX ME : need to fill up extra ? */
1405 		    next = _XmTextFindLineEnd(tw, start, NULL);
1406 
1407 		    line = Text_LineTable(w) + index;
1408 		    line->start_pos = start;
1409 		    line->virt_line = next_is_virtual;
1410 
1411 		    DEBUGOUT(_LtDebug(__FILE__, (Widget)w,
1412 		       "_XmTextUpdateLineTable: line %d start %d virtual %d\n",
1413 				      index, line->start_pos, line->virt_line));
1414 
1415 		    next_is_virtual = True;	/* See comment above */
1416 
1417 		    start = next + 1;
1418 		    index++;
1419 		}
1420 		while (next != PASTENDPOS && next > ostart &&
1421 		       index < Text_TableSize(w));
1422 	    }
1423 	}
1424     }
1425     else
1426     {
1427 	/*
1428 	 * No word-wrapping.
1429 	 */
1430 	while (end >= start)
1431 	{
1432 	    if (index >= Text_TableSize(w))
1433 	    {
1434 		Cardinal i = Text_TableSize(w);
1435 
1436 #if 0
1437 		Text_TableSize(w) += LINETABLE_INCREMENT;
1438 #else
1439 		if (Text_TableSize(w) <= LINETABLE_INCREMENT)
1440 			Text_TableSize(w) = 2 * LINETABLE_INCREMENT;
1441 		else
1442 			Text_TableSize(w) *= 2;
1443 #endif
1444 		Text_LineTable(w) = (XmTextLineTable)
1445 		    XtRealloc((char *)Text_LineTable(w),
1446 			      sizeof(XmTextLineTableRec) * Text_TableSize(w));
1447 
1448 		for (; i < Text_TableSize(w); i++)
1449 		{
1450 		    Text_LineTable(w)[i].start_pos = 0;
1451 		    Text_LineTable(w)[i].virt_line = False;
1452 		}
1453 	    }
1454 
1455 	    line = Text_LineTable(w) + index;
1456 	    line->start_pos = start;
1457 	    line->virt_line = False;
1458 
1459 	    DEBUGOUT(_LtDebug(__FILE__, (Widget)w,
1460 		       "_XmTextUpdateLineTable nowrap : line %d start %d virtual %d\n",
1461 				      index, line->start_pos, line->virt_line));
1462 
1463 	    /* Be careful not to do PASTENDPOS + 1 */
1464 	    start = (*Text_Source(w)->Scan) (Text_Source(w), start,
1465 					  XmSELECT_LINE, XmsdRight, 1, False);
1466 
1467 	    if (start == PASTENDPOS)
1468 	    {
1469 		break;		/* terminate loop */
1470 	    }
1471 	    else
1472 	    {
1473 		start++;
1474 	    }
1475 
1476 	    index++;
1477 	}
1478     }
1479 
1480     /*
1481      * All done. Store some stuff in the widget.
1482      */
1483     Text_TotalLines(w) = index;
1484     for (i=index; i<Text_TableSize(w); i++) {
1485 	Text_LineTable(w)[i].start_pos = 0;
1486 	Text_LineTable(w)[i].virt_line = False;
1487     }
1488 }
1489 
1490 /*
1491  * This function is the *initialize* variant of the one above.
1492  */
1493 static void
InitializeLineTable(XmTextWidget w)1494 InitializeLineTable(XmTextWidget w)
1495 {
1496     int i;
1497 
1498     /* Allocate initial amount */
1499     Text_LineTable(w) = (XmTextLineTable)XtMalloc(sizeof(XmTextLineTableRec)
1500 						  * LINETABLE_INCREMENT);
1501 
1502     Text_TotalLines(w) = 0;
1503     Text_TableSize(w) = LINETABLE_INCREMENT;
1504 
1505     for (i = 0; i < LINETABLE_INCREMENT; i++)
1506     {
1507 	Text_LineTable(w)[i].start_pos = 0;
1508 	Text_LineTable(w)[i].virt_line = False;
1509     }
1510 
1511     _XmTextUpdateLineTable((Widget)w, 0, 0, NULL, False);
1512 }
1513 
1514 /* Not needed beyond this */
1515 #undef LINETABLE_INCREMENT
1516 
1517 extern unsigned int
_XmTextGetTableIndex(XmTextWidget w,XmTextPosition pos)1518 _XmTextGetTableIndex(XmTextWidget w, XmTextPosition pos)
1519 {
1520     XmTextLineTable current = Text_LineTable(w) + Text_TotalLines(w) - 1;
1521     unsigned int i = Text_TotalLines(w) - 1;
1522 
1523     if (pos < 0)
1524     {
1525 	return 0;
1526     }
1527 
1528     if (Text_LineTable(w) == NULL)
1529     {
1530 	return 0;
1531     }
1532 
1533     for (; current->start_pos > pos; current--, i--);
1534 
1535 #ifdef VERBOSE
1536     DEBUGOUT(_LtDebug(__FILE__, (Widget)w,
1537 		      "XmTextGetTableIndex Pos %d Index %d\n", pos, i));
1538 #endif
1539 
1540     return i;
1541 }
1542 
1543 /* Quasi-Public Functions ------------------------------------------------ */
1544 extern void
_XmTextLineInfo(XmTextWidget w,LineNum line,XmTextPosition * startpos,LineTableExtra * extra)1545 _XmTextLineInfo(XmTextWidget w, LineNum line,
1546 		XmTextPosition *startpos, LineTableExtra *extra)
1547 {
1548     *startpos = Text_Line(w)[line].start;
1549     *extra = Text_Line(w)[line].extra;
1550 }
1551 
1552 extern void
_XmTextMarkRedraw(XmTextWidget w,XmTextPosition left,XmTextPosition right)1553 _XmTextMarkRedraw(XmTextWidget w, XmTextPosition left,
1554 		  XmTextPosition right)
1555 {
1556 }
1557 
1558 extern LineNum
_XmTextPosToLine(XmTextWidget w,XmTextPosition position)1559 _XmTextPosToLine(XmTextWidget w, XmTextPosition position)
1560 {
1561     if (position < 1)
1562 	return 0;
1563     else if (position > Text_LastPos(w))
1564 	return NOLINE;
1565     else
1566 	return _XmTextGetTableIndex(w, position) + 1;
1567 }
1568 
1569 /*
1570  * As far as I can see, this function needs to :
1571  *	- insert text
1572  *	- update the cursor position (done inside TextStrSo->Replace)
1573  *	- call XmNvalueChangedCallback (done inside TextStrSo->Replace)
1574  *	- call XmNmodifyVerifyCallback (and Wcs)	( ?? )
1575  */
1576 static void
_XmTextInsert(Widget w,XmTextPosition position,char * string,XEvent * evp)1577 _XmTextInsert(Widget w, XmTextPosition position, char *string, XEvent *evp)
1578 {
1579     XmTextStatus st;
1580     XmTextWidget tw = (XmTextWidget)w;
1581     XmTextBlockRec block;
1582     XmTextPosition startret, endret;
1583 
1584     DEBUGOUT(_LtDebug(__FILE__, w, "_XmTextInsert\n"));
1585 
1586     if (XtIsSubclass(w, xmTextFieldWidgetClass))
1587     {
1588 	XmTextFieldInsert(w, position, string);
1589 	return;
1590     }
1591 
1592     if (string == NULL)
1593     {
1594 	return;			/* Can I do this ? FIX ME */
1595     }
1596 
1597     if (!Text_Source(w))
1598     {
1599 	_XmWarning(w, "_XmTextInsert: no source\n");
1600 
1601 	return;
1602     }
1603 
1604     block.ptr = string;
1605     block.length = strlen(string);
1606     block.format = XmFMT_8_BIT;
1607     if ( position > Text_LastPos(w) )
1608 	position = Text_LastPos(w) ;
1609     startret = position;
1610     endret = position;
1611 
1612     st = (*Text_Source(w)->Replace) (tw, evp, &startret, &endret,
1613 				     &block, True);
1614     /* FIX ME ?? */
1615 
1616     RefigureLines(tw);
1617 
1618     if (XtIsRealized(w))
1619     {
1620 	Redisplay(tw);
1621     }
1622 }
1623 
1624 
1625 extern void
_XmTextSetCursorPosition(Widget w,XmTextPosition position)1626 _XmTextSetCursorPosition(Widget w, XmTextPosition position)
1627 {
1628     XmTextWidget tw = (XmTextWidget)w;
1629     XmTextVerifyCallbackStruct cbs;
1630     cbs.doit = True;
1631     cbs.newInsert = position;
1632 
1633     DEBUGOUT(_LtDebug(__FILE__, (Widget)w,
1634 		      "_XmTextSetCursorPosition Pos %d \n",
1635 		      position));
1636 
1637     if (position > Text_LastPos(w))
1638     {
1639 	position = Text_LastPos(w);
1640     }
1641 
1642     if (Text_CursorPos(w) != position)
1643     {
1644 	if (Text_MotionVerifyCallback(w))
1645 	{
1646 	    cbs.reason = XmCR_MOVING_INSERT_CURSOR;
1647 	    cbs.event = NULL;
1648 	    cbs.currInsert = Text_CursorPos(w);
1649 	    cbs.startPos = cbs.endPos = 0;
1650 	    cbs.text = NULL;
1651 
1652 	    XtCallCallbacks(w, XmNmotionVerifyCallback, &cbs);
1653 	}
1654     }
1655 
1656     if (cbs.doit)
1657     {
1658 #ifdef VERBOSE
1659 	DEBUGOUT(_LtDebug(__FILE__, (Widget)w,
1660 			  "Text_CursorPos before draw: %08x\n",
1661 			  Text_CursorPos(w)));
1662 #endif
1663 
1664 	(*Text_Output(w)->DrawInsertionPoint) (tw, Text_CursorPos(w), off);
1665 
1666 #if 0
1667 	/* rws 10 Mar 2000
1668 	   This sucks, but text/test16 sub-test 5 proves this
1669 	 */
1670 	Text_CursorPos(w) = cbs.newInsert;
1671 #else
1672 	Text_CursorPos(w) = position;
1673 #endif
1674 
1675 #ifdef VERBOSE
1676 	DEBUGOUT(_LtDebug(__FILE__, (Widget)w,
1677 			  "Text_CursorPos after draw: %08x\n",
1678 			  Text_CursorPos(w)));
1679 #endif
1680 
1681 	if (Text_AutoShowCursorPosition(w))
1682 	{
1683 	    /* Don't do this before being realized, it'll misplace the text
1684 	     *	(based on premature widget size).
1685 	     *	Fixes xmcd. Danny 25/8/1997 */
1686 	    if (XtIsRealized(w))
1687 		XmTextShowPosition(w, Text_CursorPos(w));
1688 	}
1689 	else
1690 	{
1691 	    _XmTextMovingCursorPosition(tw, Text_CursorPos(w));
1692 	}
1693 
1694 	(*Text_Output(w)->DrawInsertionPoint) (tw, Text_CursorPos(w), on);
1695     }
1696     (void)_XmImSendSpot(w);
1697 }
1698 
1699 
1700 static void
_XmTextSetEditable(Widget w,Boolean e)1701 _XmTextSetEditable(Widget w, Boolean e)
1702 {
1703     DEBUGOUT(_LtDebug(__FILE__, w, "_XmTextSetEditable()\n"));
1704 
1705     if (!XtIsRealized(w))
1706     {
1707 	return;
1708     }
1709 
1710     if (e)
1711     {				/* becomes editable */
1712 	Arg args[10];
1713 	int nargs;
1714 
1715 	XmImRegister(w, 0);
1716 
1717 	nargs = 0;
1718 	XtSetArg(args[nargs], XmNbackground, XtBackground(w)); nargs++;
1719 	XtSetArg(args[nargs], XmNforeground, Prim_Foreground(w)); nargs++;
1720 	XmImSetValues(w, args, nargs);
1721     }
1722     else
1723     {				/* Becomes un-editable */
1724 	XmImUnregister(w);
1725     }
1726 
1727     _XmStringSourceSetEditable(Text_Source(w), e);
1728 }
1729 
1730 
1731 extern void
_XmTextDisableRedisplay(XmTextWidget w,Boolean losesbackingstore)1732 _XmTextDisableRedisplay(XmTextWidget w, Boolean losesbackingstore)
1733 {
1734     Text_DisableDepth(w)++;
1735 }
1736 
1737 
1738 extern void
_XmTextEnableRedisplay(XmTextWidget w)1739 _XmTextEnableRedisplay(XmTextWidget w)
1740 {
1741     if (Text_DisableDepth(w) > 0)
1742     {
1743 	Text_DisableDepth(w)--;
1744 	if (Text_DisableDepth(w) == 0)
1745 	{
1746 	    if (Text_NeedsRedisplay(w))
1747 	    {
1748 		Redisplay(w);
1749 	    }
1750 	}
1751     }
1752 }
1753 
1754 
1755 /*
1756  * What on earth does this do ???
1757  */
1758 extern void
_XmTextInvalidate(XmTextWidget w,XmTextPosition position,XmTextPosition topos,long delta)1759 _XmTextInvalidate(XmTextWidget w, XmTextPosition position,
1760 		  XmTextPosition topos, long delta)
1761 {
1762     Cardinal i;
1763 
1764     for (i = 0;
1765 	 i < Text_LineCount(w) && Text_Line(w)[i].start <= position;
1766 	 i++);
1767 
1768     if (i >= Text_LineCount(w))
1769     {
1770 	return;
1771     }
1772 
1773     if (i==0)
1774     {
1775        /* This fixes SF [Bug #124809] */
1776        Text_Line(w)[0].changed = True;
1777        Text_Line(w)[0].changed_position = position;
1778     }
1779     else
1780     {
1781        Text_Line(w)[i - 1].changed = True;
1782        Text_Line(w)[i - 1].changed_position = position;
1783     }
1784 
1785     (*Text_Output(w)->Invalidate) (w, position, topos, delta);
1786     (*Text_Input(w)->Invalidate) (w, position, topos, delta);
1787 }
1788 
1789 
1790 /* Public Functions ------------------------------------------------------ */
1791 
1792 extern Widget
XmCreateText(Widget parent,char * name,Arg * arglist,Cardinal argCount)1793 XmCreateText(Widget parent, char *name, Arg *arglist, Cardinal argCount)
1794 {
1795     return XtCreateWidget(name, xmTextWidgetClass, parent, arglist, argCount);
1796 }
1797 
1798 
1799 extern Widget
XmCreateScrolledText(Widget parent,char * name,Arg * arglist,Cardinal argcount)1800 XmCreateScrolledText(Widget parent, char *name, Arg *arglist, Cardinal argcount)
1801 {
1802     Widget sw, w;
1803     char *sname;
1804     Cardinal i;
1805     Arg *al;
1806 
1807     if (name == NULL)
1808     {
1809 	name = "";
1810     }
1811 
1812     sname = XtMalloc(strlen(name) + 3);
1813     strcpy(sname, name);
1814     strcat(sname, "SW");
1815 
1816     al = (Arg *)XtCalloc(argcount + 4, sizeof(Arg));
1817     for (i = 0; i < argcount; i++)
1818     {
1819 	al[i].name = arglist[i].name;
1820 	al[i].value = arglist[i].value;
1821     }
1822 
1823     XtSetArg(al[i], XmNscrollingPolicy, XmAPPLICATION_DEFINED); i++;
1824     XtSetArg(al[i], XmNvisualPolicy, XmVARIABLE); i++;
1825     XtSetArg(al[i], XmNscrollBarDisplayPolicy, XmSTATIC); i++;
1826     XtSetArg(al[i], XmNshadowThickness, 0); i++;
1827 
1828     sw = XtCreateManagedWidget(sname, xmScrolledWindowWidgetClass, parent,
1829 			       al, i);
1830     XtFree((char *)sname);
1831 
1832     i = argcount;
1833     XtSetArg(al[i], XmNeditMode, XmMULTI_LINE_EDIT); i++;
1834 
1835     w = XtCreateManagedWidget(name, xmTextWidgetClass, sw, al, i);
1836     XtAddCallback(w, XmNdestroyCallback,
1837 		  _XmDestroyParentCallback,
1838 		  (XtPointer)w);
1839 
1840     XtFree((char *)al);
1841 
1842     return w;
1843 }
1844 
1845 
1846 extern void
XmTextClearSelection(Widget w,Time time)1847 XmTextClearSelection(Widget w, Time time)
1848 {
1849     Boolean sel;
1850     XmTextPosition left, right;
1851 
1852     if (XtIsSubclass(w, xmTextWidgetClass))
1853     {
1854 	sel = (*Text_Source(w)->GetSelection) (Text_Source(w), &left, &right);
1855 	if (sel)
1856 	{
1857           /* SG 22/08/1998 this is wrong, it should deselect the text
1858              for this widget only, not effecting the primary or selection
1859              properties (according to O'Reilly), it certainly shouldn't
1860              delete any text.
1861 		_XmTextDelete((XmTextWidget)w, NULL, left, right);
1862              give this a go instead,based on the same thing in XmTextField,
1863              however there is a complication, this clears the selection for
1864              all XmText widgets sharing this source - is this right ??? */
1865 	    (*Text_Source(w)->SetSelection) (Text_Source(w), -1, -1, time);
1866 	}
1867         return;
1868     }
1869     else if (XtIsSubclass(w, xmTextFieldWidgetClass))
1870     {
1871 	XmTextFieldClearSelection(w, time);
1872 	return;
1873     }
1874 
1875     _XmWarning(w, "XmTextClearSelection: widget has invalid class");
1876 
1877 }
1878 
1879 
1880 extern Boolean
XmTextCopy(Widget w,Time time)1881 XmTextCopy(Widget w, Time time)
1882 {
1883     Display		*dpy;
1884     Window		win;
1885     int			r;
1886     long		item_id;
1887     XmString		lb = NULL;
1888     Boolean		sel;
1889     XmTextPosition	left, right;
1890     XmTextBlockRec	block;
1891 
1892     if (XtIsSubclass(w, xmTextFieldWidgetClass))
1893         return XmTextFieldCopy(w,time);
1894     else if (!XmIsText(w))
1895     {
1896 	_XmWarning(w, "XmTextCopy: widget has invalid class");
1897 	return False;
1898     }
1899 
1900     if (w == NULL || XtWindow(w) == None)
1901 	return False;
1902 
1903     dpy = XtDisplay(w);
1904     win = XtWindow(w);
1905 
1906     sel = (*Text_Source(w)->GetSelection) (Text_Source(w), &left, &right);
1907     if (!sel)
1908 	return False;
1909 
1910     (*Text_Source(w)->ReadSource) (Text_Source(w), left, right, &block);
1911 
1912     lb = XmStringCreateLocalized("XmText");
1913 
1914     while ((r = XmClipboardStartCopy(dpy, win, lb, time,
1915 		NULL, NULL, &item_id)) == XmClipboardLocked)
1916 	;
1917 
1918     XmStringFree(lb);
1919     if (r != XmClipboardSuccess) {
1920 	XtFree(block.ptr);
1921 	return False;
1922     }
1923 
1924     while ((r = XmClipboardCopy(dpy, win, item_id, "STRING",
1925 		block.ptr, right - left + 1,
1926 		0, NULL)) == XmClipboardLocked)
1927 	;
1928 
1929     XtFree(block.ptr);
1930 
1931     if (r != XmClipboardSuccess) {
1932 	(void) XmClipboardEndCopy(dpy, win, item_id);
1933 	return False;
1934     }
1935 
1936     while ((r = XmClipboardEndCopy(dpy, win, item_id)) == XmClipboardLocked)
1937 	;
1938 
1939     if (r == XmClipboardSuccess)
1940 	return True;
1941     else
1942 	return False;
1943 }
1944 
1945 
1946 extern Boolean
XmTextCut(Widget w,Time time)1947 XmTextCut(Widget w, Time time)
1948 {
1949     Boolean		sel, r = False;
1950     XmTextPosition	left, right;
1951 
1952     if (XtIsSubclass(w, xmTextFieldWidgetClass))
1953         return XmTextFieldCut(w,time);
1954     else if (!XmIsText(w))
1955     {
1956 	_XmWarning(w, "XmTextCut: widget has invalid class");
1957 	return False;
1958     }
1959 
1960     if ((r = XmTextCopy(w, time)) == False)
1961         return False;
1962 
1963     sel = (*Text_Source(w)->GetSelection) (Text_Source(w), &left, &right);
1964 
1965     if (!sel || !Text_Editable(w))
1966 	return False;
1967 
1968     /* Now also remove the string from the buffer. */
1969     _XmTextDelete((XmTextWidget)w, NULL, left, right);
1970 
1971     return r;
1972 }
1973 
1974 
1975 extern Boolean
XmTextFindString(Widget w,XmTextPosition start,char * string,XmTextDirection direction,XmTextPosition * position)1976 XmTextFindString(Widget w, XmTextPosition start, char *string,
1977 		 XmTextDirection direction, XmTextPosition *position)
1978 {
1979     char *buf, *str;
1980     int len, i;
1981 
1982     len = XmTextGetLastPosition(w);
1983     if ((start < 0) || (start > len))
1984     {
1985 	return False;
1986     }
1987 
1988     buf = XmTextGetString(w);
1989 
1990     if (direction == XmTEXT_FORWARD) {
1991 	str = strstr(&buf[start], string);
1992     } else if (direction == XmTEXT_BACKWARD) {
1993 	i = start;
1994 	str = NULL;
1995 	len = strlen(string);
1996 	while (i) {
1997 		if (! strncmp(&buf[i], string, len)) {
1998 			str = &buf[i];
1999 			break;
2000 		}
2001 		i--;
2002 	}
2003     } else {
2004 	str = NULL;
2005     }
2006 
2007     if (str == (char *)NULL)
2008     {
2009 	XtFree(buf);
2010 	return False;
2011     }
2012 
2013     *str = 0;
2014     *position = (XmTextPosition)(str-buf);
2015     XtFree(buf);
2016     return True;
2017 }
2018 
2019 
2020 /*
2021  * Returns an integer value that indicates the y position of the first baseline
2022  * in the Text widget. The calculation takes into account the margin height,
2023  * shadow thickness, highlight thickness, and font ascent of the first font in the
2024  * fontlist. In this calculation the x position of the top of the widget is 0.
2025  */
2026 extern int
XmTextGetBaseline(Widget w)2027 XmTextGetBaseline(Widget w)
2028 {
2029 	/*
2030 	 * TextField does this :
2031 	 *	Prim_ShadowThickness(w) + Prim_HighlightThickness(w) +
2032 	 *		TextF_MarginHeight(w) + TextF_FontAscent(w)
2033 	 */
2034 
2035 	if (XtIsSubclass(w, xmTextWidgetClass)) {
2036 		return Prim_ShadowThickness(w) + Prim_HighlightThickness(w) +
2037 			Text_MarginHeight(w) + Out_Font_Ascent(Text_OutputData(w));
2038 	} else if (XtIsSubclass(w, xmTextFieldWidgetClass)) {
2039 		return XmTextFieldGetBaseline(w);
2040 	}
2041 
2042 	_XmWarning(w, "XmTextGetBaseline: widget has invalid class");
2043 	return 0;
2044 }
2045 
2046 
2047 extern XmTextPosition
XmTextGetCursorPosition(Widget w)2048 XmTextGetCursorPosition(Widget w)
2049 {
2050     if (XtIsSubclass(w, xmTextWidgetClass))
2051     {
2052 	return Text_CursorPos(w);
2053     }
2054     else if (XtIsSubclass(w, xmTextFieldWidgetClass))
2055     {
2056 	return XmTextFieldGetCursorPosition(w);
2057     }
2058 
2059     _XmWarning(w, "XmTextGetCursorPosition: widget has invalid class");
2060 
2061     return 0;
2062 }
2063 
2064 
2065 extern Boolean
XmTextGetEditable(Widget w)2066 XmTextGetEditable(Widget w)
2067 {
2068     if (XtIsSubclass(w, xmTextWidgetClass))
2069     {
2070 	return Text_Editable(w);
2071     }
2072     else if (XtIsSubclass(w, xmTextFieldWidgetClass))
2073     {
2074 	return XmTextFieldGetEditable(w);
2075     }
2076 
2077     _XmWarning(w, "XmTextGetEditable: widget has invalid class");
2078 
2079     return 0;
2080 }
2081 
2082 
2083 extern XmTextPosition
XmTextGetInsertionPosition(Widget w)2084 XmTextGetInsertionPosition(Widget w)
2085 {
2086     if (XtIsSubclass(w, xmTextWidgetClass))
2087     {
2088 	return Text_CursorPos(w);
2089     }
2090     else if (XtIsSubclass(w, xmTextFieldWidgetClass))
2091     {
2092 	return XmTextFieldGetInsertionPosition(w);
2093     }
2094 
2095     _XmWarning(w, "XmTextGetInsertionPosition: widget has invalid class");
2096 
2097     return 0;
2098 }
2099 
2100 
2101 extern XmTextPosition
XmTextGetLastPosition(Widget w)2102 XmTextGetLastPosition(Widget w)
2103 {
2104     if (XtIsSubclass(w, xmTextWidgetClass))
2105     {
2106 	return Text_LastPos(w);
2107     }
2108     else if (XtIsSubclass(w, xmTextFieldWidgetClass))
2109     {
2110 	return XmTextFieldGetLastPosition(w);
2111     }
2112 
2113     _XmWarning(w, "XmTextGetLastPosition: widget has invalid class");
2114 
2115     return 0;
2116 }
2117 
2118 
2119 extern int
XmTextGetMaxLength(Widget w)2120 XmTextGetMaxLength(Widget w)
2121 {
2122     if (XtIsSubclass(w, xmTextWidgetClass))
2123     {
2124 	return _XmStringSourceGetMaxLength(Text_Source(w));
2125     }
2126     else if (XtIsSubclass(w, xmTextFieldWidgetClass))
2127     {
2128 	return XmTextFieldGetMaxLength(w);
2129     }
2130 
2131     _XmWarning(w, "XmTextGetMaxLength: widget has invalid class");
2132 
2133     return 0;
2134 }
2135 
2136 
2137 extern char *
XmTextGetSelection(Widget w)2138 XmTextGetSelection(Widget w)
2139 {
2140     Boolean sel;
2141     XmTextPosition left, right;
2142     XmTextBlockRec block;
2143 
2144     if (XtIsSubclass(w, xmTextWidgetClass))
2145     {
2146 	sel = (*Text_Source(w)->GetSelection) (Text_Source(w), &left, &right);
2147 	if (!sel)
2148 	{
2149 	    return NULL;
2150 	}
2151 
2152 	(*Text_Source(w)->ReadSource) (Text_Source(w), left, right, &block);
2153 
2154 	return block.ptr;	/* Caller must free */
2155     }
2156     else if (XtIsSubclass(w, xmTextFieldWidgetClass))
2157     {
2158 	return XmTextFieldGetSelection(w);
2159     }
2160 
2161     _XmWarning(w, "XmTextGetSelection: widget has invalid class");
2162 
2163     return NULL;
2164 }
2165 
2166 
2167 extern Boolean
XmTextGetSelectionPosition(Widget w,XmTextPosition * left,XmTextPosition * right)2168 XmTextGetSelectionPosition(Widget w, XmTextPosition *left, XmTextPosition *right)
2169 {
2170     if (XtIsSubclass(w, xmTextWidgetClass))
2171     {
2172 	return (*Text_Source(w)->GetSelection) (Text_Source(w), left, right);
2173     }
2174     else if (XtIsSubclass(w, xmTextFieldWidgetClass))
2175     {
2176 	return XmTextFieldGetSelectionPosition(w, left, right);
2177     }
2178 
2179     _XmWarning(w, "XmTextGetSelectionPosition: widget has invalid class");
2180 
2181     return False;
2182 }
2183 
2184 
2185 extern wchar_t *
XmTextGetSelectionWcs(Widget w)2186 XmTextGetSelectionWcs(Widget w)
2187 {
2188     if (XtIsSubclass(w, xmTextWidgetClass))
2189     {
2190 	_XmWarning(w, "XmTextGetSelectionWcs: not implemented");
2191 	return NULL;		/* FIX ME */
2192     }
2193     else if (XtIsSubclass(w, xmTextFieldWidgetClass))
2194     {
2195 	return XmTextFieldGetSelectionWcs(w);
2196     }
2197 
2198     _XmWarning(w, "XmTextGetSelectionWcs: widget has invalid class");
2199 
2200     return NULL;
2201 }
2202 
2203 
2204 extern char *
XmTextGetString(Widget w)2205 XmTextGetString(Widget w)
2206 {
2207     if (XmIsText(w))
2208     {
2209 	return _XmStringSourceGetValue(Text_Source(w), False);
2210     }
2211     else if (XmIsTextField(w))
2212     {
2213 	return XmTextFieldGetString(w);
2214     }
2215 
2216     _XmWarning(w, "XmTextGetString: widget has invalid class");
2217 
2218     return NULL;
2219 }
2220 
2221 
2222 extern wchar_t *
XmTextGetStringWcs(Widget w)2223 XmTextGetStringWcs(Widget w)
2224 {
2225     if (XmIsText(w))
2226     {
2227 	return (wchar_t *)_XmStringSourceGetValue(Text_Source(w), True);
2228     }
2229     else if (XmIsTextField(w))
2230     {
2231 	return XmTextFieldGetStringWcs(w);
2232     }
2233 
2234     _XmWarning(w, "XmTextGetStringWcs: widget has invalid class");
2235 
2236     return NULL;
2237 }
2238 
2239 
2240 extern Boolean
XmTextFindStringWcs(Widget w,XmTextPosition start,wchar_t * wc_string,XmTextDirection direction,XmTextPosition * position)2241 XmTextFindStringWcs(Widget w,
2242 		    XmTextPosition start,
2243 		    wchar_t *wc_string,
2244 		    XmTextDirection direction,
2245 		    XmTextPosition *position)
2246 {
2247     _XmWarning(w, "XmTextFindStringWcs: not implemented");
2248     return False;
2249 }
2250 
2251 
2252 /*
2253  * XmTextGetSubstring()
2254  *
2255  * Gets a substring of the text
2256  */
2257 extern int
XmTextGetSubstring(Widget w,XmTextPosition start,int num_chars,int buffer_size,char * buffer)2258 XmTextGetSubstring(Widget w, XmTextPosition start, int num_chars,
2259 		   int buffer_size, char *buffer)
2260 {
2261     int			len;
2262     int			retval = XmCOPY_SUCCEEDED;
2263     XmTextBlockRec	block;
2264 
2265     if (XmIsTextField(w))
2266     {
2267 	return XmTextFieldGetSubstring(w, start, num_chars,
2268 				       buffer_size, buffer);
2269     }
2270     if (!XmIsText(w))
2271     {
2272 	_XmWarning(w, "XmTextGetSubstring: widget has invalid class");
2273 	return XmCOPY_FAILED;
2274     }
2275 
2276     len = (*Text_Source(w)->ReadSource)
2277 	    (Text_Source(w), start, start+num_chars, &block) - start;
2278 
2279     if(len < num_chars)
2280     {
2281 	retval = XmCOPY_TRUNCATED;
2282     } /* no else: retval may be updated to XmCOPY_FAILED in next test */
2283 
2284     if(len > buffer_size)
2285     {
2286 	retval = XmCOPY_FAILED;
2287     }
2288     else
2289     {
2290     	memcpy(buffer, block.ptr, len);
2291     }
2292 
2293     XtFree(block.ptr);
2294 
2295     return retval;
2296 }
2297 
2298 
2299 extern int
XmTextGetSubstringWcs(Widget w,XmTextPosition start,int num_chars,int buffer_size,wchar_t * buffer)2300 XmTextGetSubstringWcs(Widget w, XmTextPosition start, int num_chars,
2301 		      int buffer_size, wchar_t *buffer)
2302 {
2303     if (XmIsTextField(w))
2304     {
2305 	return XmTextFieldGetSubstringWcs(w, start, num_chars,
2306 					  buffer_size, buffer);
2307     }
2308 
2309     if (!XmIsText(w))
2310     {
2311 	_XmWarning(w, "XmTextGetSubstringWcs: widget has invalid class");
2312 
2313 	return XmCOPY_FAILED;
2314     }
2315 
2316     _XmWarning(w, "XmTextGetSubstringWcs: not implemented");
2317     return XmCOPY_FAILED;
2318 }
2319 
2320 
2321 extern XmTextPosition
XmTextGetTopCharacter(Widget w)2322 XmTextGetTopCharacter(Widget w)
2323 {
2324     if (XtIsSubclass(w, xmTextWidgetClass))
2325     {
2326 	return Text_TopPos(w);
2327     }
2328     else
2329     {
2330 	_XmWarning(w, "XmTextGetTopCharacter: widget has invalid class");
2331 	return 0;
2332      }
2333 }
2334 
2335 
2336 extern void
XmTextInsert(Widget w,XmTextPosition position,char * string)2337 XmTextInsert(Widget w, XmTextPosition position, char *string)
2338 {
2339     if (XtIsSubclass(w, xmTextWidgetClass))
2340     {
2341 	_XmTextInsert(w, position, string, NULL);
2342     }
2343     else if (XtIsSubclass(w, xmTextFieldWidgetClass))
2344     {
2345 	XmTextFieldInsert(w, position, string);
2346     }
2347     else
2348     {
2349 	_XmWarning(w, "XmTextInsert: widget has invalid class");
2350     }
2351 }
2352 
2353 
2354 extern void
XmTextInsertWcs(Widget w,XmTextPosition position,wchar_t * wcstring)2355 XmTextInsertWcs(Widget w, XmTextPosition position, wchar_t *wcstring)
2356 {
2357     if (XtIsSubclass(w, xmTextWidgetClass))
2358     {
2359 	_XmWarning(w, "XmTextInsertWcs: not implemented");
2360 	;			/* FIX ME */
2361     }
2362     else if (XtIsSubclass(w, xmTextFieldWidgetClass))
2363     {
2364 	XmTextFieldInsertWcs(w, position, wcstring);
2365     }
2366     else
2367     {
2368 	_XmWarning(w, "XmTextInsertWcs: widget has invalid class");
2369     }
2370 }
2371 
2372 
2373 extern Boolean
XmTextPaste(Widget w)2374 XmTextPaste(Widget w)
2375 {
2376     if (XtIsSubclass(w, xmTextWidgetClass))
2377     {
2378 	Display		*dpy = XtDisplay(w);
2379 	Window		win = XtWindow(w);
2380 	int		r;
2381 	char		*buf;
2382 	unsigned long	len, nbytes;
2383 	long		private_id;
2384 	XmTextPosition	pos;
2385 
2386 	if (win == None || !Text_Editable(w))
2387 	    return False;
2388 
2389 	while ((r = XmClipboardStartRetrieve(XtDisplay(w), XtWindow(w),
2390                 XtLastTimestampProcessed(XtDisplay(w)))) == XmClipboardLocked)
2391 	    ;
2392 	if (r != XmClipboardSuccess)
2393 	    return False;
2394 
2395 	/* Figure out how much we need to paste */
2396 	while ((r = XmClipboardInquireLength(dpy, win, "STRING", &len))
2397 		== XmClipboardLocked)
2398 	    ;
2399 	if (r != XmClipboardSuccess)
2400 	    return False;
2401 
2402 	buf = XtMalloc(len + 1);
2403 
2404 	while ((r = XmClipboardRetrieve(dpy, win, "STRING",
2405 		buf, len, &nbytes, &private_id)) == XmClipboardLocked)
2406 	    ;
2407 	buf[len] = '\0';
2408 
2409 	if (r != XmClipboardSuccess) {
2410 	    XtFree(buf);
2411 	    return False;
2412 	}
2413 	DEBUGOUT(_LtDebug(__FILE__, w,
2414 	    "XmTextPaste: should be getting %ld bytes\n", nbytes));
2415 
2416 	while ((r = XmClipboardEndRetrieve(dpy, win)) == XmClipboardLocked)
2417 	    ;
2418 	if (r != XmClipboardSuccess) {
2419 	    XtFree(buf);
2420 	    return False;
2421 	}
2422 
2423 	/* Now insert the text ... */
2424 	pos = Text_CursorPos(w);
2425 
2426 	_XmTextInsert(w, pos, buf, NULL);
2427 
2428 	XtFree(buf);
2429 	return True;
2430     } else if (XtIsSubclass(w, xmTextFieldWidgetClass)) {
2431 	return XmTextFieldPaste(w);
2432     } else {
2433 	_XmWarning(w, "XmTextPaste: widget has invalid class");
2434     }
2435 
2436     return False;
2437 }
2438 
2439 
2440 extern Boolean
XmTextPosToXY(Widget w,XmTextPosition position,Position * x,Position * y)2441 XmTextPosToXY(Widget w, XmTextPosition position, Position *x, Position *y)
2442 {
2443     if (XtIsSubclass(w, xmTextWidgetClass))
2444     {
2445 	return (*Text_Output(w)->PosToXY) ((XmTextWidget)w, position, x, y);
2446     }
2447     else if (XtIsSubclass(w, xmTextFieldWidgetClass))
2448     {
2449 	return XmTextFieldPosToXY(w, position, x, y);
2450     }
2451 
2452     _XmWarning(w, "XmTextPosToXY: widget has invalid class");
2453 
2454     return False;
2455 
2456 }
2457 
2458 
2459 extern Boolean
XmTextRemove(Widget w)2460 XmTextRemove(Widget w)
2461 {
2462     if (XtIsSubclass(w, xmTextWidgetClass))
2463     {
2464 	Boolean sel;
2465 	XmTextPosition left, right;
2466 
2467 	/* Copied part of the code of TextIn.c:DeleteForwardChar */
2468 	sel = (*Text_Source(w)->GetSelection) (Text_Source(w), &left, &right);
2469 
2470 	if (!sel || !Text_Editable(w))
2471 	{
2472 	    return False;
2473         }
2474 
2475 	_XmTextDelete((XmTextWidget)w, NULL, left, right);
2476 
2477 	return True;
2478     }
2479     else if (XtIsSubclass(w, xmTextFieldWidgetClass))
2480     {
2481 	return XmTextFieldRemove(w);
2482     }
2483     else
2484     {
2485 	_XmWarning(w, "XmTextRemove: widget has invalid class");
2486 	return False;
2487     }
2488 }
2489 
2490 
2491 extern void
XmTextReplace(Widget w,XmTextPosition from_pos,XmTextPosition to_pos,char * value)2492 XmTextReplace(Widget w, XmTextPosition from_pos, XmTextPosition to_pos, char *value)
2493 {
2494     XmTextStatus st;
2495     XmTextWidget tw = (XmTextWidget)w;
2496     XmTextBlockRec block;
2497     XmTextPosition startret, endret;
2498 
2499     if (XtIsSubclass(w, xmTextFieldWidgetClass))
2500     {
2501 	XmTextFieldReplace(w, from_pos, to_pos, value);
2502 
2503 	return;
2504     }
2505     else if (!XtIsSubclass(w, xmTextWidgetClass))
2506     {
2507 	_XmWarning(w, "XmTextReplace: widget has invalid class");
2508 
2509 	return;
2510     }
2511 
2512     DEBUGOUT(_LtDebug(__FILE__, w, "XmTextReplace(from %d to %d '%s'\n",
2513 		      from_pos, to_pos, value));
2514 
2515     block.ptr = value;
2516     block.length = value ? strlen(value) : 0;
2517     block.format = XmFMT_8_BIT;
2518 
2519     startret = from_pos;
2520     endret = to_pos;
2521 
2522     st = (*Text_Source(w)->Replace) (tw, NULL, &startret, &endret,
2523 				     &block, True);
2524     /* FIX ME ?? */
2525 
2526     RefigureLines(tw);
2527 
2528 #if 1
2529     XmTextShowPosition(w, from_pos + block.length);
2530 #else
2531     if (XtIsRealized(w))
2532     {
2533 	Redisplay(tw);
2534     }
2535 #endif
2536 }
2537 
2538 
2539 extern void
XmTextReplaceWcs(Widget w,XmTextPosition from_pos,XmTextPosition to_pos,wchar_t * wcstring)2540 XmTextReplaceWcs(Widget w, XmTextPosition from_pos, XmTextPosition to_pos,
2541 		 wchar_t *wcstring)
2542 {
2543     if (XtIsSubclass(w, xmTextFieldWidgetClass))
2544     {
2545 	XmTextFieldReplaceWcs(w, from_pos, to_pos, wcstring);
2546 
2547 	return;
2548     }
2549     else if (!XtIsSubclass(w, xmTextWidgetClass))
2550     {
2551 	_XmWarning(w, "XmTextReplaceWcs: widget has invalid class");
2552 
2553 	return;
2554     }
2555 
2556     _XmWarning(w, "XmTextReplaceWcs is not implemented");
2557 }
2558 
2559 
2560 extern void
XmTextSetAddMode(Widget w,Boolean state)2561 XmTextSetAddMode(Widget w, Boolean state)
2562 {
2563 	XmTextWidget tw = (XmTextWidget)w;
2564 
2565 	if (XtIsSubclass(w, xmTextWidgetClass)) {
2566 		Text_AddMode(w) = state;
2567 	} else if (XtIsSubclass(w, xmTextFieldWidgetClass)) {
2568 		XmTextFieldSetAddMode(w, state);
2569 	} else {
2570 		_XmWarning(w, "XmTextSetAddMode: widget has invalid class");
2571 	}
2572 }
2573 
2574 
2575 extern void
XmTextSetCursorPosition(Widget w,XmTextPosition position)2576 XmTextSetCursorPosition(Widget w, XmTextPosition position)
2577 {
2578     if (XtIsSubclass(w, xmTextWidgetClass))
2579     {
2580 	_XmTextSetCursorPosition(w, position);
2581     }
2582     else if (XtIsSubclass(w, xmTextFieldWidgetClass))
2583     {
2584 	XmTextFieldSetCursorPosition(w, position);
2585     }
2586     else
2587     {
2588 	_XmWarning(w, "XmTextSetCursorPosition: widget has invalid class");
2589     }
2590 }
2591 
2592 
2593 extern void
XmTextSetEditable(Widget w,Boolean editable)2594 XmTextSetEditable(Widget w, Boolean editable)
2595 {
2596     if (XtIsSubclass(w, xmTextFieldWidgetClass))
2597     {
2598 	XmTextFieldSetEditable(w, editable);
2599     }
2600     else if (!XmIsText(w))
2601     {
2602 	_XmWarning(w, "XmTextSetEditable: widget has invalid class");
2603 
2604 	return;
2605     }
2606 
2607     if (Text_Editable(w) != editable)
2608     {
2609 	_XmTextSetEditable(w, editable);
2610     }
2611 
2612     Text_Editable(w) = editable;
2613 }
2614 
2615 
2616 extern void
XmTextSetHighlight(Widget w,XmTextPosition left,XmTextPosition right,XmHighlightMode mode)2617 XmTextSetHighlight(Widget w, XmTextPosition left, XmTextPosition right, XmHighlightMode mode)
2618 {
2619     if (left >= right || left < 0 )
2620     {
2621 	/* FIX ME */
2622 	DEBUGOUT(_LtDebug(__FILE__, w,
2623 			  "XmTextSetHighlight %d >= %d, not sure what to do.\n",
2624 			  left, right));
2625 
2626 	return;
2627     }
2628 
2629     if (XtIsSubclass(w, xmTextWidgetClass))
2630     {
2631 	Cardinal i, j, k, l;
2632 	XmHighlightMode lm, rm;
2633 
2634 #if 0
2635 	fprintf(stderr,
2636 			  "XmTextSetHighlight(%d,%d,%s)\n",
2637 			  left, right, _LtDebugHighlightMode2String(mode));
2638 #endif
2639 	DEBUGOUT(_LtDebug(__FILE__, w,
2640 			  "XmTextSetHighlight(%d,%d,%s)\n",
2641 			  left, right, _LtDebugHighlightMode2String(mode)));
2642 
2643 	/* Provide for initial entries if there's none */
2644 	if (Text_Highlight(w).number == 0)
2645 	{
2646 	    Text_Highlight(w).list[0].position = 0;
2647 	    Text_Highlight(w).list[0].mode = XmHIGHLIGHT_NORMAL;
2648 	    Text_Highlight(w).list[1].position = INT_MAX;
2649 	    Text_Highlight(w).list[1].mode = XmHIGHLIGHT_NORMAL;
2650 	    Text_Highlight(w).number = 2;
2651 	}
2652 
2653 	/* Find the place from where to change the highlight */
2654 	for (i=0; i < Text_Highlight(w).number &&
2655 			Text_Highlight(w).list[i].position < left; i++)
2656 		;
2657 	if (i == 0)
2658 	{
2659 	    /* assert(left==0); */
2660 	    lm = XmHIGHLIGHT_NORMAL;
2661 	}
2662 	else
2663 	{
2664 	    lm = Text_Highlight(w).list[i-1].mode;
2665 	}
2666 	for (j=i; j < Text_Highlight(w).number &&
2667 			Text_Highlight(w).list[j].position < right; j++)
2668 		;
2669 	if (j == 0)
2670 	{
2671 	    /* assert(right==0); */
2672 	    rm = XmHIGHLIGHT_NORMAL;
2673 	}
2674 	else
2675 	{
2676 	    rm = Text_Highlight(w).list[j-1].mode;
2677 	}
2678 	if (Text_Highlight(w).list[i].position == left)
2679 	{
2680 	    Text_Highlight(w).list[i].mode = mode;
2681 	}
2682 	else if (Text_Highlight(w).list[i].position < right)
2683 	{
2684 	    Text_Highlight(w).list[i].mode = mode;
2685 	    Text_Highlight(w).list[i].position = left;
2686 	}
2687 	else
2688 	{
2689 	    /* Insert an entry for the left */
2690 	    if (lm != mode)
2691 	    {
2692 		/* Need one more entry */
2693 		/* Make sure there's an empty space */
2694 		if (Text_Highlight(w).number == Text_Highlight(w).maximum)
2695 		{
2696 		    Text_Highlight(w).maximum += 32;
2697 		    Text_Highlight(w).list = (_XmHighlightRec *)XtRealloc(
2698 				(char *)Text_Highlight(w).list,
2699 				Text_Highlight(w).maximum * sizeof(_XmHighlightRec));
2700 		}
2701 
2702 		/* Go ahead. Do we need to insert ? */
2703 		for (j=Text_Highlight(w).number; j>i; j--)
2704 		{
2705 		    Text_Highlight(w).list[j] = Text_Highlight(w).list[j-1];
2706 		}
2707 		Text_Highlight(w).number++;
2708 		Text_Highlight(w).list[i].mode = mode;
2709 		Text_Highlight(w).list[i].position = left;
2710 	    }
2711 	}
2712 
2713 	/* Remove entries */
2714 	/* FIX ME this can be more efficient */
2715 	for (i=0; i<Text_Highlight(w).number && Text_Highlight(w).list[i].position < left; i++) ;
2716 		/* i points to the entry just beyond "left" */
2717 	for (j=i; j<Text_Highlight(w).number && Text_Highlight(w).list[j].position < right; j++) ;
2718 	if (i < j-1)
2719 	{
2720 	    for (k=i+1, l=j; l<Text_Highlight(w).number; k++,l++)
2721 	    {
2722 		Text_Highlight(w).list[k] = Text_Highlight(w).list[l];
2723 	    }
2724 	    Text_Highlight(w).number -= j-i-1;
2725 	}
2726 	/* Now this is hilarious - insert one again */
2727 	i++;
2728 	if (rm != mode)
2729 	{
2730 	    if (Text_Highlight(w).number == Text_Highlight(w).maximum)
2731 	    {
2732 		Text_Highlight(w).maximum += 32;
2733 		Text_Highlight(w).list = (_XmHighlightRec *)XtRealloc(
2734 			    (char *)Text_Highlight(w).list,
2735 			    Text_Highlight(w).maximum * sizeof(_XmHighlightRec));
2736 	    }
2737 	    for (k=Text_Highlight(w).number; k>i; k--)
2738 	    {
2739 		Text_Highlight(w).list[k] = Text_Highlight(w).list[k-1];
2740 	    }
2741 	    Text_Highlight(w).number++;
2742 	    Text_Highlight(w).list[i].mode = rm;
2743 	    Text_Highlight(w).list[i].position = right;
2744 	}
2745 	/* End Highlighting */
2746 #if 0
2747 	for (i=0; i<Text_Highlight(w).number; i++)
2748 		fprintf(stderr,
2749 			  "\tXmTextSetHighlight -> [%d] %d %s\n",
2750 			  i, Text_Highlight(w).list[i].position,
2751 			  _LtDebugHighlightMode2String(Text_Highlight(w).list[i].mode));
2752 #endif
2753 
2754 	if (XtIsRealized(w))
2755 	{
2756 	    DoExpose(w, NULL, NULL);
2757 	}
2758     }
2759     else if (XtIsSubclass(w, xmTextFieldWidgetClass))
2760     {
2761 	XmTextFieldSetHighlight(w, left, right, mode);
2762     }
2763     else
2764     {
2765 	_XmWarning(w, "XmTextSetHighlight: widget has invalid class");
2766     }
2767 }
2768 
2769 
2770 extern void
XmTextSetInsertionPosition(Widget w,XmTextPosition position)2771 XmTextSetInsertionPosition(Widget w, XmTextPosition position)
2772 {
2773     if (XtIsSubclass(w, xmTextFieldWidgetClass))
2774     {
2775 	XmTextFieldSetCursorPosition(w, position);
2776     }
2777     else if (XtIsSubclass(w, xmTextWidgetClass))
2778     {
2779 	_XmTextSetCursorPosition(w, position);
2780 	Text_DestPosition(w)= Text_CursorPos(w);
2781     }
2782     else
2783     {
2784 	_XmWarning(w, "XmTextSetInsertionPosition: widget has invalid class");
2785     }
2786 }
2787 
2788 
2789 extern void
XmTextSetMaxLength(Widget w,int max_length)2790 XmTextSetMaxLength(Widget w, int max_length)
2791 {
2792     if (XtIsSubclass(w, xmTextWidgetClass))
2793     {
2794 	_XmStringSourceSetMaxLength(Text_Source(w), max_length);
2795     }
2796     else if (XtIsSubclass(w, xmTextFieldWidgetClass))
2797     {
2798 	XmTextFieldSetMaxLength(w, max_length);
2799     }
2800     else
2801     {
2802 	_XmWarning(w, "XmTextSetMaxLength: widget has invalid class");
2803     }
2804 }
2805 
2806 
2807 extern void
XmTextSetSelection(Widget w,XmTextPosition first,XmTextPosition last,Time time)2808 XmTextSetSelection(Widget w, XmTextPosition first, XmTextPosition last,
2809 		   Time time)
2810 {
2811     DEBUGOUT(_LtDebug(__FILE__, w, "XmTextSetSelection(%d,%d)\n", first, last));
2812 
2813     if (XtIsSubclass(w, xmTextWidgetClass))
2814     {
2815 	(*Text_Source(w)->SetSelection) (Text_Source(w), first, last, time);
2816     }
2817     else if (XtIsSubclass(w, xmTextFieldWidgetClass))
2818     {
2819 	XmTextFieldSetSelection(w, first, last, time);
2820     }
2821     else
2822     {
2823 	_XmWarning(w, "XmTextSetSelection: widget has invalid class");
2824     }
2825 }
2826 
2827 
2828 extern void
XmTextSetString(Widget w,char * value)2829 XmTextSetString(Widget w, char *value)
2830 {
2831     XmTextWidget tw = (XmTextWidget)w;
2832 
2833     if (XtIsSubclass(w, xmTextFieldWidgetClass))
2834     {
2835 	XmTextFieldSetString(w, value);
2836     }
2837     else if (XtIsSubclass(w, xmTextWidgetClass))
2838     {
2839 	_XmStringSourceSetValue(tw, value);
2840 
2841 	Text_TopPos(w) = 0;
2842 #if 0
2843 	/* rws 10 Mar 2000
2844 	   This cannot happen here. If the modifyVerify callback came back
2845 	   with doit False, nothing changed!!!
2846 	 */
2847 	Text_LastPos(w) = (value ? strlen(value) : 0);
2848 #endif
2849 
2850 #if 0
2851         // SG 01/11/1998 Reset the insertion point to the beginning
2852         // however this will only effect this widget using the source,
2853         // should the source take care of doing this for all its attached
2854         // widgets.
2855 #endif
2856 	Text_CursorPos(w) = 0;
2857 
2858 	DEBUGOUT(_LtDebug(__FILE__, w, "XmTextSetString(%s), lastpos %d\n",
2859 		value, Text_LastPos(w)));
2860 
2861 	_XmTextUpdateLineTable(w, 0, 0, NULL, False);
2862 
2863 	RefigureLines(tw);
2864 
2865 	(*Text_Output(tw)->Invalidate) (tw, 0, 0, 0);
2866 
2867 	if (XtIsRealized(w))
2868 	{
2869 	    Redisplay(tw);
2870 	}
2871     }
2872     else
2873     {
2874 	_XmWarning(w, "XmTextSetString: widget has invalid class");
2875     }
2876 }
2877 
2878 
2879 extern void
XmTextSetStringWcs(Widget w,wchar_t * wcstring)2880 XmTextSetStringWcs(Widget w, wchar_t *wcstring)
2881 {
2882     if (XtIsSubclass(w, xmTextWidgetClass))
2883     {
2884 	_XmWarning(w, "XmTextSetStringWcs: not implemented");
2885 	;			/* FIX ME */
2886     }
2887     else if (XtIsSubclass(w, xmTextFieldWidgetClass))
2888     {
2889 	XmTextFieldSetStringWcs(w, wcstring);
2890     }
2891     else
2892     {
2893 	_XmWarning(w, "XmTextSetStringWcs: widget has invalid class");
2894     }
2895 }
2896 
2897 
2898 extern void
XmTextDisableRedisplay(Widget w)2899 XmTextDisableRedisplay(Widget w)
2900 {
2901     Text_DisableDepth(w)++;
2902 }
2903 
2904 
2905 extern void
XmTextEnableRedisplay(Widget w)2906 XmTextEnableRedisplay(Widget w)
2907 {
2908     _XmTextEnableRedisplay((XmTextWidget)w);
2909 }
2910 
2911 
2912 extern XmTextSource
XmTextGetSource(Widget w)2913 XmTextGetSource(Widget w)
2914 {
2915     return Text_Source(w);
2916 }
2917 
2918 
2919 extern void
XmTextSetSource(Widget w,XmTextSource s,XmTextPosition top,XmTextPosition curs)2920 XmTextSetSource(Widget w, XmTextSource s,
2921 		XmTextPosition top, XmTextPosition curs)
2922 {
2923     XmTextWidget tw = (XmTextWidget)w;
2924 
2925     DEBUGOUT(_LtDebug(__FILE__, w, "XmTextSetSource\n"));
2926 
2927     if (s == NULL)
2928     {
2929 	_XmWarning(w, "Invalid source, source ignored.");
2930 	return;
2931     }
2932 
2933     (*Text_Source(w)->RemoveWidget) (Text_Source(w), tw);
2934 
2935     Text_Source(w) = s;
2936 
2937     (*Text_Source(w)->AddWidget) (Text_Source(w), tw);
2938 
2939     _XmTextUpdateLineTable(w, 0, 0, NULL, False);
2940 
2941     RefigureLines(tw);
2942 
2943     if (XtIsRealized(w))
2944     {
2945 	Redisplay(tw);
2946     }
2947 }
2948 
2949 
2950 extern void
XmTextScroll(Widget aw,int n)2951 XmTextScroll(Widget aw, int n)
2952 {
2953     XmTextWidget w = (XmTextWidget)aw;
2954     int top_index, index;
2955 
2956     if (!XtIsSubclass((Widget)w, xmTextWidgetClass))
2957     {
2958 	_XmWarning((Widget)w, "XmTextScroll: widget has invalid class");
2959 
2960 	return;
2961     }
2962 
2963     top_index = _XmTextGetTableIndex(w, Text_TopPos(w));
2964     if (n < 0)
2965     {
2966 	index = _XmMax(n + top_index, 0);
2967     }
2968     else
2969     {
2970 	/* bug #672292 */
2971 	index = _XmMin(n + top_index, Text_TotalLines(w)-1);
2972 #if 0
2973 	index = _XmMin(n + top_index,
2974 /* SG (15/08/1998)  Text_TotalLines(w) - 1) - Text_LineCount(w) + 1;
2975    we would rather like to be able to scroll down to the last line */
2976 		       Text_TotalLines(w) ) - Text_LineCount(w) + 1;
2977 #endif
2978     }
2979     DEBUGOUT(_LtDebug(__FILE__, aw, "XmTextScroll index=%d n=%d\n", index, n));
2980 
2981     Text_TableIndex(w) = index;
2982     XmTextSetTopCharacter(aw, Text_LineTable(w)[index].start_pos);
2983 }
2984 
2985 
2986 extern void
XmTextSetTopCharacter(Widget w,XmTextPosition top_character)2987 XmTextSetTopCharacter(Widget w, XmTextPosition top_character)
2988 {
2989     if (!XtIsSubclass(w, xmTextWidgetClass))
2990     {
2991 	_XmWarning(w, "XmTextSetTopCharacter: widget has invalid class");
2992 
2993 	return;
2994     }
2995 
2996     DEBUGOUT(_LtDebug(__FILE__, w, "XmTextSetTopCharacter top_character=%d\n",
2997 		      top_character));
2998 
2999     if (Text_EditMode(w) == XmSINGLE_LINE_EDIT)
3000     {
3001 	/* Scroll horizontally until top_character is leftmost character */
3002     }
3003     else
3004     {
3005 	/*
3006 	 * If w is in MULTI_LINE_EDIT then set Text_TopPos(w)
3007 	 * to the position of the first character of the line that
3008 	 * top_character points at.
3009 	 */
3010 
3011 	XmTextLineTable	lte;
3012 
3013 	lte = Text_LineTable(w) + _XmTextGetTableIndex((XmTextWidget)w,top_character);
3014 	Text_TopPos(w) = lte->start_pos;
3015 
3016 	RefigureLines((XmTextWidget)w);
3017 
3018 	if (XtIsRealized(w))
3019 	{
3020 	    Redisplay((XmTextWidget)w);
3021 	}
3022     }
3023 }
3024 
3025 
3026 extern void
XmTextShowPosition(Widget aw,XmTextPosition position)3027 XmTextShowPosition(Widget aw, XmTextPosition position)
3028 {
3029     XmTextWidget w = (XmTextWidget)aw;
3030     unsigned int top_index, index, bottom_index;
3031 
3032     DEBUGOUT(_LtDebug(__FILE__, aw, "XmTextShowPosition pos=%d\n", position));
3033 
3034     if (XtIsSubclass(aw, xmTextFieldWidgetClass)) {
3035 	XmTextFieldShowPosition(aw, position);
3036     } else if (XtIsSubclass(aw, xmTextWidgetClass)) {
3037 	bottom_index = _XmTextGetTableIndex(w, Text_BottomPos(w));
3038 	top_index = _XmTextGetTableIndex(w, Text_TopPos(w));
3039 	index = _XmTextGetTableIndex(w, position);
3040 
3041 	/* We need only be concerned with the Text_TopPos here. */
3042 
3043 	if (index < top_index) {
3044 	    ;
3045 	} else if (bottom_index < index) {
3046 	    /* This used to be here, but it's wrong :
3047 		index += top_index - bottom_index;
3048 	     */
3049 	    index = bottom_index;
3050 	} else {
3051 	    index = top_index;
3052 	}
3053 	Text_TopPos(w) = Text_LineTable(w)[index].start_pos;
3054 
3055 	/*
3056 	 * ... because the Output object will do the hard work for us anyway.
3057 	 *
3058 	 * MakePositionVisible will (I hope) also do horizontal positioning.
3059 	 */
3060 
3061 	(*Text_Output(w)->MakePositionVisible) (w, position);
3062 
3063 	if (Text_NeedsRedisplay(w)) {
3064 	    Redisplay(w);
3065 	}
3066     }
3067 }
3068 
3069 
3070 extern XmTextPosition
XmTextXYToPos(Widget w,Position x,Position y)3071 XmTextXYToPos(Widget w, Position x, Position y)
3072 {
3073     DEBUGOUT(_LtDebug(__FILE__, w, "XmTextXYToPos x=%d y=%d\n", x, y));
3074 
3075     if (XtIsSubclass(w, xmTextFieldWidgetClass))
3076     {
3077 	return XmTextFieldXYToPos(w, x, y);
3078     }
3079     else if (XtIsSubclass(w, xmTextWidgetClass))
3080     {
3081 	return (*Text_Output(w)->XYToPos) ((XmTextWidget)w, x, y);
3082     }
3083     else
3084     {
3085 	return 0;
3086     }
3087 }
3088 
3089 
3090 extern void
_XmTextExportValue(Widget w,int offset,XtArgVal * value)3091 _XmTextExportValue(Widget w, int offset, XtArgVal *value)
3092 {
3093     *value = (XtArgVal)XmTextGetString(w);
3094 
3095     DEBUGOUT(_LtDebug(__FILE__, w,
3096 		      "_XmTextExportValue: value '%s'\n",
3097 		      (char *)*value));
3098 }
3099 
3100 
3101 /*
3102  * GetValues works through a whole bunch of stuff here :
3103  * - the "normal" mechanism : Xt will copy stuff specified in resources
3104  * - synthetic resources : LessTif does this through GetValuesHook on
3105  *      the Primitive which is our superclass. _XmTextExportValue above
3106  *      is an example of this.
3107  * - explicit call of GetValues functions in our subparts, see below.
3108  *      The implementations of these are where they belong (in TextIn.c
3109  *      and TextOut.c), and both use XtGetSubvalues.
3110  *
3111  * For the infinitely curious, the last subpart (if you want to call it that),
3112  *      the XmTextSource, has no resources that you can access this way. It's
3113  *      not an Xt Object.
3114  */
3115 static void
TextGetValues(Widget w,ArgList args,Cardinal * num_args)3116 TextGetValues(Widget w, ArgList args, Cardinal *num_args)
3117 {
3118     /* Call the GetValues method in our subparts. */
3119     if (Text_Output(w))
3120     {
3121 	(*Text_Output(w)->GetValues) (w, args, *num_args);
3122     }
3123 
3124     if (Text_Input(w))
3125     {
3126 	(*Text_Input(w)->GetValues) (w, args, *num_args);
3127     }
3128 
3129     /* Be verbose about what they're trying to find out */
3130     DEBUGOUT(_LtDebug(__FILE__, w, "TextGetValues :\n"));
3131     DEBUGOUT(_LtDebugPrintArgList(__FILE__, w, args, *num_args, True));
3132 }
3133 
3134 
3135 extern int
_XmTextGetTotalLines(Widget w)3136 _XmTextGetTotalLines(Widget w)
3137 {
3138 	return Text_TotalLines(w);
3139 }
3140 
3141 
3142 extern void
_XmTextSetTopCharacter(Widget w,XmTextPosition top_character)3143 _XmTextSetTopCharacter (  Widget w,
3144                       XmTextPosition top_character)
3145 {
3146     if (Text_EditMode(w) == XmSINGLE_LINE_EDIT)
3147     {
3148 	/* Scroll horizontally until top_character is leftmost character */
3149     }
3150     else
3151     {
3152 	int index = _XmTextGetTableIndex( (XmTextWidget)w, top_character);
3153 	if ( Text_TopPos(w) != top_character )
3154 	    {
3155 	    Text_NeedsRedisplay(w) = True;
3156 	    Text_NeedsRefigureLines(w) = True;
3157 	    }
3158 	Text_NewTop(w) = Text_LineTable(w)[index].start_pos;
3159 	Text_TableIndex(w)=index;
3160 	if ( Text_NeedsRefigureLines(w) )
3161 	    RefigureLines((XmTextWidget)w);
3162 
3163 	if (XtIsRealized(w))
3164 	{
3165 	    Redisplay((XmTextWidget)w);
3166 	}
3167     }
3168 }
3169 
3170 
3171 extern LineNum
_XmTextNumLines(XmTextWidget widget)3172 _XmTextNumLines(XmTextWidget widget)
3173 {
3174 	return Text_LineCount(widget);
3175 }
3176 
3177 /*
3178  * Not sure whether I need to do all this copying.
3179  * FIX ME
3180  */
3181 static XtPointer
_XmText_TraitGetValue(Widget w,int format)3182 _XmText_TraitGetValue(Widget w, int format)
3183 {
3184 	DEBUGOUT(_LtDebug(__FILE__, w, "_XmText_TraitGetValue(%s)\n",
3185 		(format == XmFORMAT_XmSTRING) ? "XmFORMAT_XmSTRING" :
3186 		(format == XmFORMAT_MBYTE) ? "XmFORMAT_MBYTE" :
3187 		(format == XmFORMAT_WCS) ? "XmFORMAT_WCS" : "??"));
3188 
3189 	switch (format) {
3190 	case XmFORMAT_XmSTRING:
3191 		return (XtPointer)XmStringCreateSimple(Text_Value(w));
3192 	case XmFORMAT_MBYTE:
3193 		return XtNewString(XmTextGetString(w)); /* FIX ME */
3194 	case XmFORMAT_WCS:
3195 		return XtNewString(XmTextGetString(w)); /* FIX ME */
3196 	default:
3197 		return NULL;
3198 	}
3199 }
3200 
3201 static void
_XmText_TraitSetValue(Widget w,XtPointer value,int format)3202 _XmText_TraitSetValue(Widget w, XtPointer value, int format)
3203 {
3204 	char    *s;
3205 
3206 	DEBUGOUT(_LtDebug(__FILE__, w, "_XmText_TraitSetValue(%s)\n",
3207 		(format == XmFORMAT_XmSTRING) ? "XmFORMAT_XmSTRING" :
3208 		(format == XmFORMAT_MBYTE) ? "XmFORMAT_MBYTE" :
3209 		(format == XmFORMAT_WCS) ? "XmFORMAT_WCS" : "??"));
3210 
3211 	switch (format) {
3212 	case XmFORMAT_XmSTRING:
3213 	    if (XmStringGetLtoR((XmString)value, XmFONTLIST_DEFAULT_TAG, &s)) {
3214 		XmTextSetString(w, s);
3215 	    }
3216 	    return;
3217 	case XmFORMAT_MBYTE:
3218 	    /* FIX ME */
3219 	    XmTextSetString(w, (char *)value);
3220 	    return;
3221 	case XmFORMAT_WCS:
3222 	    /* FIX ME */
3223 	    XmTextSetString(w, (char *)value);
3224 	    return;
3225 	default:
3226 	    return;
3227 	}
3228 }
3229 
3230 static int
_XmText_TraitPreferredFormat(Widget w)3231 _XmText_TraitPreferredFormat(Widget w)
3232 {
3233 	DEBUGOUT(_LtDebug(__FILE__, w, "_XmText_TraitPreferredFormat\n"));
3234 
3235 	return XmFORMAT_WCS;
3236 }
3237 
3238 extern Boolean
XmTextCopyLink(Widget widget,Time time)3239 XmTextCopyLink(Widget widget,
3240                Time time)
3241 {
3242    _XmWarning(NULL, "XmTextCopyLink(): not yet implemented!");
3243    return False;
3244 }
3245