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