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