1 /* $XConsortium: Text.c /main/198 1995/08/17 09:37:40 kaleb $ */
3 /***********************************************************
5 Copyright (c) 1987, 1988, 1994 X Consortium
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 Except as contained in this notice, the name of the X Consortium shall not be
25 used in advertising or otherwise to promote the sale, use or other dealings
26 in this Software without prior written authorization from the X Consortium.
29 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
33 Permission to use, copy, modify, and distribute this software and its
34 documentation for any purpose and without fee is hereby granted,
35 provided that the above copyright notice appear in all copies and that
36 both that copyright notice and this permission notice appear in
37 supporting documentation, and that the name of Digital not be
38 used in advertising or publicity pertaining to distribution of the
39 software without specific, written prior permission.
41 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
42 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
43 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
44 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
45 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
46 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49 ******************************************************************/
51 #include <X11/IntrinsicP.h>
52 #include <X11/StringDefs.h>
53 #include <X11/Shell.h>
54 #include <X11/Xatom.h>
55 #include <X11/Xutil.h>
59 #include <X11/Xmu/Atoms.h>
60 #include <X11/Xmu/CharSet.h>
61 #include <X11/Xmu/Converters.h>
62 #include <X11/Xmu/StdSel.h>
63 #include <X11/Xmu/Misc.h>
65 #include <X11/Xaw/XawInit.h>
66 #include <X11/Xaw/Cardinals.h>
67 #include <X11/Xaw/Scrollbar.h>
69 #include <X11/Xaw/MultiSinkP.h>
70 #include <X11/Xaw/XawImP.h>
72 #include <X11/Xfuncs.h>
73 #include <ctype.h> /* for isprint() */
76 #define MAX_LEN_CT 6 /* for sequence: ESC $ ( A \xx \xx */
79 unsigned long FMT8BIT
= 0L;
80 unsigned long XawFmt8Bit
= 0L;
81 unsigned long XawFmtWide
= 0L;
83 #define SinkClearToBG XawTextSinkClearToBackground
85 #define SrcScan XawTextSourceScan
86 #define SrcRead XawTextSourceRead
87 #define SrcReplace XawTextSourceReplace
88 #define SrcSearch XawTextSourceSearch
89 #define SrcCvtSel XawTextSourceConvertSelection
90 #define SrcSetSelection XawTextSourceSetSelection
92 #define BIGNUM ((Dimension)32023)
93 #define MULTI_CLICK_TIME 500L
96 * Compute a the maximum length of a cut buffer that we can pass at any
97 * time. The 64 allows for the overhead of the Change Property request.
100 #define MAX_CUT_LEN(dpy) (XMaxRequestSize(dpy) - 64)
102 #define IsValidLine(ctx, num) ( ((num) == 0) || \
103 ((ctx)->text.lt.info[(num)].position != 0) )
108 static void UnrealizeScrollbars();
109 static void VScroll(), VJump(), HScroll(), HJump(), ClearWindow();
110 static void DisplayTextWindow(), ModifySelection(), PushCopyQueue();
111 static void UpdateTextInLine(), UpdateTextInRectangle(), PopCopyQueue();
112 static void FlushUpdate();
113 static Boolean
LineAndXYForPosition(), TranslateExposeRegion();
114 static XawTextPosition
FindGoodPosition(), _BuildLineTable();
116 void _XawTextAlterSelection(), _XawTextExecuteUpdate();
117 void _XawTextSetScrollBars(), _XawTextPrepareToUpdate();
119 /****************************************************************
121 * Full class record constant
123 ****************************************************************/
125 static XawTextSelectType defaultSelectTypes
[] = {
126 XawselectPosition
, XawselectWord
, XawselectLine
, XawselectParagraph
,
127 XawselectAll
, XawselectNull
,
130 static XPointer defaultSelectTypesPtr
= (XPointer
)defaultSelectTypes
;
131 extern char *_XawDefaultTextTranslations1
, *_XawDefaultTextTranslations2
,
132 *_XawDefaultTextTranslations3
, *_XawDefaultTextTranslations4
;
133 static Dimension defWidth
= 100;
134 static Dimension defHeight
= DEFAULT_TEXT_HEIGHT
;
136 #define offset(field) XtOffsetOf(TextRec, field)
137 static XtResource resources
[] = {
138 {XtNwidth
, XtCWidth
, XtRDimension
, sizeof(Dimension
),
139 offset(core
.width
), XtRDimension
, (XtPointer
)&defWidth
},
140 {XtNcursor
, XtCCursor
, XtRCursor
, sizeof(Cursor
),
141 offset(simple
.cursor
), XtRString
, "xterm"},
142 {XtNheight
, XtCHeight
, XtRDimension
, sizeof(Dimension
),
143 offset(core
.height
), XtRDimension
, (XtPointer
)&defHeight
},
144 {XtNdisplayPosition
, XtCTextPosition
, XtRInt
, sizeof(XawTextPosition
),
145 offset(text
.lt
.top
), XtRImmediate
, (XtPointer
)0},
146 {XtNinsertPosition
, XtCTextPosition
, XtRInt
, sizeof(XawTextPosition
),
147 offset(text
.insertPos
), XtRImmediate
,(XtPointer
)0},
148 {XtNleftMargin
, XtCMargin
, XtRPosition
, sizeof (Position
),
149 offset(text
.r_margin
.left
), XtRImmediate
, (XtPointer
)2},
150 {XtNrightMargin
, XtCMargin
, XtRPosition
, sizeof (Position
),
151 offset(text
.r_margin
.right
), XtRImmediate
, (XtPointer
)4},
152 {XtNtopMargin
, XtCMargin
, XtRPosition
, sizeof (Position
),
153 offset(text
.r_margin
.top
), XtRImmediate
, (XtPointer
)2},
154 {XtNbottomMargin
, XtCMargin
, XtRPosition
, sizeof (Position
),
155 offset(text
.r_margin
.bottom
), XtRImmediate
, (XtPointer
)2},
156 {XtNselectTypes
, XtCSelectTypes
, XtRPointer
,
157 sizeof(XawTextSelectType
*), offset(text
.sarray
),
158 XtRPointer
, (XtPointer
)&defaultSelectTypesPtr
},
159 {XtNtextSource
, XtCTextSource
, XtRWidget
, sizeof (Widget
),
160 offset(text
.source
), XtRImmediate
, NULL
},
161 {XtNtextSink
, XtCTextSink
, XtRWidget
, sizeof (Widget
),
162 offset(text
.sink
), XtRImmediate
, NULL
},
163 {XtNdisplayCaret
, XtCOutput
, XtRBoolean
, sizeof(Boolean
),
164 offset(text
.display_caret
), XtRImmediate
, (XtPointer
)True
},
165 {XtNscrollVertical
, XtCScroll
, XtRScrollMode
, sizeof(XawTextScrollMode
),
166 offset(text
.scroll_vert
), XtRImmediate
, (XtPointer
) XawtextScrollNever
},
167 {XtNscrollHorizontal
, XtCScroll
, XtRScrollMode
, sizeof(XawTextScrollMode
),
168 offset(text
.scroll_horiz
), XtRImmediate
, (XtPointer
) XawtextScrollNever
},
169 {XtNwrap
, XtCWrap
, XtRWrapMode
, sizeof(XawTextWrapMode
),
170 offset(text
.wrap
), XtRImmediate
, (XtPointer
) XawtextWrapNever
},
171 {XtNresize
, XtCResize
, XtRResizeMode
, sizeof(XawTextResizeMode
),
172 offset(text
.resize
), XtRImmediate
, (XtPointer
) XawtextResizeNever
},
173 {XtNautoFill
, XtCAutoFill
, XtRBoolean
, sizeof(Boolean
),
174 offset(text
.auto_fill
), XtRImmediate
, (XtPointer
) FALSE
},
175 {XtNunrealizeCallback
, XtCCallback
, XtRCallback
, sizeof(XtPointer
),
176 offset(text
.unrealize_callbacks
), XtRCallback
, (XtPointer
) NULL
}
182 CvtStringToScrollMode(args
, num_args
, fromVal
, toVal
)
183 XrmValuePtr args
; /* unused */
184 Cardinal
*num_args
; /* unused */
188 static XawTextScrollMode scrollMode
;
189 static XrmQuark QScrollNever
, QScrollAlways
, QScrollWhenNeeded
;
192 static Boolean inited
= FALSE
;
195 QScrollNever
= XrmPermStringToQuark(XtEtextScrollNever
);
196 QScrollWhenNeeded
= XrmPermStringToQuark(XtEtextScrollWhenNeeded
);
197 QScrollAlways
= XrmPermStringToQuark(XtEtextScrollAlways
);
201 if (strlen ((char*) fromVal
->addr
) < sizeof lowerName
) {
202 XmuCopyISOLatin1Lowered (lowerName
, (char *)fromVal
->addr
);
203 q
= XrmStringToQuark(lowerName
);
205 if (q
== QScrollNever
) scrollMode
= XawtextScrollNever
;
206 else if (q
== QScrollWhenNeeded
) scrollMode
= XawtextScrollWhenNeeded
;
207 else if (q
== QScrollAlways
) scrollMode
= XawtextScrollAlways
;
213 toVal
->size
= sizeof scrollMode
;
214 toVal
->addr
= (XPointer
) &scrollMode
;
223 CvtStringToWrapMode(args
, num_args
, fromVal
, toVal
)
224 XrmValuePtr args
; /* unused */
225 Cardinal
*num_args
; /* unused */
229 static XawTextWrapMode wrapMode
;
230 static XrmQuark QWrapNever
, QWrapLine
, QWrapWord
;
232 char lowerName
[BUFSIZ
];
233 static Boolean inited
= FALSE
;
236 QWrapNever
= XrmPermStringToQuark(XtEtextWrapNever
);
237 QWrapLine
= XrmPermStringToQuark(XtEtextWrapLine
);
238 QWrapWord
= XrmPermStringToQuark(XtEtextWrapWord
);
242 if (strlen ((char*) fromVal
->addr
) < sizeof lowerName
) {
243 XmuCopyISOLatin1Lowered (lowerName
, (char *)fromVal
->addr
);
244 q
= XrmStringToQuark(lowerName
);
246 if (q
== QWrapNever
) wrapMode
= XawtextWrapNever
;
247 else if (q
== QWrapLine
) wrapMode
= XawtextWrapLine
;
248 else if (q
== QWrapWord
) wrapMode
= XawtextWrapWord
;
254 toVal
->size
= sizeof wrapMode
;
255 toVal
->addr
= (XPointer
) &wrapMode
;
264 CvtStringToResizeMode(args
, num_args
, fromVal
, toVal
)
265 XrmValuePtr args
; /* unused */
266 Cardinal
*num_args
; /* unused */
270 static XawTextResizeMode resizeMode
;
271 static XrmQuark QResizeNever
, QResizeWidth
, QResizeHeight
, QResizeBoth
;
274 static Boolean inited
= FALSE
;
277 QResizeNever
= XrmPermStringToQuark(XtEtextResizeNever
);
278 QResizeWidth
= XrmPermStringToQuark(XtEtextResizeWidth
);
279 QResizeHeight
= XrmPermStringToQuark(XtEtextResizeHeight
);
280 QResizeBoth
= XrmPermStringToQuark(XtEtextResizeBoth
);
284 if (strlen ((char*) fromVal
->addr
) < sizeof lowerName
) {
285 XmuCopyISOLatin1Lowered (lowerName
, (char *)fromVal
->addr
);
286 q
= XrmStringToQuark(lowerName
);
288 if (q
== QResizeNever
) resizeMode
= XawtextResizeNever
;
289 else if (q
== QResizeWidth
) resizeMode
= XawtextResizeWidth
;
290 else if (q
== QResizeHeight
) resizeMode
= XawtextResizeHeight
;
291 else if (q
== QResizeBoth
) resizeMode
= XawtextResizeBoth
;
297 toVal
->size
= sizeof resizeMode
;
298 toVal
->addr
= (XPointer
) &resizeMode
;
308 size_t len1
= strlen (_XawDefaultTextTranslations1
);
309 size_t len2
= strlen (_XawDefaultTextTranslations2
);
310 size_t len3
= strlen (_XawDefaultTextTranslations3
);
311 size_t len4
= strlen (_XawDefaultTextTranslations4
);
312 char *buf
= XtMalloc ((unsigned)(len1
+ len2
+ len3
+ len4
+ 1));
316 FMT8BIT
= XawFmt8Bit
= XrmPermStringToQuark("FMT8BIT");
318 XawFmtWide
= XrmPermStringToQuark("FMTWIDE");
320 XawInitializeWidgetSet();
323 * Set the number of actions.
326 textClassRec
.core_class
.num_actions
= _XawTextActionsTableCount
;
328 (void) strcpy( cp
, _XawDefaultTextTranslations1
); cp
+= len1
;
329 (void) strcpy( cp
, _XawDefaultTextTranslations2
); cp
+= len2
;
330 (void) strcpy( cp
, _XawDefaultTextTranslations3
); cp
+= len3
;
331 (void) strcpy( cp
, _XawDefaultTextTranslations4
);
332 textWidgetClass
->core_class
.tm_table
= buf
;
334 XtAddConverter(XtRString
, XtRScrollMode
, CvtStringToScrollMode
,
335 (XtConvertArgList
)NULL
, (Cardinal
)0 );
336 XtAddConverter(XtRString
, XtRWrapMode
, CvtStringToWrapMode
,
337 (XtConvertArgList
)NULL
, (Cardinal
)0 );
338 XtAddConverter(XtRString
, XtRResizeMode
, CvtStringToResizeMode
,
339 (XtConvertArgList
)NULL
, (Cardinal
)0 );
342 /* Function Name: PositionHScrollBar.
343 * Description: Positions the Horizontal scrollbar.
344 * Arguments: ctx - the text widget.
349 PositionHScrollBar(ctx
)
352 Widget vbar
= ctx
->text
.vbar
, hbar
= ctx
->text
.hbar
;
353 Position top
, left
= 0;
355 if (ctx
->text
.hbar
== NULL
) return;
358 left
+= (Position
) (vbar
->core
.width
+ vbar
->core
.border_width
);
360 XtResizeWidget( hbar
, ctx
->core
.width
- left
, hbar
->core
.height
,
361 hbar
->core
.border_width
);
363 left
-= (Position
) hbar
->core
.border_width
;
365 top
= ctx
->core
.height
- ( hbar
->core
.height
+ hbar
->core
.border_width
);
366 XtMoveWidget( hbar
, left
, top
);
369 /* Function Name: PositionVScrollBar.
370 * Description: Positions the Vertical scrollbar.
371 * Arguments: ctx - the text widget.
376 PositionVScrollBar(ctx
)
379 Widget vbar
= ctx
->text
.vbar
;
382 if (vbar
== NULL
) return;
383 bw
= vbar
->core
.border_width
;
385 XtResizeWidget( vbar
, vbar
->core
.width
, ctx
->core
.height
, bw
);
386 XtMoveWidget( vbar
, -(Position
)bw
, -(Position
)bw
);
390 CreateVScrollBar(ctx
)
395 if (ctx
->text
.vbar
!= NULL
) return;
397 ctx
->text
.vbar
= vbar
=
398 XtCreateWidget("vScrollbar", scrollbarWidgetClass
, (Widget
)ctx
,
399 (ArgList
) NULL
, ZERO
);
400 XtAddCallback( vbar
, XtNscrollProc
, VScroll
, (XtPointer
)ctx
);
401 XtAddCallback( vbar
, XtNjumpProc
, VJump
, (XtPointer
)ctx
);
402 if (ctx
->text
.hbar
== NULL
)
403 XtAddCallback((Widget
) ctx
, XtNunrealizeCallback
, UnrealizeScrollbars
,
406 ctx
->text
.r_margin
.left
+= vbar
->core
.width
+ vbar
->core
.border_width
;
407 ctx
->text
.margin
.left
= ctx
->text
.r_margin
.left
;
409 PositionVScrollBar(ctx
);
410 PositionHScrollBar(ctx
); /* May modify location of Horiz. Bar. */
412 if (XtIsRealized((Widget
)ctx
)) {
413 XtRealizeWidget(vbar
);
418 /* Function Name: DestroyVScrollBar
419 * Description: Removes a vertical ScrollBar.
420 * Arguments: ctx - the parent text widget.
425 DestroyVScrollBar(ctx
)
428 Widget vbar
= ctx
->text
.vbar
;
430 if (vbar
== NULL
) return;
432 ctx
->text
.r_margin
.left
-= vbar
->core
.width
+ vbar
->core
.border_width
;
433 ctx
->text
.margin
.left
= ctx
->text
.r_margin
.left
;
434 if (ctx
->text
.hbar
== NULL
)
435 XtRemoveCallback((Widget
) ctx
, XtNunrealizeCallback
, UnrealizeScrollbars
,
437 XtDestroyWidget(vbar
);
438 ctx
->text
.vbar
= NULL
;
439 PositionHScrollBar(ctx
);
443 CreateHScrollBar(ctx
)
449 if (ctx
->text
.hbar
!= NULL
) return;
451 XtSetArg(args
[0], XtNorientation
, XtorientHorizontal
);
452 ctx
->text
.hbar
= hbar
=
453 XtCreateWidget("hScrollbar", scrollbarWidgetClass
, (Widget
)ctx
, args
, ONE
);
454 XtAddCallback( hbar
, XtNscrollProc
, HScroll
, (XtPointer
)ctx
);
455 XtAddCallback( hbar
, XtNjumpProc
, HJump
, (XtPointer
)ctx
);
456 if (ctx
->text
.vbar
== NULL
)
457 XtAddCallback((Widget
) ctx
, XtNunrealizeCallback
, UnrealizeScrollbars
,
460 PositionHScrollBar(ctx
);
461 if (XtIsRealized((Widget
)ctx
)) {
462 XtRealizeWidget(hbar
);
467 /* Function Name: DestroyHScrollBar
468 * Description: Removes a horizontal ScrollBar.
469 * Arguments: ctx - the parent text widget.
474 DestroyHScrollBar(ctx
)
477 Widget hbar
= ctx
->text
.hbar
;
479 if (hbar
== NULL
) return;
482 ctx->text.r_margin.bottom -= hbar->core.height + hbar->core.border_width;
483 ctx->text.margin.bottom = ctx->text.r_margin.bottom;
485 if (ctx
->text
.vbar
== NULL
)
486 XtRemoveCallback((Widget
) ctx
, XtNunrealizeCallback
, UnrealizeScrollbars
,
488 XtDestroyWidget(hbar
);
489 ctx
->text
.hbar
= NULL
;
492 static void warn_msg (w
, dir
, desc
)
497 char* fmt
= "Xaw Text Widget \"%s\": %s scrolling not allowed with %s.\n%s scrolling has been DEACTIVATED.";
498 char error_buf
[BUFSIZ
];
502 if ((len
= strlen (fmt
) + strlen (w
->core
.name
) + 2 * strlen (dir
) + strlen (desc
)) < sizeof error_buf
)
505 errorp
= XtMalloc (len
+ 1);
507 if (errorp
== NULL
) {
509 strcpy (errorp
, "Scrolling has been DEACTIVATED");
511 (void) sprintf (errorp
, fmt
, w
->core
.name
, dir
, desc
, dir
);
512 XtAppWarning (XtWidgetToApplicationContext (w
), errorp
);
517 Initialize(request
, new, args
, num_args
)
519 ArgList args
; /* unused */
520 Cardinal
*num_args
; /* unused */
522 TextWidget ctx
= (TextWidget
) new;
523 char* Horizontal
= "Horizontal";
525 ctx
->text
.lt
.lines
= 0;
526 ctx
->text
.lt
.info
= NULL
;
527 (void) bzero((char *) &(ctx
->text
.origSel
), sizeof(XawTextSelection
));
528 (void) bzero((char *) &(ctx
->text
.s
), sizeof(XawTextSelection
));
529 ctx
->text
.s
.type
= XawselectPosition
;
530 ctx
->text
.salt
= NULL
;
531 ctx
->text
.hbar
= ctx
->text
.vbar
= (Widget
) NULL
;
532 ctx
->text
.lasttime
= 0; /* ||| correct? */
533 ctx
->text
.time
= 0; /* ||| correct? */
534 ctx
->text
.showposition
= TRUE
;
535 ctx
->text
.lastPos
= (ctx
->text
.source
!= NULL
) ? GETLASTPOS
: 0;
536 ctx
->text
.file_insert
= NULL
;
537 ctx
->text
.search
= NULL
;
538 ctx
->text
.updateFrom
= (XawTextPosition
*) XtMalloc((unsigned) ONE
);
539 ctx
->text
.updateTo
= (XawTextPosition
*) XtMalloc((unsigned) ONE
);
540 ctx
->text
.numranges
= ctx
->text
.maxranges
= 0;
541 ctx
->text
.gc
= DefaultGCOfScreen(XtScreen(ctx
));
542 ctx
->text
.hasfocus
= FALSE
;
543 ctx
->text
.margin
= ctx
->text
.r_margin
; /* Strucure copy. */
544 ctx
->text
.update_disabled
= FALSE
;
545 ctx
->text
.old_insert
= -1;
547 ctx
->text
.single_char
= FALSE
;
548 ctx
->text
.copy_area_offsets
= NULL
;
549 ctx
->text
.salt2
= NULL
;
551 if (ctx
->core
.height
== DEFAULT_TEXT_HEIGHT
) {
552 ctx
->core
.height
= VMargins(ctx
);
553 if (ctx
->text
.sink
!= NULL
)
554 ctx
->core
.height
+= XawTextSinkMaxHeight(ctx
->text
.sink
, 1);
557 if (ctx
->text
.scroll_vert
!= XawtextScrollNever
)
558 if ( (ctx
->text
.resize
== XawtextResizeHeight
) ||
559 (ctx
->text
.resize
== XawtextResizeBoth
) ) {
560 warn_msg (ctx
, "Vertical", "height resize");
561 ctx
->text
.scroll_vert
= XawtextScrollNever
;
563 else if (ctx
->text
.scroll_vert
== XawtextScrollAlways
)
564 CreateVScrollBar(ctx
);
566 if (ctx
->text
.scroll_horiz
!= XawtextScrollNever
)
567 if (ctx
->text
.wrap
!= XawtextWrapNever
) {
568 warn_msg (ctx
, Horizontal
, "wrapping active");
569 ctx
->text
.scroll_horiz
= XawtextScrollNever
;
571 else if ( (ctx
->text
.resize
== XawtextResizeWidth
) ||
572 (ctx
->text
.resize
== XawtextResizeBoth
) ) {
573 warn_msg (ctx
, Horizontal
, "width resize");
574 ctx
->text
.scroll_horiz
= XawtextScrollNever
;
576 else if (ctx
->text
.scroll_horiz
== XawtextScrollAlways
)
577 CreateHScrollBar(ctx
);
581 Realize( w
, valueMask
, attributes
)
584 XSetWindowAttributes
*attributes
;
586 TextWidget ctx
= (TextWidget
)w
;
587 void _XawTextCheckResize();
589 (*textClassRec
.core_class
.superclass
->core_class
.realize
)
590 (w
, valueMask
, attributes
);
592 if (ctx
->text
.hbar
!= NULL
) { /* Put up Hbar -- Must be first. */
593 XtRealizeWidget(ctx
->text
.hbar
);
594 XtMapWidget(ctx
->text
.hbar
);
597 if (ctx
->text
.vbar
!= NULL
) { /* Put up Vbar. */
598 XtRealizeWidget(ctx
->text
.vbar
);
599 XtMapWidget(ctx
->text
.vbar
);
602 _XawTextBuildLineTable(ctx
, ctx
->text
.lt
.top
, TRUE
);
603 _XawTextSetScrollBars(ctx
);
604 _XawTextCheckResize(ctx
);
608 static void UnrealizeScrollbars(widget
, client
, call
)
609 Widget widget
; /* Text widget */
610 XtPointer client
; /* unused */
611 XtPointer call
; /* unused */
613 TextWidget ctx
= (TextWidget
) widget
;
616 XtUnrealizeWidget(ctx
->text
.hbar
);
618 XtUnrealizeWidget(ctx
->text
.vbar
);
621 /* Utility routines for support of Text */
627 static struct _DisplayRec
{
628 struct _DisplayRec
*next
;
631 struct _DisplayRec
*dpy_ptr
;
633 for (dpy_ptr
= dpy_list
; dpy_ptr
!= NULL
; dpy_ptr
= dpy_ptr
->next
)
634 if (dpy_ptr
->dpy
== d
) return;
636 dpy_ptr
= XtNew(struct _DisplayRec
);
637 dpy_ptr
->next
= dpy_list
;
641 #define Create(buffer) \
642 XChangeProperty(d, RootWindow(d, 0), buffer, XA_STRING, 8, \
643 PropModeAppend, NULL, 0 );
645 Create( XA_CUT_BUFFER0
);
646 Create( XA_CUT_BUFFER1
);
647 Create( XA_CUT_BUFFER2
);
648 Create( XA_CUT_BUFFER3
);
649 Create( XA_CUT_BUFFER4
);
650 Create( XA_CUT_BUFFER5
);
651 Create( XA_CUT_BUFFER6
);
652 Create( XA_CUT_BUFFER7
);
658 * Procedure to manage insert cursor visibility for editable text. It uses
659 * the value of ctx->insertPos and an implicit argument. In the event that
660 * position is immediately preceded by an eol graphic, then the insert cursor
661 * is displayed at the beginning of the next line.
664 InsertCursor (w
, state
)
666 XawTextInsertState state
;
668 TextWidget ctx
= (TextWidget
)w
;
672 if (ctx
->text
.lt
.lines
< 1) return;
674 if ( LineAndXYForPosition(ctx
, ctx
->text
.insertPos
, &line
, &x
, &y
) ) {
675 if (line
< ctx
->text
.lt
.lines
)
676 y
+= (ctx
->text
.lt
.info
[line
+ 1].y
- ctx
->text
.lt
.info
[line
].y
) + 1;
678 y
+= (ctx
->text
.lt
.info
[line
].y
- ctx
->text
.lt
.info
[line
- 1].y
) + 1;
680 if (ctx
->text
.display_caret
)
681 XawTextSinkInsertCursor(ctx
->text
.sink
, x
, y
, state
);
686 /* Keep Input Method up to speed */
688 if ( ctx
->simple
.international
) {
691 XtSetArg (list
[0], XtNinsertPosition
, ctx
->text
.insertPos
);
692 _XawImSetValues (w
, list
, 1);
697 * Procedure to register a span of text that is no longer valid on the display
698 * It is used to avoid a number of small, and potentially overlapping, screen
703 _XawTextNeedsUpdating(ctx
, left
, right
)
705 XawTextPosition left
, right
;
710 for (i
= 0; i
< ctx
->text
.numranges
; i
++) {
711 if (left
<= ctx
->text
.updateTo
[i
] && right
>= ctx
->text
.updateFrom
[i
]) {
712 ctx
->text
.updateFrom
[i
] = Min(left
, ctx
->text
.updateFrom
[i
]);
713 ctx
->text
.updateTo
[i
] = Max(right
, ctx
->text
.updateTo
[i
]);
717 ctx
->text
.numranges
++;
718 if (ctx
->text
.numranges
> ctx
->text
.maxranges
) {
719 ctx
->text
.maxranges
= ctx
->text
.numranges
;
720 len
= ctx
->text
.maxranges
* sizeof(XawTextPosition
);
721 ctx
->text
.updateFrom
= (XawTextPosition
*)
722 XtRealloc((char *)ctx
->text
.updateFrom
, (unsigned) len
);
723 ctx
->text
.updateTo
= (XawTextPosition
*)
724 XtRealloc((char *)ctx
->text
.updateTo
, (unsigned) len
);
726 ctx
->text
.updateFrom
[ctx
->text
.numranges
- 1] = left
;
727 ctx
->text
.updateTo
[ctx
->text
.numranges
- 1] = right
;
732 * Procedure to read a span of text in Ascii form. This is purely a hack and
733 * we probably need to add a function to sources to provide this functionality.
734 * [note: this is really a private procedure but is used in multiple modules].
738 _XawTextGetText(ctx
, left
, right
)
740 XawTextPosition left
, right
;
742 char *result
, *tempResult
;
746 if (_XawTextFormat(ctx
) == (int)XawFmt8Bit
)
747 bytes
= sizeof(unsigned char);
748 else if (_XawTextFormat(ctx
) == (int)XawFmtWide
)
749 bytes
= sizeof(wchar_t);
750 else /* if there is another fomat, add here */
753 /* leave space for ZERO */
754 tempResult
=result
=XtMalloc( (unsigned)(((Cardinal
)(right
-left
))+ONE
)* bytes
);
755 while (left
< right
) {
756 left
= SrcRead(ctx
->text
.source
, left
, &text
, (int)(right
- left
));
759 memmove(tempResult
, text
.ptr
, text
.length
* bytes
);
760 tempResult
+= text
.length
* bytes
;
763 if (bytes
== sizeof(wchar_t))
764 *((wchar_t*)tempResult
) = (wchar_t)0;
770 /* Like _XawTextGetText, but enforces ICCCM STRING type encoding. This
771 routine is currently used to put just the ASCII chars in the selection into a
775 _XawTextGetSTRING(ctx
, left
, right
)
777 XawTextPosition left
, right
;
784 /* allow ESC in accordance with ICCCM */
785 if (_XawTextFormat(ctx
) == (int)XawFmtWide
) {
786 MultiSinkObject sink
= (MultiSinkObject
) ctx
->text
.sink
;
787 ws
= (wchar_t *)_XawTextGetText(ctx
, left
, right
);
789 for (j
= 0, i
= 0; j
< n
; j
++) {
791 if (XwcTextEscapement (sink
->multi_sink
.fontset
, &wc
, 1) ||
792 (wc
== _Xaw_atowc(XawTAB
)) || (wc
== _Xaw_atowc(XawLF
)) || (wc
== _Xaw_atowc(XawESC
)))
798 s
= (unsigned char *)_XawTextGetText(ctx
, left
, right
);
799 /* only HT and NL control chars are allowed, strip out others */
800 n
= strlen((char *)s
);
802 for (j
= 0; j
< n
; j
++) {
804 if (((c
>= 0x20) && c
<= 0x7f) ||
805 (c
>= 0xa0) || (c
== XawTAB
) || (c
== XawLF
) || (c
== XawESC
)) {
818 * This routine maps an x and y position in a window that is displaying text
819 * into the corresponding position in the source.
821 * NOTE: it is illegal to call this routine unless there is a valid line table!
824 /*** figure out what line it is on ***/
826 static XawTextPosition
827 PositionForXY (ctx
, x
, y
)
831 int fromx
, line
, width
, height
;
832 XawTextPosition position
;
834 if (ctx
->text
.lt
.lines
== 0) return 0;
836 for (line
= 0; line
< ctx
->text
.lt
.lines
- 1; line
++) {
837 if (y
<= ctx
->text
.lt
.info
[line
+ 1].y
)
840 position
= ctx
->text
.lt
.info
[line
].position
;
841 if (position
>= ctx
->text
.lastPos
)
842 return(ctx
->text
.lastPos
);
843 fromx
= (int) ctx
->text
.margin
.left
;
844 XawTextSinkFindPosition( ctx
->text
.sink
, position
, fromx
, x
- fromx
,
845 FALSE
, &position
, &width
, &height
);
846 if (position
> ctx
->text
.lastPos
) return(ctx
->text
.lastPos
);
847 if (position
>= ctx
->text
.lt
.info
[line
+ 1].position
)
848 position
= SrcScan(ctx
->text
.source
, ctx
->text
.lt
.info
[line
+ 1].position
,
849 XawstPositions
, XawsdLeft
, 1, TRUE
);
854 * This routine maps a source position in to the corresponding line number
855 * of the text that is displayed in the window.
857 * NOTE: It is illegal to call this routine unless there is a valid line table!
861 LineForPosition (ctx
, position
)
863 XawTextPosition position
;
867 for (line
= 0; line
< ctx
->text
.lt
.lines
; line
++)
868 if (position
< ctx
->text
.lt
.info
[line
+ 1].position
)
874 * This routine maps a source position into the corresponding line number
875 * and the x, y coordinates of the text that is displayed in the window.
877 * NOTE: It is illegal to call this routine unless there is a valid line table!
881 LineAndXYForPosition (ctx
, pos
, line
, x
, y
)
887 XawTextPosition linePos
, endPos
;
892 *x
= ctx
->text
.margin
.left
;
893 *y
= ctx
->text
.margin
.top
;
894 if (visible
= IsPositionVisible(ctx
, pos
)) {
895 *line
= LineForPosition(ctx
, pos
);
896 *y
= ctx
->text
.lt
.info
[*line
].y
;
897 *x
= ctx
->text
.margin
.left
;
898 linePos
= ctx
->text
.lt
.info
[*line
].position
;
899 XawTextSinkFindDistance( ctx
->text
.sink
, linePos
,
900 *x
, pos
, &realW
, &endPos
, &realH
);
907 * This routine builds a line table. It does this by starting at the
908 * specified position and measuring text to determine the staring position
909 * of each line to be displayed. It also determines and saves in the
910 * linetable all the required metrics for displaying a given line (e.g.
911 * x offset, y offset, line length, etc.).
915 #if NeedFunctionPrototypes
916 _XawTextBuildLineTable (
918 XawTextPosition position
,
919 _XtBoolean force_rebuild
)
921 _XawTextBuildLineTable (ctx
, position
, force_rebuild
)
923 XawTextPosition position
;
924 Boolean force_rebuild
;
927 Dimension height
= 0;
931 if ((int)ctx
->core
.height
> VMargins(ctx
)) {
932 height
= ctx
->core
.height
- VMargins(ctx
);
933 lines
= XawTextSinkMaxLines(ctx
->text
.sink
, height
);
935 size
= sizeof(XawTextLineTableEntry
) * (lines
+ 1);
937 if ( (lines
!= ctx
->text
.lt
.lines
) || (ctx
->text
.lt
.info
== NULL
) ) {
938 ctx
->text
.lt
.info
= (XawTextLineTableEntry
*) XtRealloc((char *) ctx
->text
.
940 ctx
->text
.lt
.lines
= lines
;
941 force_rebuild
= TRUE
;
944 if ( force_rebuild
|| (position
!= ctx
->text
.lt
.top
) ) {
945 (void) bzero((char *) ctx
->text
.lt
.info
, size
);
946 (void) _BuildLineTable(ctx
, ctx
->text
.lt
.top
= position
, zeroPosition
, 0);
951 * This assumes that the line table does not change size.
954 static XawTextPosition
955 _BuildLineTable(ctx
, position
, min_pos
, line
)
957 XawTextPosition position
, min_pos
;
960 XawTextLineTableEntry
* lt
= ctx
->text
.lt
.info
+ line
;
961 XawTextPosition endPos
;
963 int count
, width
, realW
, realH
;
964 Widget src
= ctx
->text
.source
;
966 if ( ((ctx
->text
.resize
== XawtextResizeWidth
) ||
967 (ctx
->text
.resize
== XawtextResizeBoth
) ) ||
968 (ctx
->text
.wrap
== XawtextWrapNever
) )
971 width
= Max(0, ((int)ctx
->core
.width
- (int)HMargins(ctx
)));
973 y
= ( (line
== 0) ? ctx
->text
.margin
.top
: lt
->y
);
978 lt
->position
= position
;
980 XawTextSinkFindPosition( ctx
->text
.sink
, position
, ctx
->text
.margin
.left
,
981 width
, ctx
->text
.wrap
== XawtextWrapWord
,
982 &endPos
, &realW
, &realH
);
983 lt
->textWidth
= realW
;
986 if (ctx
->text
.wrap
== XawtextWrapNever
)
987 endPos
= SrcScan(src
, position
, XawstEOL
, XawsdRight
, 1, TRUE
);
989 if ( endPos
== ctx
->text
.lastPos
) { /* We have reached the end. */
990 if(SrcScan(src
, position
, XawstEOL
, XawsdRight
, 1, FALSE
) == endPos
)
996 if ( (line
> ctx
->text
.lt
.lines
) ||
997 ((lt
->position
== (position
= endPos
)) && (position
> min_pos
)) )
1002 * If we are at the end of the buffer put two special lines in the table.
1004 * a) Both have position > text.lastPos and lt->textWidth = 0.
1005 * b) The first has a real height, and the second has a height that
1006 * is the rest of the screen.
1008 * I could fill in the rest of the table with valid heights and a large
1009 * lastPos, but this method keeps the number of fill regions down to a
1012 * One valid entry is needed at the end of the table so that the cursor
1013 * does not jump off the bottom of the window.
1016 for ( count
= 0; count
< 2 ; count
++)
1017 if (line
++ < ctx
->text
.lt
.lines
) { /* make sure not to run of the end. */
1018 (++lt
)->y
= (count
== 0) ? y
: ctx
->core
.height
;
1020 lt
->position
= ctx
->text
.lastPos
+ 100;
1023 if (line
< ctx
->text
.lt
.lines
) /* Clear out rest of table. */
1024 (void) bzero( (char *) (lt
+ 1),
1025 (ctx
->text
.lt
.lines
- line
) * sizeof(XawTextLineTableEntry
) );
1027 ctx
->text
.lt
.info
[ctx
->text
.lt
.lines
].position
= lt
->position
;
1032 /* Function Name: GetWidestLine
1033 * Description: Returns the width (in pixels) of the widest line that
1034 * is currently visable.
1035 * Arguments: ctx - the text widget.
1036 * Returns: the width of the widest line.
1038 * NOTE: This function requires a valid line table.
1047 XawTextLineTablePtr lt
= &(ctx
->text
.lt
);
1049 for (i
= 0, widest
= 1 ; i
< lt
->lines
; i
++)
1050 if (widest
< lt
->info
[i
].textWidth
)
1051 widest
= lt
->info
[i
].textWidth
;
1057 CheckVBarScrolling(ctx
)
1061 Boolean temp
= (ctx
->text
.vbar
== NULL
);
1063 if (ctx
->text
.scroll_vert
== XawtextScrollNever
) return;
1065 if ( (ctx
->text
.lastPos
> 0) && (ctx
->text
.lt
.lines
> 0)) {
1066 first
= ctx
->text
.lt
.top
;
1067 first
/= (float) ctx
->text
.lastPos
;
1068 last
= ctx
->text
.lt
.info
[ctx
->text
.lt
.lines
].position
;
1069 if ( ctx
->text
.lt
.info
[ctx
->text
.lt
.lines
].position
< ctx
->text
.lastPos
)
1070 last
/= (float) ctx
->text
.lastPos
;
1074 if (ctx
->text
.scroll_vert
== XawtextScrollWhenNeeded
) {
1076 XawTextPosition last_pos
;
1077 Position y
= ctx
->core
.height
- ctx
->text
.margin
.bottom
;
1079 if (ctx
->text
.hbar
!= NULL
)
1080 y
-= (ctx
->text
.hbar
->core
.height
+
1081 2 * ctx
->text
.hbar
->core
.border_width
);
1083 last_pos
= PositionForXY(ctx
, (Position
) ctx
->core
.width
, y
);
1084 line
= LineForPosition(ctx
, last_pos
);
1086 if ( (y
< ctx
->text
.lt
.info
[line
+ 1].y
) || ((last
- first
) < 1.0) )
1087 CreateVScrollBar(ctx
);
1089 DestroyVScrollBar(ctx
);
1092 if (ctx
->text
.vbar
!= NULL
)
1093 XawScrollbarSetThumb(ctx
->text
.vbar
, first
, last
- first
);
1095 if ( (ctx
->text
.vbar
== NULL
) != temp
) {
1096 _XawTextNeedsUpdating(ctx
, zeroPosition
, ctx
->text
.lastPos
);
1097 if (ctx
->text
.vbar
== NULL
)
1098 _XawTextBuildLineTable (ctx
, zeroPosition
, FALSE
);
1101 else if (ctx
->text
.vbar
!= NULL
)
1102 if (ctx
->text
.scroll_vert
== XawtextScrollWhenNeeded
)
1103 DestroyVScrollBar(ctx
);
1104 else if (ctx
->text
.scroll_vert
== XawtextScrollAlways
)
1105 XawScrollbarSetThumb(ctx
->text
.vbar
, 0.0, 1.0);
1109 * This routine is used by Text to notify an associated scrollbar of the
1110 * correct metrics (position and shown fraction) for the text being currently
1111 * displayed in the window.
1115 _XawTextSetScrollBars(ctx
)
1118 float first
, last
, widest
;
1119 Boolean temp
= (ctx
->text
.hbar
== NULL
);
1120 Boolean vtemp
= (ctx
->text
.vbar
== NULL
);
1122 CheckVBarScrolling(ctx
);
1124 if (ctx
->text
.scroll_horiz
== XawtextScrollNever
) return;
1126 if (ctx
->text
.vbar
!= NULL
)
1127 widest
= (int)(ctx
->core
.width
- ctx
->text
.vbar
->core
.width
-
1128 ctx
->text
.vbar
->core
.border_width
);
1130 widest
= ctx
->core
.width
;
1131 widest
/= (last
= GetWidestLine(ctx
));
1132 if (ctx
->text
.scroll_horiz
== XawtextScrollWhenNeeded
)
1134 CreateHScrollBar(ctx
);
1136 DestroyHScrollBar(ctx
);
1138 if ( (ctx
->text
.hbar
== NULL
) != temp
) {
1139 _XawTextBuildLineTable (ctx
, ctx
->text
.lt
.top
, TRUE
);
1140 CheckVBarScrolling(ctx
); /* Recheck need for vbar, now that we added
1141 or removed the hbar.*/
1144 if (ctx
->text
.hbar
!= NULL
) {
1145 first
= ctx
->text
.r_margin
.left
- ctx
->text
.margin
.left
;
1147 XawScrollbarSetThumb(ctx
->text
.hbar
, first
, widest
);
1150 if (((ctx
->text
.hbar
== NULL
) && (ctx
->text
.margin
.left
!=
1151 ctx
->text
.r_margin
.left
)) ||
1152 (ctx
->text
.vbar
== NULL
) != vtemp
)
1154 ctx
->text
.margin
.left
= ctx
->text
.r_margin
.left
;
1155 _XawTextNeedsUpdating(ctx
, zeroPosition
, ctx
->text
.lastPos
);
1161 * The routine will scroll the displayed text by lines. If the arg is
1162 * positive, move up; otherwise, move down. [note: this is really a private
1163 * procedure but is used in multiple modules].
1167 _XawTextVScroll(ctx
, n
)
1171 XawTextPosition top
, target
;
1174 XawTextLineTable
* lt
= &(ctx
->text
.lt
);
1176 if (abs(n
) > ctx
->text
.lt
.lines
)
1177 n
= (n
> 0) ? ctx
->text
.lt
.lines
: -ctx
->text
.lt
.lines
;
1182 if ( IsValidLine(ctx
, n
) )
1183 top
= Min(lt
->info
[n
].position
, ctx
->text
.lastPos
);
1185 top
= ctx
->text
.lastPos
;
1187 y
= IsValidLine(ctx
, n
) ? lt
->info
[n
].y
: ctx
->core
.height
;
1188 _XawTextBuildLineTable(ctx
, top
, FALSE
);
1189 if (top
>= ctx
->text
.lastPos
)
1190 DisplayTextWindow( (Widget
) ctx
);
1192 XCopyArea(XtDisplay(ctx
), XtWindow(ctx
), XtWindow(ctx
), ctx
->text
.gc
,
1193 0, y
, (int)ctx
->core
.width
, (int)ctx
->core
.height
- y
,
1194 0, ctx
->text
.margin
.top
);
1196 PushCopyQueue(ctx
, 0, (int) -y
);
1197 SinkClearToBG(ctx
->text
.sink
,
1199 (Position
) (ctx
->text
.margin
.top
+ ctx
->core
.height
- y
),
1200 (Dimension
) ctx
->core
.width
, (Dimension
) ctx
->core
.height
);
1202 if (n
< lt
->lines
) n
++; /* update descenders at bottom */
1203 _XawTextNeedsUpdating(ctx
, lt
->info
[lt
->lines
- n
].position
,
1205 _XawTextSetScrollBars(ctx
);
1209 XawTextPosition updateTo
;
1210 unsigned int height
, clear_height
;
1214 top
= SrcScan(ctx
->text
.source
, target
, XawstEOL
,
1215 XawsdLeft
, n
+1, FALSE
);
1217 _XawTextBuildLineTable(ctx
, top
, FALSE
);
1218 y
= IsValidLine(ctx
, n
) ? lt
->info
[n
].y
: ctx
->core
.height
;
1219 updateTo
= IsValidLine(ctx
, n
) ? lt
->info
[n
].position
: ctx
->text
.lastPos
;
1220 if (IsValidLine(ctx
, lt
->lines
- n
))
1221 height
= lt
->info
[lt
->lines
-n
].y
- ctx
->text
.margin
.top
;
1222 else if (ctx
->core
.height
- HMargins(ctx
))
1223 height
= ctx
->core
.height
- HMargins(ctx
);
1226 if (y
> (int) ctx
->text
.margin
.top
)
1227 clear_height
= y
- ctx
->text
.margin
.top
;
1231 if ( updateTo
== target
) {
1232 XCopyArea(XtDisplay(ctx
), XtWindow(ctx
), XtWindow(ctx
), ctx
->text
.gc
,
1233 0, ctx
->text
.margin
.top
, (int) ctx
->core
.width
, height
, 0, y
);
1234 PushCopyQueue(ctx
, 0, (int) y
);
1235 SinkClearToBG(ctx
->text
.sink
, (Position
) 0, ctx
->text
.margin
.top
,
1236 (Dimension
) ctx
->core
.width
, (Dimension
) clear_height
);
1238 _XawTextNeedsUpdating(ctx
, lt
->info
[0].position
, updateTo
);
1239 _XawTextSetScrollBars(ctx
);
1241 else if (lt
->top
!= target
)
1242 DisplayTextWindow((Widget
)ctx
);
1244 XtSetArg (list
[0], XtNinsertPosition
, ctx
->text
.lt
.top
+ctx
->text
.lt
.lines
);
1245 _XawImSetValues ((Widget
) ctx
, list
, 1);
1250 HScroll(w
, closure
, callData
)
1252 XtPointer closure
; /* TextWidget */
1253 XtPointer callData
; /* #pixels */
1255 TextWidget ctx
= (TextWidget
) closure
;
1256 Widget tw
= (Widget
) ctx
;
1257 Position old_left
, pixels
= (Position
)(int) callData
;
1258 XRectangle rect
, t_rect
;
1260 _XawTextPrepareToUpdate(ctx
);
1262 old_left
= ctx
->text
.margin
.left
;
1263 ctx
->text
.margin
.left
-= pixels
;
1264 if (ctx
->text
.margin
.left
> ctx
->text
.r_margin
.left
) {
1265 ctx
->text
.margin
.left
= ctx
->text
.r_margin
.left
;
1266 pixels
= old_left
- ctx
->text
.margin
.left
;
1270 rect
.width
= (unsigned short) pixels
+ ctx
->text
.margin
.right
;
1271 rect
.x
= (short) ctx
->core
.width
- (short) rect
.width
;
1272 rect
.y
= (short) ctx
->text
.margin
.top
;
1273 rect
.height
= (unsigned short) ctx
->core
.height
- rect
.y
;
1275 XCopyArea(XtDisplay(tw
), XtWindow(tw
), XtWindow(tw
), ctx
->text
.gc
,
1276 pixels
, (int) rect
.y
,
1277 (unsigned int) rect
.x
, (unsigned int) ctx
->core
.height
,
1280 PushCopyQueue(ctx
, (int) -pixels
, 0);
1282 else if (pixels
< 0) {
1285 if (ctx
->text
.vbar
!= NULL
)
1286 rect
.x
+= (short) (ctx
->text
.vbar
->core
.width
+
1287 ctx
->text
.vbar
->core
.border_width
);
1289 rect
.width
= (Position
) - pixels
;
1290 rect
.y
= ctx
->text
.margin
.top
;
1291 rect
.height
= ctx
->core
.height
- rect
.y
;
1293 XCopyArea(XtDisplay(tw
), XtWindow(tw
), XtWindow(tw
), ctx
->text
.gc
,
1294 (int) rect
.x
, (int) rect
.y
,
1295 (unsigned int) ctx
->core
.width
- rect
.width
,
1296 (unsigned int) rect
.height
,
1297 (int) rect
.x
+ rect
.width
, (int) rect
.y
);
1299 PushCopyQueue(ctx
, (int) rect
.width
, 0);
1302 * Redraw the line overflow marks.
1305 t_rect
.x
= ctx
->core
.width
- ctx
->text
.margin
.right
;
1306 t_rect
.width
= ctx
->text
.margin
.right
;
1308 t_rect
.height
= rect
.height
;
1310 SinkClearToBG(ctx
->text
.sink
, (Position
) t_rect
.x
, (Position
) t_rect
.y
,
1311 (Dimension
) t_rect
.width
, (Dimension
) t_rect
.height
);
1313 UpdateTextInRectangle(ctx
, &t_rect
);
1317 * Put in the text that just became visible.
1320 if ( pixels
!= 0 ) {
1321 SinkClearToBG(ctx
->text
.sink
, (Position
) rect
.x
, (Position
) rect
.y
,
1322 (Dimension
) rect
.width
, (Dimension
) rect
.height
);
1324 UpdateTextInRectangle(ctx
, &rect
);
1326 _XawTextExecuteUpdate(ctx
);
1327 _XawTextSetScrollBars(ctx
);
1332 HJump(w
, closure
, callData
)
1334 XtPointer closure
, callData
; /* closure = TextWidget, callData = percent. */
1336 TextWidget ctx
= (TextWidget
) closure
;
1337 float * percent
= (float *) callData
;
1338 Position new_left
, old_left
= ctx
->text
.margin
.left
;
1340 long move
; /*difference of Positions can be bigger than Position; lint err */
1342 new_left
= ctx
->text
.r_margin
.left
;
1343 new_left
-= (Position
) (*percent
* GetWidestLine(ctx
));
1344 move
= old_left
- new_left
;
1346 if (labs(move
) < (int)ctx
->core
.width
) {
1347 HScroll(w
, (XtPointer
) ctx
, (XtPointer
) move
);
1350 _XawTextPrepareToUpdate(ctx
);
1351 ctx
->text
.margin
.left
= new_left
;
1352 if (XtIsRealized((Widget
) ctx
)) DisplayTextWindow((Widget
) ctx
);
1353 _XawTextExecuteUpdate(ctx
);
1356 /* Function Name: UpdateTextInLine
1357 * Description: Updates some text in a given line.
1358 * Arguments: ctx - the text widget.
1359 * line - the line number (in the line table) of this line.
1360 * left, right - left and right pixel offsets of the
1366 UpdateTextInLine(ctx
, line
, left
, right
)
1369 Position left
, right
;
1371 XawTextPosition pos1
, pos2
;
1372 int width
, height
, local_left
, local_width
;
1373 XawTextLineTableEntry
* lt
= ctx
->text
.lt
.info
+ line
;
1375 if ( ((int)(lt
->textWidth
+ ctx
->text
.margin
.left
) < left
) ||
1376 ( ctx
->text
.margin
.left
> right
) )
1377 return; /* no need to update. */
1379 local_width
= left
- ctx
->text
.margin
.left
;
1380 XawTextSinkFindPosition(ctx
->text
.sink
, lt
->position
,
1381 (int) ctx
->text
.margin
.left
,
1382 local_width
, FALSE
, &pos1
, &width
, &height
);
1384 if (right
>= (Position
) lt
->textWidth
- ctx
->text
.margin
.left
)
1385 if ( (IsValidLine(ctx
, line
+ 1)) &&
1386 (ctx
->text
.lt
.info
[line
+ 1].position
<= ctx
->text
.lastPos
) )
1387 pos2
= SrcScan( ctx
->text
.source
, (lt
+ 1)->position
, XawstPositions
,
1388 XawsdLeft
, 1, TRUE
);
1392 XawTextPosition t_pos
;
1394 local_left
= ctx
->text
.margin
.left
+ width
;
1395 local_width
= right
- local_left
;
1396 XawTextSinkFindPosition(ctx
->text
.sink
, pos1
, local_left
,
1397 local_width
, FALSE
, &pos2
, &width
, &height
);
1399 t_pos
= SrcScan( ctx
->text
.source
, pos2
,
1400 XawstPositions
, XawsdRight
, 1, TRUE
);
1401 if (t_pos
< (lt
+ 1)->position
)
1405 _XawTextNeedsUpdating(ctx
, pos1
, pos2
);
1409 * The routine will scroll the displayed text by pixels. If the calldata is
1410 * positive, move up; otherwise, move down.
1415 VScroll(w
, closure
, callData
)
1417 XtPointer closure
; /* TextWidget */
1418 XtPointer callData
; /* #pixels */
1420 TextWidget ctx
= (TextWidget
)closure
;
1421 int height
, lines
= (int) callData
;
1423 height
= ctx
->core
.height
- VMargins(ctx
);
1426 lines
= (int) (lines
* (int) ctx
->text
.lt
.lines
) / height
;
1427 _XawTextPrepareToUpdate(ctx
);
1428 _XawTextVScroll(ctx
, lines
);
1429 _XawTextExecuteUpdate(ctx
);
1433 * The routine "thumbs" the displayed text. Thumbing means reposition the
1434 * displayed view of the source to a new position determined by a fraction
1435 * of the way from beginning to end. Ideally, this should be determined by
1436 * the number of displayable lines in the source. This routine does it as a
1437 * fraction of the first position and last position and then normalizes to
1438 * the start of the line containing the position.
1440 * BUG/deficiency: The normalize to line portion of this routine will
1441 * cause thumbing to always position to the start of the source.
1446 VJump(w
, closure
, callData
)
1448 XtPointer closure
, callData
; /* closuer = TextWidget, callData = percent. */
1450 float * percent
= (float *) callData
;
1451 TextWidget ctx
= (TextWidget
)closure
;
1452 XawTextPosition position
, old_top
, old_bot
;
1453 XawTextLineTable
* lt
= &(ctx
->text
.lt
);
1455 _XawTextPrepareToUpdate(ctx
);
1457 if ( (lt
->lines
> 0) && (IsValidLine(ctx
, lt
->lines
- 1)) )
1458 old_bot
= lt
->info
[lt
->lines
- 1].position
;
1460 old_bot
= ctx
->text
.lastPos
;
1462 position
= (long) (*percent
* (float) ctx
->text
.lastPos
);
1463 position
= SrcScan(ctx
->text
.source
, position
, XawstEOL
, XawsdLeft
, 1, FALSE
);
1464 if ( (position
>= old_top
) && (position
<= old_bot
) ) {
1466 for (;(line
< lt
->lines
) && (position
> lt
->info
[line
].position
) ; line
++);
1467 _XawTextVScroll(ctx
, line
);
1470 XawTextPosition new_bot
;
1471 _XawTextBuildLineTable(ctx
, position
, FALSE
);
1472 new_bot
= IsValidLine(ctx
, lt
->lines
-1) ? lt
->info
[lt
->lines
-1].position
1473 : ctx
->text
.lastPos
;
1475 if ((old_top
>= lt
->top
) && (old_top
<= new_bot
)) {
1477 for (;(line
< lt
->lines
) && (old_top
> lt
->info
[line
].position
); line
++);
1478 _XawTextBuildLineTable(ctx
, old_top
, FALSE
);
1479 _XawTextVScroll(ctx
, -line
);
1482 DisplayTextWindow( (Widget
) ctx
);
1484 _XawTextExecuteUpdate(ctx
);
1488 MatchSelection(selection
, s
)
1490 XawTextSelection
*s
;
1495 for (count
= 0, match
= s
->selections
; count
< s
->atom_count
; match
++, count
++)
1496 if (*match
== selection
)
1502 ConvertSelection(w
, selection
, target
, type
, value
, length
, format
)
1504 Atom
*selection
, *target
, *type
;
1506 unsigned long *length
;
1509 Display
* d
= XtDisplay(w
);
1510 TextWidget ctx
= (TextWidget
)w
;
1511 Widget src
= ctx
->text
.source
;
1512 XawTextEditType edit_mode
;
1515 XawTextSelectionSalt
*salt
= NULL
;
1516 XawTextSelection
*s
;
1518 if (*target
== XA_TARGETS(d
)) {
1519 Atom
* targetP
, * std_targets
;
1520 unsigned long std_length
;
1522 if ( SrcCvtSel(src
, selection
, target
, type
, value
, length
, format
) )
1525 XmuConvertStandardSelection(w
, ctx
->text
.time
, selection
,
1526 target
, type
, (XPointer
*)&std_targets
,
1527 &std_length
, format
);
1529 *value
= XtMalloc((unsigned) sizeof(Atom
)*(std_length
+ 7));
1530 targetP
= *(Atom
**)value
;
1531 *length
= std_length
+ 6;
1532 *targetP
++ = XA_STRING
;
1533 *targetP
++ = XA_TEXT(d
);
1534 *targetP
++ = XA_COMPOUND_TEXT(d
);
1535 *targetP
++ = XA_LENGTH(d
);
1536 *targetP
++ = XA_LIST_LENGTH(d
);
1537 *targetP
++ = XA_CHARACTER_POSITION(d
);
1539 XtSetArg(args
[0], XtNeditType
,&edit_mode
);
1540 XtGetValues(src
, args
, ONE
);
1542 if (edit_mode
== XawtextEdit
) {
1543 *targetP
++ = XA_DELETE(d
);
1546 (void) memmove((char*)targetP
, (char*)std_targets
, sizeof(Atom
)*std_length
);
1547 XtFree((char*)std_targets
);
1553 if ( SrcCvtSel(src
, selection
, target
, type
, value
, length
, format
) )
1556 if (MatchSelection (*selection
, &ctx
->text
.s
))
1560 for (salt
= ctx
->text
.salt
; salt
; salt
= salt
->next
)
1561 if (MatchSelection (*selection
, &salt
->s
))
1567 if (*target
== XA_STRING
||
1568 *target
== XA_TEXT(d
) ||
1569 *target
== XA_COMPOUND_TEXT(d
)) {
1570 if (*target
== XA_TEXT(d
)) {
1571 if (_XawTextFormat(ctx
) == (int)XawFmtWide
)
1572 *type
= XA_COMPOUND_TEXT(d
);
1579 * If salt is True, the salt->contents stores CT string,
1580 * its length is measured in bytes.
1581 * Refer to _XawTextSaltAwaySelection().
1583 * by Li Yuhong, Mar. 20, 1991.
1586 *value
= _XawTextGetSTRING(ctx
, s
->left
, s
->right
);
1587 if (_XawTextFormat(ctx
) == (int)XawFmtWide
) {
1588 XTextProperty textprop
;
1589 if (XwcTextListToTextProperty(d
, (wchar_t **)value
, 1,
1590 XCompoundTextStyle
, &textprop
)
1596 *value
= (XtPointer
)textprop
.value
;
1597 *length
= textprop
.nitems
;
1599 *length
= strlen(*value
);
1602 *value
= XtMalloc((salt
->length
+ 1) * sizeof(unsigned char));
1603 strcpy (*value
, salt
->contents
);
1604 *length
= salt
->length
;
1606 if (_XawTextFormat(ctx
) == (int)XawFmtWide
&& *type
== XA_STRING
) {
1607 XTextProperty textprop
;
1610 textprop
.encoding
= XA_COMPOUND_TEXT(d
);
1611 textprop
.value
= (unsigned char *)*value
;
1612 textprop
.nitems
= strlen(*value
);
1613 textprop
.format
= 8;
1614 if (XwcTextPropertyToTextList(d
, &textprop
, (wchar_t ***)&wlist
, &count
)
1620 if (XwcTextListToTextProperty( d
, (wchar_t **)wlist
, 1,
1621 XStringStyle
, &textprop
) < Success
) {
1622 XwcFreeStringList( (wchar_t**) wlist
);
1625 *value
= (XtPointer
) textprop
.value
;
1626 *length
= textprop
.nitems
;
1627 XwcFreeStringList( (wchar_t**) wlist
);
1633 if ( (*target
== XA_LIST_LENGTH(d
)) || (*target
== XA_LENGTH(d
)) ) {
1636 temp
= (long *) XtMalloc( (unsigned) sizeof(long) );
1637 if (*target
== XA_LIST_LENGTH(d
))
1639 else /* *target == XA_LENGTH(d) */
1640 *temp
= (long) (s
->right
- s
->left
);
1642 *value
= (XPointer
) temp
;
1649 if (*target
== XA_CHARACTER_POSITION(d
)) {
1652 temp
= (long *) XtMalloc( (unsigned)( 2 * sizeof(long) ) );
1653 temp
[0] = (long) (s
->left
+ 1);
1655 *value
= (XPointer
) temp
;
1662 if (*target
== XA_DELETE(d
)) {
1663 void _XawTextZapSelection(); /* From TextAction.c */
1666 _XawTextZapSelection( ctx
, (XEvent
*) NULL
, TRUE
);
1674 if (XmuConvertStandardSelection(w
, ctx
->text
.time
, selection
, target
, type
,
1675 (XPointer
*)value
, length
, format
))
1682 /* Function Name: GetCutBuffferNumber
1683 * Description: Returns the number of the cut buffer.
1684 * Arguments: atom - the atom to check.
1685 * Returns: the number of the cut buffer representing this atom or
1689 #define NOT_A_CUT_BUFFER -1
1692 GetCutBufferNumber(atom
)
1695 if (atom
== XA_CUT_BUFFER0
) return(0);
1696 if (atom
== XA_CUT_BUFFER1
) return(1);
1697 if (atom
== XA_CUT_BUFFER2
) return(2);
1698 if (atom
== XA_CUT_BUFFER3
) return(3);
1699 if (atom
== XA_CUT_BUFFER4
) return(4);
1700 if (atom
== XA_CUT_BUFFER5
) return(5);
1701 if (atom
== XA_CUT_BUFFER6
) return(6);
1702 if (atom
== XA_CUT_BUFFER7
) return(7);
1703 return(NOT_A_CUT_BUFFER
);
1707 LoseSelection(w
, selection
)
1711 TextWidget ctx
= (TextWidget
) w
;
1714 XawTextSelectionSalt
*salt
, *prevSalt
, *nextSalt
;
1716 _XawTextPrepareToUpdate(ctx
);
1718 atomP
= ctx
->text
.s
.selections
;
1719 for (i
= 0 ; i
< ctx
->text
.s
.atom_count
; i
++, atomP
++)
1720 if ( (*selection
== *atomP
) ||
1721 (GetCutBufferNumber(*atomP
) != NOT_A_CUT_BUFFER
) )/* is a cut buffer */
1724 while (ctx
->text
.s
.atom_count
&&
1725 ctx
->text
.s
.selections
[ctx
->text
.s
.atom_count
-1] == 0)
1726 ctx
->text
.s
.atom_count
--;
1729 * Must walk the selection list in opposite order from UnsetSelection.
1732 atomP
= ctx
->text
.s
.selections
;
1733 for (i
= 0 ; i
< ctx
->text
.s
.atom_count
; i
++, atomP
++)
1734 if (*atomP
== (Atom
)0) {
1735 *atomP
= ctx
->text
.s
.selections
[--ctx
->text
.s
.atom_count
];
1736 while (ctx
->text
.s
.atom_count
&&
1737 ctx
->text
.s
.selections
[ctx
->text
.s
.atom_count
-1] == 0)
1738 ctx
->text
.s
.atom_count
--;
1741 if (ctx
->text
.s
.atom_count
== 0)
1742 ModifySelection(ctx
, ctx
->text
.insertPos
, ctx
->text
.insertPos
);
1744 if (ctx
->text
.old_insert
>= 0) /* Update in progress. */
1745 _XawTextExecuteUpdate(ctx
);
1748 for (salt
= ctx
->text
.salt
; salt
; salt
= nextSalt
)
1750 atomP
= salt
->s
.selections
;
1751 nextSalt
= salt
->next
;
1752 for (i
= 0 ; i
< salt
->s
.atom_count
; i
++, atomP
++)
1753 if (*selection
== *atomP
)
1756 while (salt
->s
.atom_count
&&
1757 salt
->s
.selections
[salt
->s
.atom_count
-1] == 0)
1759 salt
->s
.atom_count
--;
1763 * Must walk the selection list in opposite order from UnsetSelection.
1766 atomP
= salt
->s
.selections
;
1767 for (i
= 0 ; i
< salt
->s
.atom_count
; i
++, atomP
++)
1768 if (*atomP
== (Atom
)0)
1770 *atomP
= salt
->s
.selections
[--salt
->s
.atom_count
];
1771 while (salt
->s
.atom_count
&&
1772 salt
->s
.selections
[salt
->s
.atom_count
-1] == 0)
1773 salt
->s
.atom_count
--;
1775 if (salt
->s
.atom_count
== 0)
1777 XtFree ((char *) salt
->s
.selections
);
1778 XtFree (salt
->contents
);
1780 prevSalt
->next
= nextSalt
;
1782 ctx
->text
.salt
= nextSalt
;
1783 XtFree ((char *) salt
);
1791 _XawTextSaltAwaySelection (ctx
, selections
, num_atoms
)
1796 XawTextSelectionSalt
*salt
;
1799 for (i
= 0; i
< num_atoms
; i
++)
1800 LoseSelection ((Widget
) ctx
, selections
+ i
);
1803 salt
= (XawTextSelectionSalt
*)
1804 XtMalloc( (unsigned) sizeof(XawTextSelectionSalt
) );
1807 salt
->s
.selections
= (Atom
*)
1808 XtMalloc( (unsigned) ( num_atoms
* sizeof (Atom
) ) );
1809 if (!salt
->s
.selections
)
1811 XtFree ((char *) salt
);
1814 salt
->s
.left
= ctx
->text
.s
.left
;
1815 salt
->s
.right
= ctx
->text
.s
.right
;
1816 salt
->s
.type
= ctx
->text
.s
.type
;
1817 salt
->contents
= _XawTextGetSTRING(ctx
, ctx
->text
.s
.left
, ctx
->text
.s
.right
);
1818 if (_XawTextFormat(ctx
) == (int)XawFmtWide
) {
1819 XTextProperty textprop
;
1820 if (XwcTextListToTextProperty(XtDisplay((Widget
)ctx
),
1821 (wchar_t**)(&(salt
->contents
)), 1, XCompoundTextStyle
,
1822 &textprop
) < Success
) {
1823 XtFree(salt
->contents
);
1827 XtFree(salt
->contents
);
1828 salt
->contents
= (char *)textprop
.value
;
1829 salt
->length
= textprop
.nitems
;
1831 salt
->length
= strlen (salt
->contents
);
1832 salt
->next
= ctx
->text
.salt
;
1833 ctx
->text
.salt
= salt
;
1835 for (i
= 0; i
< num_atoms
; i
++)
1837 if (GetCutBufferNumber (selections
[i
]) == NOT_A_CUT_BUFFER
)
1839 salt
->s
.selections
[j
++] = selections
[i
];
1840 XtOwnSelection ((Widget
) ctx
, selections
[i
], ctx
->text
.time
,
1841 ConvertSelection
, LoseSelection
, (XtSelectionDoneProc
)NULL
);
1844 salt
->s
.atom_count
= j
;
1848 _SetSelection(ctx
, left
, right
, selections
, count
)
1850 XawTextPosition left
, right
;
1854 XawTextPosition pos
;
1856 if (left
< ctx
->text
.s
.left
) {
1857 pos
= Min(right
, ctx
->text
.s
.left
);
1858 _XawTextNeedsUpdating(ctx
, left
, pos
);
1860 if (left
> ctx
->text
.s
.left
) {
1861 pos
= Min(left
, ctx
->text
.s
.right
);
1862 _XawTextNeedsUpdating(ctx
, ctx
->text
.s
.left
, pos
);
1864 if (right
< ctx
->text
.s
.right
) {
1865 pos
= Max(right
, ctx
->text
.s
.left
);
1866 _XawTextNeedsUpdating(ctx
, pos
, ctx
->text
.s
.right
);
1868 if (right
> ctx
->text
.s
.right
) {
1869 pos
= Max(left
, ctx
->text
.s
.right
);
1870 _XawTextNeedsUpdating(ctx
, pos
, right
);
1873 ctx
->text
.s
.left
= left
;
1874 ctx
->text
.s
.right
= right
;
1876 SrcSetSelection(ctx
->text
.source
, left
, right
,
1877 (count
== 0) ? None
: selections
[0]);
1880 Widget w
= (Widget
) ctx
;
1884 Atom selection
= selections
[--count
];
1887 * If this is a cut buffer.
1890 if ((buffer
= GetCutBufferNumber(selection
)) != NOT_A_CUT_BUFFER
) {
1891 unsigned char *ptr
, *tptr
;
1892 unsigned int amount
, max_len
= MAX_CUT_LEN(XtDisplay(w
));
1895 tptr
= ptr
= (unsigned char *) _XawTextGetSTRING(ctx
, ctx
->text
.s
.left
,
1897 if (_XawTextFormat(ctx
) == (int)XawFmtWide
) {
1899 * Only XA_STRING(Latin 1) is allowed in CUT_BUFFER,
1900 * so we get it from wchar string, then free the wchar string.
1902 XTextProperty textprop
;
1903 if (XwcTextListToTextProperty(XtDisplay(w
), (wchar_t**)&ptr
, 1,
1904 XStringStyle
, &textprop
) < Success
) {
1905 XtFree((char *)ptr
);
1908 XtFree((char *)ptr
);
1909 tptr
= ptr
= textprop
.value
;
1912 _CreateCutBuffers(XtDisplay(w
));
1913 XRotateBuffers(XtDisplay(w
), 1);
1915 amount
= Min ( (len
= strlen((char *)ptr
)), max_len
);
1916 XChangeProperty(XtDisplay(w
), RootWindow(XtDisplay(w
), 0), selection
,
1917 XA_STRING
, 8, PropModeReplace
, ptr
, amount
);
1919 while (len
> max_len
) {
1922 amount
= Min (len
, max_len
);
1923 XChangeProperty(XtDisplay(w
), RootWindow(XtDisplay(w
), 0),
1924 selection
, XA_STRING
, 8, PropModeAppend
,
1927 XtFree ((char *)ptr
);
1929 else /* This is a real selection */
1930 XtOwnSelection(w
, selection
, ctx
->text
.time
, ConvertSelection
,
1931 LoseSelection
, (XtSelectionDoneProc
)NULL
);
1935 XawTextUnsetSelection((Widget
)ctx
);
1939 * This internal routine deletes the text from pos1 to pos2 in a source and
1940 * then inserts, at pos1, the text that was passed. As a side effect it
1941 * "invalidates" that portion of the displayed text (if any).
1943 * NOTE: It is illegal to call this routine unless there is a valid line table!
1947 _XawTextReplace (ctx
, pos1
, pos2
, text
)
1949 XawTextPosition pos1
, pos2
;
1952 int i
, line1
, error
;
1954 XawTextPosition updateFrom
, updateTo
;
1955 Widget src
= ctx
->text
.source
;
1956 XawTextEditType edit_mode
;
1958 Boolean tmp
= ctx
->text
.update_disabled
;
1960 ctx
->text
.update_disabled
= True
; /* No redisplay during replacement. */
1963 * The insertPos may not always be set to the right spot in XawtextAppend
1966 XtSetArg(args
[0], XtNeditType
, &edit_mode
);
1967 XtGetValues(src
, args
, ONE
);
1969 if ((pos1
== ctx
->text
.insertPos
) && (edit_mode
== XawtextAppend
)) {
1970 ctx
->text
.insertPos
= ctx
->text
.lastPos
;
1971 pos2
= SrcScan(src
, ctx
->text
.insertPos
, XawstPositions
, XawsdRight
,
1972 (int)(ctx
->text
.insertPos
- pos1
), (Boolean
)TRUE
);
1973 pos1
= ctx
->text
.insertPos
;
1974 if ( (pos1
== pos2
) && (text
->length
== 0) ) {
1975 ctx
->text
.update_disabled
= FALSE
; /* rearm redisplay. */
1976 return( XawEditError
);
1980 updateFrom
= SrcScan(src
, pos1
, XawstWhiteSpace
, XawsdLeft
, 1, FALSE
);
1981 updateFrom
= Max(updateFrom
, ctx
->text
.lt
.top
);
1983 line1
= LineForPosition(ctx
, updateFrom
);
1984 if ( (error
= SrcReplace(src
, pos1
, pos2
, text
)) != 0) {
1985 ctx
->text
.update_disabled
= tmp
; /* restore redisplay */
1989 XawTextUnsetSelection((Widget
)ctx
);
1991 ctx
->text
.lastPos
= GETLASTPOS
;
1992 if (ctx
->text
.lt
.top
>= ctx
->text
.lastPos
) {
1993 _XawTextBuildLineTable(ctx
, ctx
->text
.lastPos
, FALSE
);
1994 ClearWindow( (Widget
) ctx
);
1995 ctx
->text
.update_disabled
= tmp
; /* restore redisplay */
1996 return(0); /* Things are fine. */
1999 ctx
->text
.single_char
= (text
->length
<= 1 && pos2
- pos1
<= 1);
2001 delta
= text
->length
- (pos2
- pos1
);
2003 if (delta
< ctx
->text
.lastPos
) {
2004 for (pos2
+= delta
, i
= 0; i
< ctx
->text
.numranges
; i
++) {
2005 if (ctx
->text
.updateFrom
[i
] > pos1
)
2006 ctx
->text
.updateFrom
[i
] += delta
;
2007 if (ctx
->text
.updateTo
[i
] >= pos1
)
2008 ctx
->text
.updateTo
[i
] += delta
;
2013 * fixup all current line table entries to reflect edit.
2014 * %%% it is not legal to do arithmetic on positions.
2015 * using Scan would be more proper.
2018 XawTextLineTableEntry
*lineP
;
2019 i
= LineForPosition(ctx
, pos1
) + 1;
2020 for (lineP
= ctx
->text
.lt
.info
+ i
; i
<= ctx
->text
.lt
.lines
; i
++, lineP
++)
2021 lineP
->position
+= delta
;
2025 * Now process the line table and fixup in case edits caused
2026 * changes in line breaks. If we are breaking on word boundaries,
2027 * this code checks for moving words to and from lines.
2030 if (IsPositionVisible(ctx
, updateFrom
)) {
2031 updateTo
= _BuildLineTable(ctx
,
2032 ctx
->text
.lt
.info
[line1
].position
, pos1
, line1
);
2033 _XawTextNeedsUpdating(ctx
, updateFrom
, updateTo
);
2036 ctx
->text
.update_disabled
= tmp
; /* restore redisplay */
2037 return(0); /* Things are fine. */
2041 * This routine will display text between two arbitrary source positions.
2042 * In the event that this span contains highlighted text for the selection,
2043 * only that portion will be displayed highlighted.
2045 * NOTE: it is illegal to call this routine unless there
2046 * is a valid line table!
2050 DisplayText(w
, pos1
, pos2
)
2052 XawTextPosition pos1
, pos2
;
2054 TextWidget ctx
= (TextWidget
)w
;
2056 int height
, line
, i
, lastPos
= ctx
->text
.lastPos
;
2057 XawTextPosition startPos
, endPos
;
2058 Boolean clear_eol
, done_painting
;
2060 pos1
= (pos1
< ctx
->text
.lt
.top
) ? ctx
->text
.lt
.top
: pos1
;
2061 pos2
= FindGoodPosition(ctx
, pos2
);
2062 if ( (pos1
>= pos2
) || !LineAndXYForPosition(ctx
, pos1
, &line
, &x
, &y
) )
2063 return; /* line not visible, or pos1 >= pos2. */
2065 for ( startPos
= pos1
, i
= line
; IsValidLine(ctx
, i
) &&
2066 (i
< ctx
->text
.lt
.lines
) ; i
++) {
2069 if ( (endPos
= ctx
->text
.lt
.info
[i
+ 1].position
) > pos2
) {
2070 clear_eol
= ((endPos
= pos2
) >= lastPos
);
2071 done_painting
= (!clear_eol
|| ctx
->text
.single_char
);
2075 done_painting
= FALSE
;
2078 height
= ctx
->text
.lt
.info
[i
+ 1].y
- ctx
->text
.lt
.info
[i
].y
;
2080 if ( (endPos
> startPos
) ) {
2081 if ( (x
== (Position
) ctx
->text
.margin
.left
) && (x
> 0) )
2082 SinkClearToBG (ctx
->text
.sink
,
2084 (Dimension
) ctx
->text
.margin
.left
, (Dimension
)height
);
2086 if ( (startPos
>= ctx
->text
.s
.right
) || (endPos
<= ctx
->text
.s
.left
) )
2087 XawTextSinkDisplayText(ctx
->text
.sink
, x
, y
, startPos
, endPos
, FALSE
);
2088 else if ((startPos
>= ctx
->text
.s
.left
) && (endPos
<= ctx
->text
.s
.right
))
2089 XawTextSinkDisplayText(ctx
->text
.sink
, x
, y
, startPos
, endPos
, TRUE
);
2091 DisplayText(w
, startPos
, ctx
->text
.s
.left
);
2092 DisplayText(w
, Max(startPos
, ctx
->text
.s
.left
),
2093 Min(endPos
, ctx
->text
.s
.right
));
2094 DisplayText(w
, ctx
->text
.s
.right
, endPos
);
2099 SinkClearToBG(ctx
->text
.sink
,
2100 (Position
) (ctx
->text
.lt
.info
[i
].textWidth
+
2101 ctx
->text
.margin
.left
),
2102 (Position
) y
, w
->core
.width
, (Dimension
) height
);
2105 * We only get here if single character is true, and we need
2106 * to clear to the end of the screen. We know that since there
2107 * was only one character deleted that this is the same
2108 * as clearing an extra line, so we do this, and are done.
2110 * This a performance hack, and a pretty gross one, but it works.
2112 * Chris Peterson 11/13/89.
2115 if (done_painting
) {
2117 SinkClearToBG(ctx
->text
.sink
,
2118 (Position
) ctx
->text
.margin
.left
, (Position
) y
,
2119 w
->core
.width
, (Dimension
) height
);
2121 break; /* set single_char to FALSE and return. */
2125 x
= (Position
) ctx
->text
.margin
.left
;
2126 y
= ctx
->text
.lt
.info
[i
+ 1].y
;
2128 || (y
>= (int)(ctx
->core
.height
- ctx
->text
.margin
.bottom
)) )
2131 ctx
->text
.single_char
= FALSE
;
2135 * This routine implements multi-click selection in a hardwired manner.
2136 * It supports multi-click entity cycling (char, word, line, file) and mouse
2137 * motion adjustment of the selected entitie (i.e. select a word then, with
2138 * button still down, adjust wich word you really meant by moving the mouse).
2139 * [NOTE: This routine is to be replaced by a set of procedures that
2140 * will allows clients to implements a wide class of draw through and
2141 * multi-click selection user interfaces.]
2145 DoSelection (ctx
, pos
, time
, motion
)
2147 XawTextPosition pos
;
2151 XawTextPosition newLeft
, newRight
;
2152 XawTextSelectType newType
, *sarray
;
2153 Widget src
= ctx
->text
.source
;
2156 newType
= ctx
->text
.s
.type
;
2158 if ( (labs((long) time
- (long) ctx
->text
.lasttime
) < MULTI_CLICK_TIME
) &&
2159 ((pos
>= ctx
->text
.s
.left
) && (pos
<= ctx
->text
.s
.right
))) {
2160 sarray
= ctx
->text
.sarray
;
2161 for (;*sarray
!= XawselectNull
&& *sarray
!= ctx
->text
.s
.type
; sarray
++);
2163 if (*sarray
== XawselectNull
)
2164 newType
= *(ctx
->text
.sarray
);
2166 newType
= *(sarray
+ 1);
2167 if (newType
== XawselectNull
)
2168 newType
= *(ctx
->text
.sarray
);
2171 else /* single-click event */
2172 newType
= *(ctx
->text
.sarray
);
2174 ctx
->text
.lasttime
= time
;
2177 case XawselectPosition
:
2178 newLeft
= newRight
= pos
;
2182 newRight
= SrcScan(src
, pos
, XawstPositions
, XawsdRight
, 1, FALSE
);
2185 case XawselectParagraph
:
2187 XawTextScanType stype
;
2189 if (newType
== XawselectWord
)
2190 stype
= XawstWhiteSpace
;
2192 stype
= XawstParagraph
;
2195 * Somewhat complicated, but basically I treat the space between
2196 * two objects as another object. The object that I am currently
2197 * in then becomes the end of the selection.
2199 * Chris Peterson - 4/19/90.
2202 newRight
= SrcScan(ctx
->text
.source
, pos
, stype
, XawsdRight
, 1, FALSE
);
2203 newRight
=SrcScan(ctx
->text
.source
, newRight
,stype
,XawsdLeft
,1, FALSE
);
2205 if (pos
!= newRight
)
2206 newLeft
= SrcScan(ctx
->text
.source
, pos
, stype
, XawsdLeft
, 1, FALSE
);
2210 newLeft
=SrcScan(ctx
->text
.source
, newLeft
, stype
, XawsdRight
,1,FALSE
);
2212 if (newLeft
> newRight
) {
2213 XawTextPosition temp
= newLeft
;
2220 newLeft
= SrcScan(src
, pos
, XawstEOL
, XawsdLeft
, 1, FALSE
);
2221 newRight
= SrcScan(src
, pos
, XawstEOL
, XawsdRight
, 1, FALSE
);
2224 newLeft
= SrcScan(src
, pos
, XawstAll
, XawsdLeft
, 1, FALSE
);
2225 newRight
= SrcScan(src
, pos
, XawstAll
, XawsdRight
, 1, FALSE
);
2228 XtAppWarning(XtWidgetToApplicationContext((Widget
) ctx
),
2229 "Text Widget: empty selection array.");
2233 if ( (newLeft
!= ctx
->text
.s
.left
) || (newRight
!= ctx
->text
.s
.right
)
2234 || (newType
!= ctx
->text
.s
.type
)) {
2235 ModifySelection(ctx
, newLeft
, newRight
);
2236 if (pos
- ctx
->text
.s
.left
< ctx
->text
.s
.right
- pos
)
2237 ctx
->text
.insertPos
= newLeft
;
2239 ctx
->text
.insertPos
= newRight
;
2240 ctx
->text
.s
.type
= newType
;
2242 if (!motion
) { /* setup so we can freely mix select extend calls*/
2243 ctx
->text
.origSel
.type
= ctx
->text
.s
.type
;
2244 ctx
->text
.origSel
.left
= ctx
->text
.s
.left
;
2245 ctx
->text
.origSel
.right
= ctx
->text
.s
.right
;
2247 if (pos
>= ctx
->text
.s
.left
+ ((ctx
->text
.s
.right
- ctx
->text
.s
.left
) / 2))
2248 ctx
->text
.extendDir
= XawsdRight
;
2250 ctx
->text
.extendDir
= XawsdLeft
;
2255 * This routine implements extension of the currently selected text in
2256 * the "current" mode (i.e. char word, line, etc.). It worries about
2257 * extending from either end of the selection and handles the case when you
2258 * cross through the "center" of the current selection (e.g. switch which
2259 * end you are extending!).
2263 ExtendSelection (ctx
, pos
, motion
)
2265 XawTextPosition pos
;
2268 XawTextScanDirection dir
;
2270 if (!motion
) { /* setup for extending selection */
2271 if (ctx
->text
.s
.left
== ctx
->text
.s
.right
) /* no current selection. */
2272 ctx
->text
.s
.left
= ctx
->text
.s
.right
= ctx
->text
.insertPos
;
2274 ctx
->text
.origSel
.left
= ctx
->text
.s
.left
;
2275 ctx
->text
.origSel
.right
= ctx
->text
.s
.right
;
2278 ctx
->text
.origSel
.type
= ctx
->text
.s
.type
;
2280 if (pos
>= ctx
->text
.s
.left
+ ((ctx
->text
.s
.right
- ctx
->text
.s
.left
) / 2))
2281 ctx
->text
.extendDir
= XawsdRight
;
2283 ctx
->text
.extendDir
= XawsdLeft
;
2285 else /* check for change in extend direction */
2286 if ((ctx
->text
.extendDir
== XawsdRight
&& pos
<= ctx
->text
.origSel
.left
) ||
2287 (ctx
->text
.extendDir
== XawsdLeft
&& pos
>= ctx
->text
.origSel
.right
)) {
2288 ctx
->text
.extendDir
= (ctx
->text
.extendDir
== XawsdRight
) ?
2289 XawsdLeft
: XawsdRight
;
2290 ModifySelection(ctx
, ctx
->text
.origSel
.left
, ctx
->text
.origSel
.right
);
2293 dir
= ctx
->text
.extendDir
;
2294 switch (ctx
->text
.s
.type
) {
2296 case XawselectParagraph
:
2298 XawTextPosition left_pos
, right_pos
;
2299 XawTextScanType stype
;
2301 if (ctx
->text
.s
.type
== XawselectWord
)
2302 stype
= XawstWhiteSpace
;
2304 stype
= XawstParagraph
;
2307 * Somewhat complicated, but basically I treat the space between
2308 * two objects as another object. The object that I am currently
2309 * in then becomes the end of the selection.
2311 * Chris Peterson - 4/19/90.
2314 right_pos
= SrcScan(ctx
->text
.source
, pos
, stype
, XawsdRight
, 1, FALSE
);
2315 right_pos
=SrcScan(ctx
->text
.source
, right_pos
,stype
,XawsdLeft
,1, FALSE
);
2317 if (pos
!= right_pos
)
2318 left_pos
= SrcScan(ctx
->text
.source
, pos
, stype
, XawsdLeft
, 1, FALSE
);
2322 left_pos
=SrcScan(ctx
->text
.source
, left_pos
, stype
, XawsdRight
,1,FALSE
);
2324 if (dir
== XawsdLeft
)
2325 pos
= Min(left_pos
, right_pos
);
2326 else /* dir == XawsdRight */
2327 pos
= Max(left_pos
, right_pos
);
2331 pos
= SrcScan(ctx
->text
.source
, pos
, XawstEOL
, dir
, 1, dir
== XawsdRight
);
2334 pos
= ctx
->text
.insertPos
;
2335 case XawselectPosition
: /* fall through. */
2340 if (dir
== XawsdRight
)
2341 ModifySelection(ctx
, ctx
->text
.s
.left
, pos
);
2343 ModifySelection(ctx
, pos
, ctx
->text
.s
.right
);
2345 ctx
->text
.insertPos
= pos
;
2349 * Clear the window to background color.
2356 TextWidget ctx
= (TextWidget
) w
;
2358 if (XtIsRealized(w
))
2359 SinkClearToBG(ctx
->text
.sink
,
2360 (Position
) 0, (Position
) 0,
2361 w
->core
.width
, w
->core
.height
);
2364 /* Function Name: _XawTextClearAndCenterDisplay
2365 * Description: Redraws the display with the cursor in insert point
2366 * centered vertically.
2367 * Arguments: ctx - the text widget.
2372 _XawTextClearAndCenterDisplay(ctx
)
2375 int insert_line
= LineForPosition(ctx
, ctx
->text
.insertPos
);
2376 int scroll_by
= insert_line
- ctx
->text
.lt
.lines
/2;
2378 _XawTextVScroll(ctx
, scroll_by
);
2379 DisplayTextWindow( (Widget
) ctx
);
2383 * Internal redisplay entire window.
2384 * Legal to call only if widget is realized.
2388 DisplayTextWindow (w
)
2391 TextWidget ctx
= (TextWidget
) w
;
2393 _XawTextBuildLineTable(ctx
, ctx
->text
.lt
.top
, FALSE
);
2394 _XawTextNeedsUpdating(ctx
, zeroPosition
, ctx
->text
.lastPos
);
2395 _XawTextSetScrollBars(ctx
);
2399 * This routine checks to see if the window should be resized (grown or
2400 * shrunk) when text to be painted overflows to the right or
2401 * the bottom of the window. It is used by the keyboard input routine.
2405 _XawTextCheckResize(ctx
)
2408 Widget w
= (Widget
) ctx
;
2409 int line
= 0, old_height
;
2410 XtWidgetGeometry rbox
, return_geom
;
2412 if ( (ctx
->text
.resize
== XawtextResizeWidth
) ||
2413 (ctx
->text
.resize
== XawtextResizeBoth
) ) {
2414 XawTextLineTableEntry
*lt
;
2416 for (lt
= ctx
->text
.lt
.info
;
2417 IsValidLine(ctx
, line
) && (line
< ctx
->text
.lt
.lines
);
2419 if ((int)(lt
->textWidth
+ ctx
->text
.margin
.left
) > (int)rbox
.width
)
2420 rbox
.width
= lt
->textWidth
+ ctx
->text
.margin
.left
;
2423 rbox
.width
+= ctx
->text
.margin
.right
;
2424 if (rbox
.width
> ctx
->core
.width
) { /* Only get wider. */
2425 rbox
.request_mode
= CWWidth
;
2426 if (XtMakeGeometryRequest(w
, &rbox
, &return_geom
) == XtGeometryAlmost
)
2427 (void) XtMakeGeometryRequest(w
, &return_geom
, (XtWidgetGeometry
*) NULL
);
2431 if ( !((ctx
->text
.resize
== XawtextResizeHeight
) ||
2432 (ctx
->text
.resize
== XawtextResizeBoth
)) )
2435 if (IsPositionVisible(ctx
, ctx
->text
.lastPos
))
2436 line
= LineForPosition(ctx
, ctx
->text
.lastPos
);
2438 line
= ctx
->text
.lt
.lines
;
2440 if ( (line
+ 1) == ctx
->text
.lt
.lines
) return;
2442 old_height
= ctx
->core
.height
;
2443 rbox
.request_mode
= CWHeight
;
2444 rbox
.height
= XawTextSinkMaxHeight(ctx
->text
.sink
, line
+ 1) + VMargins(ctx
);
2446 if ((int)rbox
.height
< old_height
) return; /* It will only get taller. */
2448 if (XtMakeGeometryRequest(w
, &rbox
, &return_geom
) == XtGeometryAlmost
)
2449 if (XtMakeGeometryRequest(w
, &return_geom
, (XtWidgetGeometry
*)NULL
) != XtGeometryYes
)
2452 _XawTextBuildLineTable(ctx
, ctx
->text
.lt
.top
, TRUE
);
2456 * Converts (params, num_params) to a list of atoms & caches the
2457 * list in the TextWidget instance.
2461 _XawTextSelectionList(ctx
, list
, nelems
)
2466 Atom
* sel
= ctx
->text
.s
.selections
;
2467 Display
*dpy
= XtDisplay((Widget
) ctx
);
2470 if (nelems
> ctx
->text
.s
.array_size
) {
2471 sel
= (Atom
*) XtRealloc((char *) sel
, sizeof(Atom
) * nelems
);
2472 ctx
->text
.s
.array_size
= nelems
;
2473 ctx
->text
.s
.selections
= sel
;
2475 for (n
=nelems
; --n
>= 0; sel
++, list
++)
2476 *sel
= XInternAtom(dpy
, *list
, False
);
2477 ctx
->text
.s
.atom_count
= nelems
;
2478 return ctx
->text
.s
.selections
;
2481 /* Function Name: SetSelection
2482 * Description: Sets the current selection.
2483 * Arguments: ctx - the text widget.
2484 * defaultSel - the default selection.
2485 * l, r - the left and right ends of the selection.
2486 * list, nelems - the selection list (as strings).
2489 * NOTE: if (ctx->text.s.left >= ctx->text.s.right) then the selection
2494 _XawTextSetSelection(ctx
, l
, r
, list
, nelems
)
2496 XawTextPosition l
, r
;
2500 if (nelems
== 1 && !strcmp (list
[0], "none"))
2503 String defaultSel
= "PRIMARY";
2507 _SetSelection(ctx
, l
, r
, _XawTextSelectionList(ctx
, list
, nelems
), nelems
);
2511 /* Function Name: ModifySelection
2512 * Description: Modifies the current selection.
2513 * Arguments: ctx - the text widget.
2514 * left, right - the left and right ends of the selection.
2517 * NOTE: if (ctx->text.s.left >= ctx->text.s.right) then the selection
2522 ModifySelection(ctx
, left
, right
)
2524 XawTextPosition left
, right
;
2527 ctx
->text
.insertPos
= left
;
2528 _SetSelection( ctx
, left
, right
, (Atom
*) NULL
, ZERO
);
2532 * This routine is used to perform various selection functions. The goal is
2533 * to be able to specify all the more popular forms of draw-through and
2534 * multi-click selection user interfaces from the outside.
2538 _XawTextAlterSelection (ctx
, mode
, action
, params
, num_params
)
2540 XawTextSelectionMode mode
; /* {XawsmTextSelect, XawsmTextExtend} */
2541 XawTextSelectionAction action
; /* {XawactionStart,
2542 XawactionAdjust, XawactionEnd} */
2544 Cardinal
*num_params
;
2546 XawTextPosition position
;
2550 * This flag is used by TextPop.c:DoReplace() to determine if the selection
2551 * is okay to use, or if it has been modified.
2554 if (ctx
->text
.search
!= NULL
)
2555 ctx
->text
.search
->selection_changed
= TRUE
;
2557 position
= PositionForXY (ctx
, (int) ctx
->text
.ev_x
, (int) ctx
->text
.ev_y
);
2559 flag
= (action
!= XawactionStart
);
2560 if (mode
== XawsmTextSelect
)
2561 DoSelection (ctx
, position
, ctx
->text
.time
, flag
);
2562 else /* mode == XawsmTextExtend */
2563 ExtendSelection (ctx
, position
, flag
);
2565 if (action
== XawactionEnd
)
2566 _XawTextSetSelection(ctx
, ctx
->text
.s
.left
, ctx
->text
.s
.right
,
2567 params
, *num_params
);
2570 /* Function Name: RectanglesOverlap
2571 * Description: Returns TRUE if two rectangles overlap.
2572 * Arguments: rect1, rect2 - the two rectangles to check.
2573 * Returns: TRUE iff these rectangles overlap.
2577 RectanglesOverlap(rect1
, rect2
)
2578 XRectangle
*rect1
, *rect2
;
2580 return ( (rect1
->x
< rect2
->x
+ (short) rect2
->width
) &&
2581 (rect2
->x
< rect1
->x
+ (short) rect1
->width
) &&
2582 (rect1
->y
< rect2
->y
+ (short) rect2
->height
) &&
2583 (rect2
->y
< rect1
->y
+ (short) rect1
->height
) );
2586 /* Function Name: UpdateTextInRectangle.
2587 * Description: Updates the text in a rectangle.
2588 * Arguments: ctx - the text widget.
2589 * rect - the rectangle to update.
2594 UpdateTextInRectangle(ctx
, rect
)
2598 XawTextLineTableEntry
*info
= ctx
->text
.lt
.info
;
2599 int line
, x
= rect
->x
, y
= rect
->y
;
2600 int right
= rect
->width
+ x
, bottom
= rect
->height
+ y
;
2602 for (line
= 0;( (line
< ctx
->text
.lt
.lines
) &&
2603 IsValidLine(ctx
, line
) && (info
->y
< bottom
)); line
++, info
++)
2604 if ( (info
+ 1)->y
>= y
)
2605 UpdateTextInLine(ctx
, line
, x
, right
);
2609 * This routine processes all "expose region" XEvents. In general, its job
2610 * is to the best job at minimal re-paint of the text, displayed in the
2611 * window, that it can.
2616 ProcessExposeRegion(w
, event
, region
)
2619 Region region
; /* Unused. */
2621 TextWidget ctx
= (TextWidget
) w
;
2622 XRectangle expose
, cursor
;
2623 Boolean need_to_draw
;
2625 if (event
->type
== Expose
) {
2626 expose
.x
= event
->xexpose
.x
;
2627 expose
.y
= event
->xexpose
.y
;
2628 expose
.width
= event
->xexpose
.width
;
2629 expose
.height
= event
->xexpose
.height
;
2631 else if (event
->type
== GraphicsExpose
) {
2632 expose
.x
= event
->xgraphicsexpose
.x
;
2633 expose
.y
= event
->xgraphicsexpose
.y
;
2634 expose
.width
= event
->xgraphicsexpose
.width
;
2635 expose
.height
= event
->xgraphicsexpose
.height
;
2637 else { /* No Expose */
2639 return; /* no more processing necessary. */
2642 need_to_draw
= TranslateExposeRegion(ctx
, &expose
);
2643 if ((event
->type
== GraphicsExpose
) && (event
->xgraphicsexpose
.count
== 0))
2647 return; /* don't draw if we don't need to. */
2649 _XawTextPrepareToUpdate(ctx
);
2650 UpdateTextInRectangle(ctx
, &expose
);
2651 XawTextSinkGetCursorBounds(ctx
->text
.sink
, &cursor
);
2652 if (RectanglesOverlap(&cursor
, &expose
)) {
2653 SinkClearToBG(ctx
->text
.sink
, (Position
) cursor
.x
, (Position
) cursor
.y
,
2654 (Dimension
) cursor
.width
, (Dimension
) cursor
.height
);
2655 UpdateTextInRectangle(ctx
, &cursor
);
2657 _XawTextExecuteUpdate(ctx
);
2661 * This routine does all setup required to syncronize batched screen updates
2665 _XawTextPrepareToUpdate(ctx
)
2668 if (ctx
->text
.old_insert
< 0) {
2669 InsertCursor((Widget
)ctx
, XawisOff
);
2670 ctx
->text
.numranges
= 0;
2671 ctx
->text
.showposition
= FALSE
;
2672 ctx
->text
.old_insert
= ctx
->text
.insertPos
;
2677 * This is a private utility routine used by _XawTextExecuteUpdate. It
2678 * processes all the outstanding update requests and merges update
2679 * ranges where possible.
2683 void FlushUpdate(ctx
)
2687 XawTextPosition updateFrom
, updateTo
;
2688 if (!XtIsRealized((Widget
)ctx
)) {
2689 ctx
->text
.numranges
= 0;
2692 while (ctx
->text
.numranges
> 0) {
2693 updateFrom
= ctx
->text
.updateFrom
[0];
2695 for (i
= 1 ; i
< ctx
->text
.numranges
; i
++) {
2696 if (ctx
->text
.updateFrom
[i
] < updateFrom
) {
2697 updateFrom
= ctx
->text
.updateFrom
[i
];
2701 updateTo
= ctx
->text
.updateTo
[w
];
2702 ctx
->text
.numranges
--;
2703 ctx
->text
.updateFrom
[w
] = ctx
->text
.updateFrom
[ctx
->text
.numranges
];
2704 ctx
->text
.updateTo
[w
] = ctx
->text
.updateTo
[ctx
->text
.numranges
];
2705 for (i
= ctx
->text
.numranges
- 1 ; i
>= 0 ; i
--) {
2706 while (ctx
->text
.updateFrom
[i
] <= updateTo
&& i
< ctx
->text
.numranges
) {
2707 updateTo
= ctx
->text
.updateTo
[i
];
2708 ctx
->text
.numranges
--;
2709 ctx
->text
.updateFrom
[i
] = ctx
->text
.updateFrom
[ctx
->text
.numranges
];
2710 ctx
->text
.updateTo
[i
] = ctx
->text
.updateTo
[ctx
->text
.numranges
];
2713 DisplayText((Widget
)ctx
, updateFrom
, updateTo
);
2718 * This is a private utility routine used by _XawTextExecuteUpdate. This
2719 * routine worries about edits causing new data or the insertion point becoming
2720 * invisible (off the screen, or under the horiz. scrollbar). Currently
2721 * it always makes it visible by scrolling. It probably needs
2722 * generalization to allow more options.
2726 _XawTextShowPosition(ctx
)
2729 int x
, y
, lines
, number
;
2731 XawTextPosition max_pos
, top
, first
;
2733 if ( (!XtIsRealized((Widget
)ctx
)) || (ctx
->text
.lt
.lines
<= 0) )
2737 * Find out the bottom the visable window, and make sure that the
2738 * cursor does not go past the end of this space.
2740 * This makes sure that the cursor does not go past the end of the
2744 x
= ctx
->core
.width
;
2745 y
= ctx
->core
.height
- ctx
->text
.margin
.bottom
;
2746 if (ctx
->text
.hbar
!= NULL
)
2747 y
-= ctx
->text
.hbar
->core
.height
+ 2 * ctx
->text
.hbar
->core
.border_width
;
2749 max_pos
= PositionForXY (ctx
, x
, y
);
2750 lines
= LineForPosition(ctx
, max_pos
) + 1; /* number of visable lines. */
2752 if ( (ctx
->text
.insertPos
>= ctx
->text
.lt
.top
) &&
2753 (ctx
->text
.insertPos
< max_pos
))
2756 first
= ctx
->text
.lt
.top
;
2759 if (ctx
->text
.insertPos
< first
) { /* We need to scroll down. */
2760 top
= SrcScan(ctx
->text
.source
, ctx
->text
.insertPos
,
2761 XawstEOL
, XawsdLeft
, 1, FALSE
);
2763 /* count the number of lines we have to scroll */
2766 while (first
> top
) {
2767 first
= SrcScan(ctx
->text
.source
, first
,
2768 XawstEOL
, XawsdLeft
, 1, TRUE
);
2770 if ( - number
> lines
)
2776 if (first
<= top
) { /* If we found the proper number
2779 /* Back up to just before the last CR. */
2781 first
= SrcScan(ctx
->text
.source
, first
,
2782 XawstPositions
, XawsdRight
, 1, TRUE
);
2784 /* Check to make sure the cursor is visable. */
2794 else { /* We need to Scroll up */
2795 top
= SrcScan(ctx
->text
.source
, ctx
->text
.insertPos
,
2796 XawstEOL
, XawsdLeft
, lines
, FALSE
);
2799 lines
= LineForPosition(ctx
, top
);
2805 _XawTextBuildLineTable(ctx
, top
, FALSE
);
2806 DisplayTextWindow((Widget
)ctx
);
2809 _XawTextVScroll(ctx
, lines
);
2811 _XawTextSetScrollBars(ctx
);
2815 * This routine causes all batched screen updates to be performed
2819 _XawTextExecuteUpdate(ctx
)
2822 if ( ctx
->text
.update_disabled
|| (ctx
->text
.old_insert
< 0) )
2825 if((ctx
->text
.old_insert
!= ctx
->text
.insertPos
) || (ctx
->text
.showposition
))
2826 _XawTextShowPosition(ctx
);
2828 InsertCursor((Widget
)ctx
, XawisOn
);
2829 ctx
->text
.old_insert
= -1;
2837 TextWidget ctx
= (TextWidget
)w
;
2839 DestroyHScrollBar(ctx
);
2840 DestroyVScrollBar(ctx
);
2842 XtFree((char *)ctx
->text
.s
.selections
);
2843 XtFree((char *)ctx
->text
.lt
.info
);
2844 XtFree((char *)ctx
->text
.search
);
2845 XtFree((char *)ctx
->text
.updateFrom
);
2846 XtFree((char *)ctx
->text
.updateTo
);
2850 * by the time we are managed (and get this far) we had better
2851 * have both a source and a sink
2858 TextWidget ctx
= (TextWidget
) w
;
2860 PositionVScrollBar(ctx
);
2861 PositionHScrollBar(ctx
);
2863 _XawTextBuildLineTable(ctx
, ctx
->text
.lt
.top
, TRUE
);
2864 _XawTextSetScrollBars(ctx
);
2868 * This routine allow the application program to Set attributes.
2873 SetValues(current
, request
, new, args
, num_args
)
2874 Widget current
, request
, new;
2878 TextWidget oldtw
= (TextWidget
) current
;
2879 TextWidget newtw
= (TextWidget
) new;
2880 Boolean redisplay
= FALSE
;
2881 Boolean display_caret
= newtw
->text
.display_caret
;
2884 newtw
->text
.display_caret
= oldtw
->text
.display_caret
;
2885 _XawTextPrepareToUpdate(newtw
);
2886 newtw
->text
.display_caret
= display_caret
;
2888 if (oldtw
->text
.r_margin
.left
!= newtw
->text
.r_margin
.left
) {
2889 newtw
->text
.margin
.left
= newtw
->text
.r_margin
.left
;
2890 if (newtw
->text
.vbar
!= NULL
)
2891 newtw
->text
.margin
.left
+= newtw
->text
.vbar
->core
.width
+
2892 newtw
->text
.vbar
->core
.border_width
;
2896 if (oldtw
->text
.scroll_vert
!= newtw
->text
.scroll_vert
) {
2897 if (newtw
->text
.scroll_vert
== XawtextScrollNever
)
2898 DestroyVScrollBar(newtw
);
2899 else if (newtw
->text
.scroll_vert
== XawtextScrollAlways
)
2900 CreateVScrollBar(newtw
);
2904 if (oldtw
->text
.r_margin
.bottom
!= newtw
->text
.r_margin
.bottom
) {
2905 newtw
->text
.margin
.bottom
= newtw
->text
.r_margin
.bottom
;
2906 if (newtw
->text
.hbar
!= NULL
)
2907 newtw
->text
.margin
.bottom
+= newtw
->text
.hbar
->core
.height
+
2908 newtw
->text
.hbar
->core
.border_width
;
2912 if (oldtw
->text
.scroll_horiz
!= newtw
->text
.scroll_horiz
) {
2913 if (newtw
->text
.scroll_horiz
== XawtextScrollNever
)
2914 DestroyHScrollBar(newtw
);
2915 else if (newtw
->text
.scroll_horiz
== XawtextScrollAlways
)
2916 CreateHScrollBar(newtw
);
2920 if ( oldtw
->text
.source
!= newtw
->text
.source
)
2921 XawTextSetSource( (Widget
) newtw
, newtw
->text
.source
, newtw
->text
.lt
.top
);
2923 newtw
->text
.redisplay_needed
= False
;
2924 XtSetValues( (Widget
)newtw
->text
.source
, args
, *num_args
);
2925 XtSetValues( (Widget
)newtw
->text
.sink
, args
, *num_args
);
2927 if ( oldtw
->text
.wrap
!= newtw
->text
.wrap
||
2928 oldtw
->text
.lt
.top
!= newtw
->text
.lt
.top
||
2929 oldtw
->text
.r_margin
.right
!= newtw
->text
.r_margin
.right
||
2930 oldtw
->text
.r_margin
.top
!= newtw
->text
.r_margin
.top
||
2931 oldtw
->text
.sink
!= newtw
->text
.sink
||
2932 newtw
->text
.redisplay_needed
)
2934 _XawTextBuildLineTable(newtw
, newtw
->text
.lt
.top
, TRUE
);
2938 if (oldtw
->text
.insertPos
!= newtw
->text
.insertPos
) {
2939 newtw
->text
.showposition
= TRUE
;
2943 _XawTextExecuteUpdate(newtw
);
2945 _XawTextSetScrollBars(newtw
);
2950 /* invoked by the Simple widget's SetValues */
2951 static Boolean
ChangeSensitive(w
)
2952 Widget w
; /* the new widget */
2955 TextWidget tw
= (TextWidget
) w
;
2957 (*(&simpleClassRec
)->simple_class
.change_sensitive
)(w
);
2959 XtSetArg(args
[0], XtNancestorSensitive
,
2960 (tw
->core
.ancestor_sensitive
&& tw
->core
.sensitive
));
2962 XtSetValues(tw
->text
.vbar
, args
, ONE
);
2964 XtSetValues(tw
->text
.hbar
, args
, ONE
);
2968 /* Function Name: GetValuesHook
2969 * Description: This is a get values hook routine that gets the
2970 * values in the text source and sink.
2971 * Arguments: w - the Text Widget.
2972 * args - the argument list.
2973 * num_args - the number of args.
2978 GetValuesHook(w
, args
, num_args
)
2981 Cardinal
* num_args
;
2983 XtGetValues( ((TextWidget
) w
)->text
.source
, args
, *num_args
);
2984 XtGetValues( ((TextWidget
) w
)->text
.sink
, args
, *num_args
);
2987 /* Function Name: FindGoodPosition
2988 * Description: Returns a valid position given any postition
2989 * Arguments: pos - any position.
2990 * Returns: a position between (0 and lastPos);
2993 static XawTextPosition
2994 FindGoodPosition(ctx
, pos
)
2996 XawTextPosition pos
;
2998 if (pos
< 0) return(0);
2999 return ( ((pos
> ctx
->text
.lastPos
) ? ctx
->text
.lastPos
: pos
) );
3002 /************************************************************
3004 * Routines for handling the copy area expose queue.
3006 ************************************************************/
3008 /* Function Name: PushCopyQueue
3009 * Description: Pushes a value onto the copy queue.
3010 * Arguments: ctx - the text widget.
3011 * h, v - amount of offset in the horiz and vert directions.
3016 PushCopyQueue(ctx
, h
, v
)
3020 struct text_move
* offsets
= XtNew(struct text_move
);
3024 offsets
->next
= NULL
;
3026 if (ctx
->text
.copy_area_offsets
== NULL
)
3027 ctx
->text
.copy_area_offsets
= offsets
;
3029 struct text_move
* end
= ctx
->text
.copy_area_offsets
;
3030 for ( ; end
->next
!= NULL
; end
= end
->next
) {}
3031 end
->next
= offsets
;
3035 /* Function Name: PopCopyQueue
3036 * Description: Pops the top value off of the copy queue.
3037 * Arguments: ctx - the text widget.
3045 struct text_move
* offsets
= ctx
->text
.copy_area_offsets
;
3047 if (offsets
== NULL
)
3048 (void) printf( "Xaw Text widget %s: empty copy queue\n",
3049 XtName( (Widget
) ctx
) );
3051 ctx
->text
.copy_area_offsets
= offsets
->next
;
3052 XtFree((char *) offsets
); /* free what you allocate. */
3056 /* Function Name: TranslateExposeRegion
3057 * Description: Translates the expose that came into
3058 * the cordinates that now exist in the Text widget.
3059 * Arguments: ctx - the text widget.
3060 * expose - a Rectangle, who's region currently
3061 * contains the expose event location.
3062 * this region will be returned containing
3063 * the new rectangle.
3064 * Returns: True if there is drawing that needs to be done.
3068 TranslateExposeRegion(ctx
, expose
)
3070 XRectangle
* expose
;
3072 struct text_move
* offsets
= ctx
->text
.copy_area_offsets
;
3074 int x
, y
, width
, height
;
3077 * Skip over the first one, this has already been taken into account.
3080 if (!offsets
|| !(offsets
= offsets
->next
))
3085 width
= expose
->width
;
3086 height
= expose
->height
;
3091 offsets
= offsets
->next
;
3095 * remove that area of the region that is now outside the window.
3103 value
= y
+ height
- ctx
->core
.height
;
3108 return(FALSE
); /* no need to draw outside the window. */
3111 * and now in the horiz direction...
3119 value
= x
+ width
- ctx
->core
.width
;
3124 return(FALSE
); /* no need to draw outside the window. */
3128 expose
->width
= width
;
3129 expose
->height
= height
;
3133 /* Li wrote this so the IM can find a given text position's screen position. */
3136 #if NeedFunctionPrototypes
3139 XawTextPosition pos
,
3143 _XawTextPosToXY( w
, pos
, x
, y
)
3145 XawTextPosition pos
;
3150 LineAndXYForPosition( (TextWidget
)w
, pos
, &line
, x
, y
);
3153 /*******************************************************************
3154 The following routines provide procedural interfaces to Text window state
3155 setting and getting. They need to be redone so than the args code can use
3156 them. I suggest we create a complete set that takes the context as an
3157 argument and then have the public version lookup the context and call the
3158 internal one. The major value of this set is that they have actual application
3159 clients and therefore the functionality provided is required for any future
3161 ********************************************************************/
3164 #if NeedFunctionPrototypes
3165 XawTextDisplay (Widget w
)
3171 if (!XtIsRealized(w
)) return;
3173 _XawTextPrepareToUpdate( (TextWidget
) w
);
3174 DisplayTextWindow(w
);
3175 _XawTextExecuteUpdate( (TextWidget
) w
);
3179 #if NeedFunctionPrototypes
3180 XawTextSetSelectionArray(Widget w
, XawTextSelectType
*sarray
)
3182 XawTextSetSelectionArray(w
, sarray
)
3184 XawTextSelectType
*sarray
;
3187 ((TextWidget
)w
)->text
.sarray
= sarray
;
3191 #if NeedFunctionPrototypes
3192 XawTextGetSelectionPos(Widget w
, XawTextPosition
*left
, XawTextPosition
*right
)
3194 XawTextGetSelectionPos(w
, left
, right
)
3196 XawTextPosition
* left
,* right
;
3199 *left
= ((TextWidget
) w
)->text
.s
.left
;
3200 *right
= ((TextWidget
) w
)->text
.s
.right
;
3205 #if NeedFunctionPrototypes
3206 XawTextSetSource(Widget w
, Widget source
, XawTextPosition startPos
)
3208 XawTextSetSource(w
, source
, startPos
)
3210 XawTextPosition startPos
;
3213 TextWidget ctx
= (TextWidget
) w
;
3215 ctx
->text
.source
= source
;
3216 ctx
->text
.lt
.top
= startPos
;
3217 ctx
->text
.s
.left
= ctx
->text
.s
.right
= 0;
3218 ctx
->text
.insertPos
= startPos
;
3219 ctx
->text
.lastPos
= GETLASTPOS
;
3221 _XawTextBuildLineTable(ctx
, ctx
->text
.lt
.top
, TRUE
);
3226 * This public routine deletes the text from startPos to endPos in a source and
3227 * then inserts, at startPos, the text that was passed. As a side effect it
3228 * "invalidates" that portion of the displayed text (if any), so that things
3229 * will be repainted properly.
3233 #if NeedFunctionPrototypes
3234 XawTextReplace(Widget w
, XawTextPosition startPos
, XawTextPosition endPos
,
3237 XawTextReplace(w
, startPos
, endPos
, text
)
3239 XawTextPosition startPos
, endPos
;
3243 TextWidget ctx
= (TextWidget
) w
;
3246 _XawTextPrepareToUpdate(ctx
);
3247 endPos
= FindGoodPosition(ctx
, endPos
);
3248 startPos
= FindGoodPosition(ctx
, startPos
);
3249 if ((result
= _XawTextReplace(ctx
, startPos
, endPos
, text
)) == XawEditDone
) {
3250 long delta
= text
->length
- (endPos
- startPos
);
3251 if (ctx
->text
.insertPos
>= (endPos
+ delta
)) {
3252 XawTextScanDirection sd
= (delta
< 0) ? XawsdLeft
: XawsdRight
;
3253 ctx
->text
.insertPos
= SrcScan(ctx
->text
.source
, ctx
->text
.insertPos
,
3254 XawstPositions
, sd
, labs(delta
), TRUE
);
3258 _XawTextCheckResize(ctx
);
3259 _XawTextExecuteUpdate(ctx
);
3260 _XawTextSetScrollBars(ctx
);
3266 #if NeedFunctionPrototypes
3267 XawTextTopPosition(Widget w
)
3269 XawTextTopPosition(w
)
3273 return( ((TextWidget
) w
)->text
.lt
.top
);
3277 #if NeedFunctionPrototypes
3278 XawTextSetInsertionPoint(Widget w
, XawTextPosition position
)
3280 XawTextSetInsertionPoint(w
, position
)
3282 XawTextPosition position
;
3285 TextWidget ctx
= (TextWidget
) w
;
3287 _XawTextPrepareToUpdate(ctx
);
3288 ctx
->text
.insertPos
= FindGoodPosition(ctx
, position
);
3289 ctx
->text
.showposition
= TRUE
;
3291 _XawTextExecuteUpdate(ctx
);
3295 #if NeedFunctionPrototypes
3296 XawTextGetInsertionPoint(Widget w
)
3298 XawTextGetInsertionPoint(w
)
3302 return( ((TextWidget
) w
)->text
.insertPos
);
3306 * NOTE: Must walk the selection list in opposite order from LoseSelection.
3310 #if NeedFunctionPrototypes
3311 XawTextUnsetSelection(Widget w
)
3313 XawTextUnsetSelection(w
)
3317 TextWidget ctx
= (TextWidget
)w
;
3319 while (ctx
->text
.s
.atom_count
!= 0) {
3320 Atom sel
= ctx
->text
.s
.selections
[ctx
->text
.s
.atom_count
- 1];
3321 if ( sel
!= (Atom
) 0 ) {
3323 * As selections are lost the atom_count will decrement.
3325 if (GetCutBufferNumber(sel
) == NOT_A_CUT_BUFFER
)
3326 XtDisownSelection(w
, sel
, ctx
->text
.time
);
3327 LoseSelection(w
, &sel
); /* In case this is a cut buffer, or
3328 XtDisownSelection failed to call us. */
3334 #if NeedFunctionPrototypes
3335 XawTextSetSelection (Widget w
, XawTextPosition left
, XawTextPosition right
)
3337 XawTextSetSelection (w
, left
, right
)
3339 XawTextPosition left
, right
;
3342 TextWidget ctx
= (TextWidget
) w
;
3344 _XawTextPrepareToUpdate(ctx
);
3345 _XawTextSetSelection(ctx
, FindGoodPosition(ctx
, left
),
3346 FindGoodPosition(ctx
, right
), (String
*)NULL
, ZERO
);
3347 _XawTextExecuteUpdate(ctx
);
3351 #if NeedFunctionPrototypes
3352 XawTextInvalidate(Widget w
, XawTextPosition from
, XawTextPosition to
)
3354 XawTextInvalidate(w
, from
, to
)
3356 XawTextPosition from
,to
;
3359 TextWidget ctx
= (TextWidget
) w
;
3361 from
= FindGoodPosition(ctx
, from
);
3362 to
= FindGoodPosition(ctx
, to
);
3363 ctx
->text
.lastPos
= GETLASTPOS
;
3364 _XawTextPrepareToUpdate(ctx
);
3365 _XawTextNeedsUpdating(ctx
, from
, to
);
3366 _XawTextBuildLineTable(ctx
, ctx
->text
.lt
.top
, TRUE
);
3367 _XawTextExecuteUpdate(ctx
);
3372 #if NeedFunctionPrototypes
3373 XawTextDisableRedisplay(Widget w
)
3375 XawTextDisableRedisplay(w
)
3379 ((TextWidget
) w
)->text
.update_disabled
= True
;
3380 _XawTextPrepareToUpdate( (TextWidget
) w
);
3384 #if NeedFunctionPrototypes
3385 XawTextEnableRedisplay(Widget w
)
3387 XawTextEnableRedisplay(w
)
3391 TextWidget ctx
= (TextWidget
)w
;
3392 XawTextPosition lastPos
;
3394 if (!ctx
->text
.update_disabled
) return;
3396 ctx
->text
.update_disabled
= False
;
3397 lastPos
= ctx
->text
.lastPos
= GETLASTPOS
;
3398 ctx
->text
.lt
.top
= FindGoodPosition(ctx
, ctx
->text
.lt
.top
);
3399 ctx
->text
.insertPos
= FindGoodPosition(ctx
, ctx
->text
.insertPos
);
3400 if ( (ctx
->text
.s
.left
> lastPos
) || (ctx
->text
.s
.right
> lastPos
) )
3401 ctx
->text
.s
.left
= ctx
->text
.s
.right
= 0;
3403 _XawTextBuildLineTable(ctx
, ctx
->text
.lt
.top
, TRUE
);
3404 if (XtIsRealized(w
))
3405 DisplayTextWindow(w
);
3406 _XawTextExecuteUpdate(ctx
);
3410 #if NeedFunctionPrototypes
3411 XawTextGetSource(Widget w
)
3417 return ((TextWidget
)w
)->text
.source
;
3421 #if NeedFunctionPrototypes
3422 XawTextDisplayCaret (Widget w
,
3423 #if NeedWidePrototypes
3424 /* Boolean */ int display_caret
)
3426 Boolean display_caret
)
3429 XawTextDisplayCaret (w
, display_caret
)
3431 Boolean display_caret
;
3434 TextWidget ctx
= (TextWidget
) w
;
3436 if (ctx
->text
.display_caret
== display_caret
) return;
3438 if (XtIsRealized(w
)) {
3439 _XawTextPrepareToUpdate(ctx
);
3440 ctx
->text
.display_caret
= display_caret
;
3441 _XawTextExecuteUpdate(ctx
);
3444 ctx
->text
.display_caret
= display_caret
;
3447 /* Function Name: XawTextSearch(w, dir, text).
3448 * Description: searches for the given text block.
3449 * Arguments: w - The text widget.
3450 * dir - The direction to search.
3451 * text - The text block containing info about the string
3453 * Returns: The position of the text found, or XawTextSearchError on
3458 #if NeedFunctionPrototypes
3459 XawTextSearch(Widget w
,
3460 #if NeedWidePrototypes
3461 /* XawTextScanDirection */ int dir
,
3463 XawTextScanDirection dir
,
3467 XawTextSearch(w
, dir
, text
)
3469 XawTextScanDirection dir
;
3470 XawTextBlock
* text
;
3473 TextWidget ctx
= (TextWidget
) w
;
3475 return(SrcSearch(ctx
->text
.source
, ctx
->text
.insertPos
, dir
, text
));
3478 TextClassRec textClassRec
= {
3480 /* superclass */ (WidgetClass
) &simpleClassRec
,
3481 /* class_name */ "Text",
3482 /* widget_size */ sizeof(TextRec
),
3483 /* class_initialize */ ClassInitialize
,
3484 /* class_part_init */ NULL
,
3485 /* class_inited */ FALSE
,
3486 /* initialize */ Initialize
,
3487 /* initialize_hook */ NULL
,
3488 /* realize */ Realize
,
3489 /* actions */ _XawTextActionsTable
,
3490 /* num_actions */ 0, /* Set in ClassInitialize. */
3491 /* resources */ resources
,
3492 /* num_ resource */ XtNumber(resources
),
3493 /* xrm_class */ NULLQUARK
,
3494 /* compress_motion */ TRUE
,
3495 /* compress_exposure*/ XtExposeGraphicsExpose
| XtExposeNoExpose
,
3496 /* compress_enterleave*/ TRUE
,
3497 /* visible_interest */ FALSE
,
3498 /* destroy */ TextDestroy
,
3499 /* resize */ Resize
,
3500 /* expose */ ProcessExposeRegion
,
3501 /* set_values */ SetValues
,
3502 /* set_values_hook */ NULL
,
3503 /* set_values_almost*/ XtInheritSetValuesAlmost
,
3504 /* get_values_hook */ GetValuesHook
,
3505 /* accept_focus */ NULL
,
3506 /* version */ XtVersion
,
3507 /* callback_private */ NULL
,
3508 /* tm_table */ NULL
, /* set in ClassInitialize */
3509 /* query_geometry */ XtInheritQueryGeometry
,
3510 /* display_accelerator*/ XtInheritDisplayAccelerator
,
3511 /* extension */ NULL
3513 { /* Simple fields */
3514 /* change_sensitive */ ChangeSensitive
3521 WidgetClass textWidgetClass
= (WidgetClass
)&textClassRec
;