1 #if (!defined(lint) && !defined(SABER))
2 static char Xrcsid
[] = "$XConsortium: Text.c,v 1.136 89/12/15 12:10:56 kit Exp $";
3 #endif /* lint && SABER */
5 /***********************************************************
6 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
7 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
11 Permission to use, copy, modify, and distribute this software and its
12 documentation for any purpose and without fee is hereby granted,
13 provided that the above copyright notice appear in all copies and that
14 both that copyright notice and this permission notice appear in
15 supporting documentation, and that the names of Digital or MIT not be
16 used in advertising or publicity pertaining to distribution of the
17 software without specific, written prior permission.
19 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
20 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
21 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
22 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
23 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
27 ******************************************************************/
30 #include <X11/IntrinsicP.h>
31 #include <X11/StringDefs.h>
32 #include <X11/Shell.h>
33 #include <X11/Xatom.h>
35 #include <X11/Xmu/Atoms.h>
36 #include <X11/Xmu/CharSet.h>
37 #include <X11/Xmu/Converters.h>
38 #include <X11/Xmu/StdSel.h>
39 #include <X11/Xmu/Misc.h>
41 #include <./Xaw3_1XawInit.h>
42 #include <./Xaw3_1Cardinals.h>
43 #include <./Xaw3_1Scrollbar.h>
44 #include <./Xaw3_1TextP.h>
48 #define bcopy(a,b,c) memmove(b,a,c)
51 #define bzero(a,b) memset(a,0,b)
57 #define SinkClearToBG XawTextSinkClearToBackground
59 #define SrcScan XawTextSourceScan
60 #define SrcRead XawTextSourceRead
61 #define SrcReplace XawTextSourceReplace
62 #define SrcSearch XawTextSourceSearch
63 #define SrcCvtSel XawTextSourceConvertSelection
64 #define SrcSetSelection XawTextSourceSetSelection
69 extern int errno
, sys_nerr
;
70 extern char* sys_errlist
[];
72 #define BIGNUM ((Dimension)32023)
73 #define MULTI_CLICK_TIME 500L
75 #define IsValidLine(ctx, num) ( ((num) == 0) || \
76 ((ctx)->text.lt.info[(num)].position != 0) )
82 static void VScroll(), VJump(), HScroll(), HJump(), ClearWindow();
83 static void DisplayTextWindow(), ModifySelection();
84 static void UpdateTextInLine(), UpdateTextInRectangle();
85 static Boolean
LineAndXYForPosition();
86 static XawTextPosition
FindGoodPosition(), _BuildLineTable();
88 void _XawTextAlterSelection(), _XawTextExecuteUpdate();
89 void _XawTextBuildLineTable(), _XawTextSetScrollBars();
90 void _XawTextPrepareToUpdate(TextWidget ctx
);
92 /****************************************************************
94 * Full class record constant
96 ****************************************************************/
98 static XawTextSelectType defaultSelectTypes
[] = {
99 XawselectPosition
, XawselectWord
, XawselectLine
, XawselectParagraph
,
100 XawselectAll
, XawselectNull
,
103 static caddr_t defaultSelectTypesPtr
= (caddr_t
)defaultSelectTypes
;
104 extern char *_XawDefaultTextTranslations1
, *_XawDefaultTextTranslations2
,
105 *_XawDefaultTextTranslations3
;
106 static Dimension defWidth
= 100;
107 static Dimension defHeight
= DEFAULT_TEXT_HEIGHT
;
109 #define offset(field) XtOffset(TextWidget, field)
110 static XtResource resources
[] = {
111 {XtNwidth
, XtCWidth
, XtRDimension
, sizeof(Dimension
),
112 offset(core
.width
), XtRDimension
, (caddr_t
)&defWidth
},
113 {XtNcursor
, XtCCursor
, XtRCursor
, sizeof(Cursor
),
114 offset(simple
.cursor
), XtRString
, "xterm"},
115 {XtNheight
, XtCHeight
, XtRDimension
, sizeof(Dimension
),
116 offset(core
.height
), XtRDimension
, (caddr_t
)&defHeight
},
118 {XtNdisplayPosition
, XtCTextPosition
, XtRInt
, sizeof(XawTextPosition
),
119 offset(text
.lt
.top
), XtRImmediate
, (caddr_t
)0},
120 {XtNinsertPosition
, XtCTextPosition
, XtRInt
, sizeof(XawTextPosition
),
121 offset(text
.insertPos
), XtRImmediate
,(caddr_t
)0},
122 {XtNleftMargin
, XtCMargin
, XtRPosition
, sizeof (Position
),
123 offset(text
.r_margin
.left
), XtRImmediate
, (caddr_t
)2},
124 {XtNrightMargin
, XtCMargin
, XtRPosition
, sizeof (Position
),
125 offset(text
.r_margin
.right
), XtRImmediate
, (caddr_t
)4},
126 {XtNtopMargin
, XtCMargin
, XtRPosition
, sizeof (Position
),
127 offset(text
.r_margin
.top
), XtRImmediate
, (caddr_t
)2},
128 {XtNbottomMargin
, XtCMargin
, XtRPosition
, sizeof (Position
),
129 offset(text
.r_margin
.bottom
), XtRImmediate
, (caddr_t
)2},
130 {XtNselectTypes
, XtCSelectTypes
, XtRPointer
,
131 sizeof(XawTextSelectType
*), offset(text
.sarray
),
132 XtRPointer
, (caddr_t
)&defaultSelectTypesPtr
},
133 {XtNtextSource
, XtCTextSource
, XtRWidget
, sizeof (Widget
),
134 offset(text
.source
), XtRImmediate
, NULL
},
135 {XtNtextSink
, XtCTextSink
, XtRWidget
, sizeof (Widget
),
136 offset(text
.sink
), XtRImmediate
, NULL
},
137 {XtNdisplayCaret
, XtCOutput
, XtRBoolean
, sizeof(Boolean
),
138 offset(text
.display_caret
), XtRImmediate
, (caddr_t
)True
},
139 {XtNscrollVertical
, XtCScroll
, XtRScrollMode
, sizeof(XawTextScrollMode
),
140 offset(text
.scroll_vert
), XtRImmediate
, (caddr_t
) XawtextScrollNever
},
141 {XtNscrollHorizontal
, XtCScroll
, XtRScrollMode
, sizeof(XawTextScrollMode
),
142 offset(text
.scroll_horiz
), XtRImmediate
, (caddr_t
) XawtextScrollNever
},
143 {XtNwrap
, XtCWrap
, XtRWrapMode
, sizeof(XawTextWrapMode
),
144 offset(text
.wrap
), XtRImmediate
, (caddr_t
) XawtextWrapNever
},
145 {XtNresize
, XtCResize
, XtRResizeMode
, sizeof(XawTextResizeMode
),
146 offset(text
.resize
), XtRImmediate
, (caddr_t
) XawtextResizeNever
},
147 {XtNautoFill
, XtCAutoFill
, XtRBoolean
, sizeof(Boolean
),
148 offset(text
.auto_fill
), XtRImmediate
, (caddr_t
) FALSE
},
152 * This resource is obsolete.
154 {XtNtextOptions
, XtCTextOptions
, XtRInt
, sizeof (int),
155 offset(text
.options
), XtRImmediate
, (caddr_t
)0},
160 #define done(address, type) \
161 { toVal->size = sizeof(type); toVal->addr = (caddr_t) address; }
165 CvtStringToEditMode(args
, num_args
, fromVal
, toVal
)
166 XrmValuePtr args
; /* unused */
167 Cardinal
*num_args
; /* unused */
171 static XawTextEditType editType
;
172 static XrmQuark QRead
, QAppend
, QEdit
;
174 char lowerName
[BUFSIZ
];
175 static Boolean inited
= FALSE
;
178 QRead
= XrmStringToQuark(XtEtextRead
);
179 QAppend
= XrmStringToQuark(XtEtextAppend
);
180 QEdit
= XrmStringToQuark(XtEtextEdit
);
184 XmuCopyISOLatin1Lowered (lowerName
, (char *)fromVal
->addr
);
185 q
= XrmStringToQuark(lowerName
);
187 if (q
== QRead
) editType
= XawtextRead
;
188 else if (q
== QAppend
) editType
= XawtextAppend
;
189 else if (q
== QEdit
) editType
= XawtextEdit
;
194 done(&editType
, XawTextEditType
);
201 CvtStringToScrollMode(args
, num_args
, fromVal
, toVal
)
202 XrmValuePtr args
; /* unused */
203 Cardinal
*num_args
; /* unused */
207 static XawTextScrollMode scrollMode
;
208 static XrmQuark QScrollNever
, QScrollAlways
, QScrollWhenNeeded
;
210 char lowerName
[BUFSIZ
];
211 static Boolean inited
= FALSE
;
214 QScrollNever
= XrmStringToQuark(XtEtextScrollNever
);
215 QScrollWhenNeeded
= XrmStringToQuark(XtEtextScrollWhenNeeded
);
216 QScrollAlways
= XrmStringToQuark(XtEtextScrollAlways
);
220 XmuCopyISOLatin1Lowered (lowerName
, (char *)fromVal
->addr
);
221 q
= XrmStringToQuark(lowerName
);
223 if (q
== QScrollNever
) scrollMode
= XawtextScrollNever
;
224 else if (q
== QScrollWhenNeeded
) scrollMode
= XawtextScrollWhenNeeded
;
225 else if (q
== QScrollAlways
) scrollMode
= XawtextScrollAlways
;
230 done(&scrollMode
, XawTextScrollMode
);
236 CvtStringToWrapMode(args
, num_args
, fromVal
, toVal
)
237 XrmValuePtr args
; /* unused */
238 Cardinal
*num_args
; /* unused */
242 static XawTextWrapMode wrapMode
;
243 static XrmQuark QWrapNever
, QWrapLine
, QWrapWord
;
245 char lowerName
[BUFSIZ
];
246 static Boolean inited
= FALSE
;
249 QWrapNever
= XrmStringToQuark(XtEtextWrapNever
);
250 QWrapLine
= XrmStringToQuark(XtEtextWrapLine
);
251 QWrapWord
= XrmStringToQuark(XtEtextWrapWord
);
255 XmuCopyISOLatin1Lowered (lowerName
, (char *)fromVal
->addr
);
256 q
= XrmStringToQuark(lowerName
);
258 if (q
== QWrapNever
) wrapMode
= XawtextWrapNever
;
259 else if (q
== QWrapLine
) wrapMode
= XawtextWrapLine
;
260 else if (q
== QWrapWord
) wrapMode
= XawtextWrapWord
;
265 done(&wrapMode
, XawTextWrapMode
);
271 CvtStringToResizeMode(args
, num_args
, fromVal
, toVal
)
272 XrmValuePtr args
; /* unused */
273 Cardinal
*num_args
; /* unused */
277 static XawTextResizeMode resizeMode
;
278 static XrmQuark QResizeNever
, QResizeWidth
, QResizeHeight
, QResizeBoth
;
280 char lowerName
[BUFSIZ
];
281 static Boolean inited
= FALSE
;
284 QResizeNever
= XrmStringToQuark(XtEtextResizeNever
);
285 QResizeWidth
= XrmStringToQuark(XtEtextResizeWidth
);
286 QResizeHeight
= XrmStringToQuark(XtEtextResizeHeight
);
287 QResizeBoth
= XrmStringToQuark(XtEtextResizeBoth
);
291 XmuCopyISOLatin1Lowered (lowerName
, (char *)fromVal
->addr
);
292 q
= XrmStringToQuark(lowerName
);
294 if (q
== QResizeNever
) resizeMode
= XawtextResizeNever
;
295 else if (q
== QResizeWidth
) resizeMode
= XawtextResizeWidth
;
296 else if (q
== QResizeHeight
) resizeMode
= XawtextResizeHeight
;
297 else if (q
== QResizeBoth
) resizeMode
= XawtextResizeBoth
;
302 done(&resizeMode
, XawTextResizeMode
);
311 int len1
= strlen (_XawDefaultTextTranslations1
);
312 int len2
= strlen (_XawDefaultTextTranslations2
);
313 int len3
= strlen (_XawDefaultTextTranslations3
);
314 char *buf
= XtMalloc (len1
+ len2
+ len3
+ 1);
317 XawInitializeWidgetSet();
320 * Set the number of actions.
323 textClassRec
.core_class
.num_actions
= textActionsTableCount
;
325 strcpy (cp
, _XawDefaultTextTranslations1
); cp
+= len1
;
326 strcpy (cp
, _XawDefaultTextTranslations2
); cp
+= len2
;
327 strcpy (cp
, _XawDefaultTextTranslations3
);
328 textWidgetClass
->core_class
.tm_table
= buf
;
330 XtAddConverter(XtRString
, XtREditMode
, CvtStringToEditMode
, NULL
, 0);
331 XtAddConverter(XtRString
, XtRScrollMode
, CvtStringToScrollMode
, NULL
, 0);
332 XtAddConverter(XtRString
, XtRWrapMode
, CvtStringToWrapMode
, NULL
, 0);
333 XtAddConverter(XtRString
, XtRResizeMode
, CvtStringToResizeMode
, NULL
, 0);
336 /* Function Name: PositionHScrollBar.
337 * Description: Positions the Horizontal scrollbar.
338 * Arguments: ctx - the text widget.
343 PositionHScrollBar(ctx
)
346 Widget vbar
= ctx
->text
.vbar
, hbar
= ctx
->text
.hbar
;
347 Position top
, left
= 0;
349 if (ctx
->text
.hbar
== NULL
) return;
352 left
+= (Position
) (vbar
->core
.width
+ vbar
->core
.border_width
);
354 XtResizeWidget( hbar
, ctx
->core
.width
- left
, hbar
->core
.height
,
355 hbar
->core
.border_width
);
357 left
-= (Position
) hbar
->core
.border_width
;
359 top
= ctx
->core
.height
- ( hbar
->core
.height
+ hbar
->core
.border_width
);
360 XtMoveWidget( hbar
, left
, top
);
363 /* Function Name: PositionVScrollBar.
364 * Description: Positions the Vertical scrollbar.
365 * Arguments: ctx - the text widget.
370 PositionVScrollBar(ctx
)
373 Widget vbar
= ctx
->text
.vbar
;
376 if (vbar
== NULL
) return;
377 bw
= vbar
->core
.border_width
;
379 XtResizeWidget( vbar
, vbar
->core
.width
, ctx
->core
.height
, bw
);
380 XtMoveWidget( vbar
, -(Position
)bw
, -(Position
)bw
);
384 CreateVScrollBar(ctx
)
389 if (ctx
->text
.vbar
!= NULL
) return;
391 ctx
->text
.vbar
= vbar
=
392 XtCreateWidget("vScrollbar", scrollbarWidgetClass
, (Widget
)ctx
, NULL
, ZERO
);
393 XtAddCallback( vbar
, XtNscrollProc
, VScroll
, (caddr_t
)ctx
);
394 XtAddCallback( vbar
, XtNjumpProc
, VJump
, (caddr_t
)ctx
);
396 ctx
->text
.r_margin
.left
+= vbar
->core
.width
+ vbar
->core
.border_width
;
397 ctx
->text
.margin
.left
= ctx
->text
.r_margin
.left
;
399 PositionVScrollBar(ctx
);
400 PositionHScrollBar(ctx
); /* May modify location of Horiz. Bar. */
402 if (XtIsRealized((Widget
)ctx
)) {
403 XtRealizeWidget(vbar
);
408 /* Function Name: DestroyVScrollBar
409 * Description: Removes a vertical ScrollBar.
410 * Arguments: ctx - the parent text widget.
415 DestroyVScrollBar(ctx
)
418 Widget vbar
= ctx
->text
.vbar
;
420 if (vbar
== NULL
) return;
422 ctx
->text
.r_margin
.left
-= vbar
->core
.width
+ vbar
->core
.border_width
;
423 ctx
->text
.margin
.left
= ctx
->text
.r_margin
.left
;
424 XtDestroyWidget(vbar
);
425 ctx
->text
.vbar
= NULL
;
426 PositionHScrollBar(ctx
);
430 CreateHScrollBar(ctx
)
436 if (ctx
->text
.hbar
!= NULL
) return;
438 XtSetArg(args
[0], XtNorientation
, XtorientHorizontal
);
439 ctx
->text
.hbar
= hbar
=
440 XtCreateWidget("hScrollbar", scrollbarWidgetClass
, (Widget
)ctx
, args
, ONE
);
441 XtAddCallback( hbar
, XtNscrollProc
, HScroll
, (caddr_t
)ctx
);
442 XtAddCallback( hbar
, XtNjumpProc
, HJump
, (caddr_t
)ctx
);
444 PositionHScrollBar(ctx
);
445 if (XtIsRealized((Widget
)ctx
)) {
446 XtRealizeWidget(hbar
);
451 /* Function Name: DestroyHScrollBar
452 * Description: Removes a horizontal ScrollBar.
453 * Arguments: ctx - the parent text widget.
458 DestroyHScrollBar(ctx
)
461 Widget hbar
= ctx
->text
.hbar
;
463 if (hbar
== NULL
) return;
466 ctx->text.r_margin.bottom -= hbar->core.height + hbar->core.border_width;
467 ctx->text.margin.bottom = ctx->text.r_margin.bottom;
470 XtDestroyWidget(hbar
);
471 ctx
->text
.hbar
= NULL
;
476 Initialize(request
, new, args
, num_args
)
478 ArgList args
; /* unused */
479 Cardinal
*num_args
; /* unused */
481 TextWidget ctx
= (TextWidget
) new;
482 char error_buf
[BUFSIZ
];
485 FMT8BIT
= XInternAtom(XtDisplay(new), "FMT8BIT", False
);
487 ctx
->text
.lt
.lines
= 0;
488 ctx
->text
.lt
.info
= NULL
;
489 bzero((char *) &(ctx
->text
.origSel
), sizeof(XawTextSelection
));
490 bzero((char *) &(ctx
->text
.s
), sizeof(XawTextSelection
));
491 ctx
->text
.s
.type
= XawselectPosition
;
492 ctx
->text
.hbar
= ctx
->text
.vbar
= (Widget
) NULL
;
493 ctx
->text
.lasttime
= 0; /* ||| correct? */
494 ctx
->text
.time
= 0; /* ||| correct? */
495 ctx
->text
.showposition
= TRUE
;
496 ctx
->text
.lastPos
= (ctx
->text
.source
!= NULL
) ? GETLASTPOS
: 0;
497 ctx
->text
.file_insert
= NULL
;
498 ctx
->text
.search
= NULL
;
499 ctx
->text
.updateFrom
= (XawTextPosition
*) XtMalloc(ONE
);
500 ctx
->text
.updateTo
= (XawTextPosition
*) XtMalloc(ONE
);
501 ctx
->text
.numranges
= ctx
->text
.maxranges
= 0;
502 ctx
->text
.gc
= DefaultGCOfScreen(XtScreen(ctx
));
503 ctx
->text
.hasfocus
= FALSE
;
504 ctx
->text
.margin
= ctx
->text
.r_margin
; /* Strucure copy. */
505 ctx
->text
.update_disabled
= FALSE
;
506 ctx
->text
.old_insert
= -1;
508 ctx
->text
.single_char
= FALSE
;
511 /*******************************
512 * For Compatability. */
514 if (ctx
->text
.options
!= 0)
515 XawTextChangeOptions((Widget
) ctx
, ctx
->text
.options
);
516 /*******************************/
519 if (ctx
->core
.height
== DEFAULT_TEXT_HEIGHT
) {
520 ctx
->core
.height
= VMargins(ctx
);
521 if (ctx
->text
.sink
!= NULL
)
522 ctx
->core
.height
+= XawTextSinkMaxHeight(ctx
->text
.sink
, 1);
525 if (ctx
->text
.scroll_vert
!= XawtextScrollNever
)
526 if ( (ctx
->text
.resize
== XawtextResizeHeight
) ||
527 (ctx
->text
.resize
== XawtextResizeBoth
) ) {
528 sprintf(error_buf
, "Text Widget (%s):\n %s %s.", ctx
->core
.name
,
529 "Vertical scrolling not allowed with height resize.\n",
530 "Vertical scrolling has been DEACTIVATED.");
531 XtAppWarning(XtWidgetToApplicationContext(new), error_buf
);
532 ctx
->text
.scroll_vert
= XawtextScrollNever
;
534 else if (ctx
->text
.scroll_vert
== XawtextScrollAlways
)
535 CreateVScrollBar(ctx
);
537 if (ctx
->text
.scroll_horiz
!= XawtextScrollNever
)
538 if (ctx
->text
.wrap
!= XawtextWrapNever
) {
539 sprintf(error_buf
, "Text Widget (%s):\n %s %s.", ctx
->core
.name
,
540 "Horizontal scrolling not allowed with wrapping active.\n",
541 "Horizontal scrolling has been DEACTIVATED.");
542 XtAppWarning(XtWidgetToApplicationContext(new), error_buf
);
543 ctx
->text
.scroll_horiz
= XawtextScrollNever
;
545 else if ( (ctx
->text
.resize
== XawtextResizeWidth
) ||
546 (ctx
->text
.resize
== XawtextResizeBoth
) ) {
547 sprintf(error_buf
, "Text Widget (%s):\n %s %s.", ctx
->core
.name
,
548 "Horizontal scrolling not allowed with width resize.\n",
549 "Horizontal scrolling has been DEACTIVATED.");
550 XtAppWarning(XtWidgetToApplicationContext(new), error_buf
);
551 ctx
->text
.scroll_horiz
= XawtextScrollNever
;
553 else if (ctx
->text
.scroll_horiz
== XawtextScrollAlways
)
554 CreateHScrollBar(ctx
);
558 Realize( w
, valueMask
, attributes
)
561 XSetWindowAttributes
*attributes
;
563 TextWidget ctx
= (TextWidget
)w
;
565 (*textClassRec
.core_class
.superclass
->core_class
.realize
)
566 (w
, valueMask
, attributes
);
568 if (ctx
->text
.hbar
!= NULL
) { /* Put up Hbar -- Must be first. */
569 XtRealizeWidget(ctx
->text
.hbar
);
570 XtMapWidget(ctx
->text
.hbar
);
573 if (ctx
->text
.vbar
!= NULL
) { /* Put up Vbar. */
574 XtRealizeWidget(ctx
->text
.vbar
);
575 XtMapWidget(ctx
->text
.vbar
);
578 _XawTextBuildLineTable(ctx
, ctx
->text
.lt
.top
, TRUE
);
579 _XawTextSetScrollBars(ctx
);
582 /* Utility routines for support of Text */
588 static struct _DisplayRec
{
589 struct _DisplayRec
*next
;
592 struct _DisplayRec
*dpy_ptr
;
594 for (dpy_ptr
= dpy_list
; dpy_ptr
!= NULL
; dpy_ptr
= dpy_ptr
->next
)
595 if (dpy_ptr
->dpy
== d
) return;
597 dpy_ptr
= XtNew(struct _DisplayRec
);
598 dpy_ptr
->next
= dpy_list
;
602 #define Create(buffer) \
603 XChangeProperty(d, RootWindow(d, 0), buffer, XA_STRING, 8, \
604 PropModeAppend, NULL, 0 );
606 Create( XA_CUT_BUFFER0
);
607 Create( XA_CUT_BUFFER1
);
608 Create( XA_CUT_BUFFER2
);
609 Create( XA_CUT_BUFFER3
);
610 Create( XA_CUT_BUFFER4
);
611 Create( XA_CUT_BUFFER5
);
612 Create( XA_CUT_BUFFER6
);
613 Create( XA_CUT_BUFFER7
);
619 * Procedure to manage insert cursor visibility for editable text. It uses
620 * the value of ctx->insertPos and an implicit argument. In the event that
621 * position is immediately preceded by an eol graphic, then the insert cursor
622 * is displayed at the beginning of the next line.
625 InsertCursor (w
, state
)
627 XawTextInsertState state
;
629 TextWidget ctx
= (TextWidget
)w
;
633 if (ctx
->text
.lt
.lines
< 1) return;
635 if ( LineAndXYForPosition(ctx
, ctx
->text
.insertPos
, &line
, &x
, &y
) ) {
636 if (line
< ctx
->text
.lt
.lines
)
637 y
+= (ctx
->text
.lt
.info
[line
+ 1].y
- ctx
->text
.lt
.info
[line
].y
) + 1;
639 y
+= (ctx
->text
.lt
.info
[line
].y
- ctx
->text
.lt
.info
[line
- 1].y
) + 1;
641 if (ctx
->text
.display_caret
)
642 XawTextSinkInsertCursor(ctx
->text
.sink
, x
, y
, state
);
649 * Procedure to register a span of text that is no longer valid on the display
650 * It is used to avoid a number of small, and potentially overlapping, screen
655 _XawTextNeedsUpdating(ctx
, left
, right
)
657 XawTextPosition left
, right
;
661 for (i
= 0; i
< ctx
->text
.numranges
; i
++) {
662 if (left
<= ctx
->text
.updateTo
[i
] && right
>= ctx
->text
.updateFrom
[i
]) {
663 ctx
->text
.updateFrom
[i
] = Min(left
, ctx
->text
.updateFrom
[i
]);
664 ctx
->text
.updateTo
[i
] = Max(right
, ctx
->text
.updateTo
[i
]);
668 ctx
->text
.numranges
++;
669 if (ctx
->text
.numranges
> ctx
->text
.maxranges
) {
670 ctx
->text
.maxranges
= ctx
->text
.numranges
;
671 i
= ctx
->text
.maxranges
* sizeof(XawTextPosition
);
672 ctx
->text
.updateFrom
= (XawTextPosition
*)
673 XtRealloc((char *)ctx
->text
.updateFrom
, (unsigned) i
);
674 ctx
->text
.updateTo
= (XawTextPosition
*)
675 XtRealloc((char *)ctx
->text
.updateTo
, (unsigned) i
);
677 ctx
->text
.updateFrom
[ctx
->text
.numranges
- 1] = left
;
678 ctx
->text
.updateTo
[ctx
->text
.numranges
- 1] = right
;
683 * Procedure to read a span of text in Ascii form. This is purely a hack and
684 * we probably need to add a function to sources to provide this functionality.
685 * [note: this is really a private procedure but is used in multiple modules].
689 _XawTextGetText(ctx
, left
, right
)
691 XawTextPosition left
, right
;
693 char *result
, *tempResult
;
695 Cardinal length
= (Cardinal
) (right
- left
);
697 tempResult
= result
= XtMalloc(length
+ ONE
); /* leave space for '\0'. */
698 while (left
< right
) {
699 left
= SrcRead(ctx
->text
.source
, left
, &text
, right
- left
);
700 (void) strncpy(tempResult
, text
.ptr
, text
.length
);
701 tempResult
+= text
.length
;
703 result
[(int) length
] = '\0'; /* NULL terminate this sucker */
707 /* like _XawTextGetText, but enforces ICCCM STRING type encoding */
710 _XawTextGetSTRING(ctx
, left
, right
)
712 XawTextPosition left
, right
;
714 register unsigned char *s
;
715 register unsigned char c
;
716 register int i
, j
, n
;
718 s
= (unsigned char *)_XawTextGetText(ctx
, left
, right
);
719 /* only HT and NL control chars are allowed, strip out others */
720 n
= strlen((char *)s
);
722 for (j
= 0; j
< n
; j
++) {
724 if (((c
>= 0x20) && c
<= 0x7f) ||
725 (c
>= 0xa0) || (c
== '\t') || (c
== '\n')) {
735 * This routine maps an x and y position in a window that is displaying text
736 * into the corresponding position in the source.
738 * NOTE: it is illegal to call this routine unless there is a valid line table!
741 /*** figure out what line it is on ***/
743 static XawTextPosition
744 PositionForXY (ctx
, x
, y
)
748 int fromx
, line
, width
, height
;
749 XawTextPosition position
;
751 if (ctx
->text
.lt
.lines
== 0) return 0;
753 for (line
= 0; line
< ctx
->text
.lt
.lines
- 1; line
++) {
754 if (y
<= ctx
->text
.lt
.info
[line
+ 1].y
)
757 position
= ctx
->text
.lt
.info
[line
].position
;
758 if (position
>= ctx
->text
.lastPos
)
759 return(ctx
->text
.lastPos
);
760 fromx
= (int) ctx
->text
.margin
.left
;
761 XawTextSinkFindPosition( ctx
->text
.sink
, position
, fromx
, x
- fromx
,
762 FALSE
, &position
, &width
, &height
);
763 if (position
>= ctx
->text
.lt
.info
[line
+ 1].position
)
764 position
= SrcScan(ctx
->text
.source
, ctx
->text
.lt
.info
[line
+ 1].position
,
765 XawstPositions
, XawsdLeft
, 1, TRUE
);
766 if (position
> ctx
->text
.lastPos
) position
= ctx
->text
.lastPos
;
771 * This routine maps a source position in to the corresponding line number
772 * of the text that is displayed in the window.
774 * NOTE: It is illegal to call this routine unless there is a valid line table!
778 LineForPosition (ctx
, position
)
780 XawTextPosition position
;
784 for (line
= 0; line
< ctx
->text
.lt
.lines
; line
++)
785 if (position
< ctx
->text
.lt
.info
[line
+ 1].position
)
791 * This routine maps a source position into the corresponding line number
792 * and the x, y coordinates of the text that is displayed in the window.
794 * NOTE: It is illegal to call this routine unless there is a valid line table!
798 LineAndXYForPosition (ctx
, pos
, line
, x
, y
)
804 XawTextPosition linePos
, endPos
;
809 *x
= ctx
->text
.margin
.left
;
810 *y
= ctx
->text
.margin
.top
;
811 if (visible
= IsPositionVisible(ctx
, pos
)) {
812 *line
= LineForPosition(ctx
, pos
);
813 *y
= ctx
->text
.lt
.info
[*line
].y
;
814 *x
= ctx
->text
.margin
.left
;
815 linePos
= ctx
->text
.lt
.info
[*line
].position
;
816 XawTextSinkFindDistance( ctx
->text
.sink
, linePos
,
817 *x
, pos
, &realW
, &endPos
, &realH
);
824 * This routine builds a line table. It does this by starting at the
825 * specified position and measuring text to determine the staring position
826 * of each line to be displayed. It also determines and saves in the
827 * linetable all the required metrics for displaying a given line (e.g.
828 * x offset, y offset, line length, etc.).
832 _XawTextBuildLineTable (ctx
, position
, force_rebuild
)
834 XawTextPosition position
; /* top. */
835 Boolean force_rebuild
;
837 Dimension height
= 0;
841 if (ctx
->core
.height
> VMargins(ctx
)) {
842 height
= ctx
->core
.height
- VMargins(ctx
);
843 lines
= XawTextSinkMaxLines(ctx
->text
.sink
, height
);
845 size
= sizeof(XawTextLineTableEntry
) * (lines
+ 1);
847 if ( (lines
!= ctx
->text
.lt
.lines
) || (ctx
->text
.lt
.info
== NULL
) ) {
848 ctx
->text
.lt
.info
= (XawTextLineTableEntry
*) XtRealloc((char *) ctx
->text
.
850 ctx
->text
.lt
.lines
= lines
;
851 force_rebuild
= TRUE
;
854 if ( force_rebuild
|| (position
!= ctx
->text
.lt
.top
) ) {
855 bzero((char *) ctx
->text
.lt
.info
, size
);
856 (void) _BuildLineTable(ctx
, ctx
->text
.lt
.top
= position
, zeroPosition
, 0);
861 * This assumes that the line table does not change size.
864 static XawTextPosition
865 _BuildLineTable(ctx
, position
, min_pos
, line
)
867 XawTextPosition position
, min_pos
;
870 XawTextLineTableEntry
* lt
= ctx
->text
.lt
.info
+ line
;
871 XawTextPosition endPos
;
873 int count
, width
, realW
, realH
;
874 Widget src
= ctx
->text
.source
;
876 if ( ((ctx
->text
.resize
== XawtextResizeWidth
) ||
877 (ctx
->text
.resize
== XawtextResizeBoth
) ) ||
878 (ctx
->text
.wrap
== XawtextWrapNever
) )
881 width
= Max(0, (ctx
->core
.width
- HMargins(ctx
)));
883 y
= ( (line
== 0) ? ctx
->text
.margin
.top
: lt
->y
);
887 lt
->position
= position
;
889 XawTextSinkFindPosition( ctx
->text
.sink
, position
, ctx
->text
.margin
.left
,
890 width
, ctx
->text
.wrap
== XawtextWrapWord
,
891 &endPos
, &realW
, &realH
);
892 lt
->textWidth
= realW
;
895 if (ctx
->text
.wrap
== XawtextWrapNever
)
896 endPos
= SrcScan(src
, position
, XawstEOL
, XawsdRight
, 1, TRUE
);
898 if ( endPos
== ctx
->text
.lastPos
) { /* We have reached the end. */
899 if(SrcScan(src
, position
, XawstEOL
, XawsdRight
, 1, FALSE
) == endPos
)
905 if ( (line
> ctx
->text
.lt
.lines
) ||
906 ((lt
->position
== (position
= endPos
)) && (position
> min_pos
)) )
911 * If we are at the end of the buffer put two special lines in the table.
913 * a) Both have position > text.lastPos and lt->textWidth = 0.
914 * b) The first has a real height, and the second has a height that
915 * is the rest of the screen.
917 * I counld fill in the rest of the table with valid heights and a large
918 * lastPos, but this method keeps the number of fill regions down to a
921 * One valid endty is needed at the end of the table so that the cursor
922 * does not jump off the bottom of the window.
925 for ( count
= 0; count
< 2 ; count
++)
926 if (line
++ < ctx
->text
.lt
.lines
) { /* make sure not to run of the end. */
927 (++lt
)->y
= (count
== 0) ? y
: ctx
->core
.height
;
929 lt
->position
= ctx
->text
.lastPos
+ 100;
932 if (line
< ctx
->text
.lt
.lines
) /* Clear out rest of table. */
933 bzero( (char *) (lt
+ 1),
934 (ctx
->text
.lt
.lines
- line
) * sizeof(XawTextLineTableEntry
) );
936 ctx
->text
.lt
.info
[ctx
->text
.lt
.lines
].position
= lt
->position
;
941 /* Function Name: GetWidestLine
942 * Description: Returns the width (in pixels) of the widest line that
943 * is currently visable.
944 * Arguments: ctx - the text widget.
945 * Returns: the width of the widest line.
947 * NOTE: This function requires a valid line table.
956 XawTextLineTablePtr lt
= &(ctx
->text
.lt
);
958 for (i
= 0, widest
= 1 ; i
< lt
->lines
; i
++)
959 if (widest
< lt
->info
[i
].textWidth
)
960 widest
= lt
->info
[i
].textWidth
;
966 CheckVBarScrolling(ctx
)
970 Boolean temp
= (ctx
->text
.vbar
== NULL
);
972 if (ctx
->text
.scroll_vert
== XawtextScrollNever
) return;
974 if ( (ctx
->text
.lastPos
> 0) && (ctx
->text
.lt
.lines
> 0)) {
975 first
= ctx
->text
.lt
.top
;
976 first
/= (float) ctx
->text
.lastPos
;
977 last
= ctx
->text
.lt
.info
[ctx
->text
.lt
.lines
].position
;
978 if ( ctx
->text
.lt
.info
[ctx
->text
.lt
.lines
].position
<= ctx
->text
.lastPos
)
979 last
/= (float) ctx
->text
.lastPos
;
983 if (ctx
->text
.scroll_vert
== XawtextScrollWhenNeeded
)
984 if ( (last
- first
) < 1.0 )
985 CreateVScrollBar(ctx
);
986 else /* last - first >= 1.0 */
987 DestroyVScrollBar(ctx
);
989 if (ctx
->text
.vbar
!= NULL
)
990 XawScrollbarSetThumb(ctx
->text
.vbar
, first
, last
- first
);
992 if ( (ctx
->text
.vbar
== NULL
) != temp
) {
993 _XawTextNeedsUpdating(ctx
, zeroPosition
, ctx
->text
.lastPos
);
994 if (ctx
->text
.vbar
== NULL
)
995 _XawTextBuildLineTable (ctx
, zeroPosition
, FALSE
);
998 else if (ctx
->text
.vbar
!= NULL
)
999 if (ctx
->text
.scroll_vert
== XawtextScrollWhenNeeded
)
1000 DestroyVScrollBar(ctx
);
1001 else if (ctx
->text
.scroll_vert
== XawtextScrollAlways
)
1002 XawScrollbarSetThumb(ctx
->text
.vbar
, 0.0, 1.0);
1006 * This routine is used by Text to notify an associated scrollbar of the
1007 * correct metrics (position and shown fraction) for the text being currently
1008 * displayed in the window.
1012 _XawTextSetScrollBars(ctx
)
1015 float first
, last
, widest
;
1016 Boolean temp
= (ctx
->text
.hbar
== NULL
);
1018 CheckVBarScrolling(ctx
);
1020 if (ctx
->text
.scroll_horiz
== XawtextScrollNever
) return;
1022 if (ctx
->text
.vbar
!= NULL
)
1023 widest
= (ctx
->core
.width
- ctx
->text
.vbar
->core
.width
-
1024 ctx
->text
.vbar
->core
.border_width
);
1026 widest
= ctx
->core
.width
;
1027 widest
/= (last
= GetWidestLine(ctx
));
1028 if (ctx
->text
.scroll_horiz
== XawtextScrollWhenNeeded
)
1030 CreateHScrollBar(ctx
);
1032 DestroyHScrollBar(ctx
);
1034 if (ctx
->text
.hbar
!= NULL
) {
1035 first
= ctx
->text
.r_margin
.left
- ctx
->text
.margin
.left
;
1037 XawScrollbarSetThumb(ctx
->text
.hbar
, first
, widest
);
1039 else if (ctx
->text
.margin
.left
!= ctx
->text
.r_margin
.left
) {
1040 ctx
->text
.margin
.left
= ctx
->text
.r_margin
.left
;
1041 _XawTextNeedsUpdating(ctx
, zeroPosition
, ctx
->text
.lastPos
);
1044 if ( (ctx
->text
.hbar
== NULL
) != temp
) {
1045 _XawTextBuildLineTable (ctx
, ctx
->text
.lt
.top
, TRUE
);
1046 CheckVBarScrolling(ctx
);
1051 * The routine will scroll the displayed text by lines. If the arg is
1052 * positive, move up; otherwise, move down. [note: this is really a private
1053 * procedure but is used in multiple modules].
1057 _XawTextVScroll(ctx
, n
)
1061 XawTextPosition top
, target
;
1063 XawTextLineTable
* lt
= &(ctx
->text
.lt
);
1065 if (abs(n
) > ctx
->text
.lt
.lines
)
1066 n
= (n
> 0) ? ctx
->text
.lt
.lines
: -ctx
->text
.lt
.lines
;
1071 if ( IsValidLine(ctx
, n
) )
1072 top
= Min(lt
->info
[n
].position
, ctx
->text
.lastPos
);
1074 top
= ctx
->text
.lastPos
;
1076 y
= IsValidLine(ctx
, n
) ? lt
->info
[n
].y
: ctx
->core
.height
;
1077 _XawTextBuildLineTable(ctx
, top
, FALSE
);
1078 if (top
>= ctx
->text
.lastPos
)
1079 DisplayTextWindow( (Widget
) ctx
);
1081 XCopyArea(XtDisplay(ctx
), XtWindow(ctx
), XtWindow(ctx
), ctx
->text
.gc
,
1082 0, y
, (int)ctx
->core
.width
, (int)ctx
->core
.height
- y
,
1083 0, ctx
->text
.margin
.top
);
1084 SinkClearToBG(ctx
->text
.sink
,
1086 (Position
) (ctx
->text
.margin
.top
+ ctx
->core
.height
- y
),
1087 (Dimension
) ctx
->core
.width
, (Dimension
) ctx
->core
.height
);
1089 if (n
< lt
->lines
) n
++; /* update descenders at bottom */
1090 _XawTextNeedsUpdating(ctx
, lt
->info
[lt
->lines
- n
].position
,
1092 _XawTextSetScrollBars(ctx
);
1096 XawTextPosition updateTo
;
1097 unsigned int height
, clear_height
;
1101 top
= SrcScan(ctx
->text
.source
, target
, XawstEOL
,
1102 XawsdLeft
, n
+1, FALSE
);
1104 _XawTextBuildLineTable(ctx
, top
, FALSE
);
1105 y
= IsValidLine(ctx
, n
) ? lt
->info
[n
].y
: ctx
->core
.height
;
1106 updateTo
= IsValidLine(ctx
, n
) ? lt
->info
[n
].position
: ctx
->text
.lastPos
;
1107 if (IsValidLine(ctx
, lt
->lines
- n
))
1108 height
= lt
->info
[lt
->lines
-n
].y
- ctx
->text
.margin
.top
;
1109 else if (ctx
->core
.height
- HMargins(ctx
))
1110 height
= ctx
->core
.height
- HMargins(ctx
);
1113 if (y
> (int) ctx
->text
.margin
.top
)
1114 clear_height
= y
- ctx
->text
.margin
.top
;
1118 if ( updateTo
== target
) {
1119 XCopyArea(XtDisplay(ctx
), XtWindow(ctx
), XtWindow(ctx
), ctx
->text
.gc
,
1120 0, ctx
->text
.margin
.top
, (int) ctx
->core
.width
, height
, 0, y
);
1121 SinkClearToBG(ctx
->text
.sink
, (Position
) 0, ctx
->text
.margin
.top
,
1122 (Dimension
) ctx
->core
.width
, (Dimension
) clear_height
);
1124 _XawTextNeedsUpdating(ctx
, lt
->info
[0].position
, updateTo
);
1125 _XawTextSetScrollBars(ctx
);
1127 else if (lt
->top
!= target
)
1128 DisplayTextWindow((Widget
)ctx
);
1134 HScroll(w
, closure
, callData
)
1136 caddr_t closure
; /* TextWidget */
1137 caddr_t callData
; /* #pixels */
1139 TextWidget ctx
= (TextWidget
) closure
;
1140 Widget tw
= (Widget
) ctx
;
1141 Position old_left
, pixels
= (Position
) callData
;
1142 XRectangle rect
, t_rect
;
1144 _XawTextPrepareToUpdate(ctx
);
1146 old_left
= ctx
->text
.margin
.left
;
1147 ctx
->text
.margin
.left
-= pixels
;
1148 if (ctx
->text
.margin
.left
> ctx
->text
.r_margin
.left
) {
1149 ctx
->text
.margin
.left
= ctx
->text
.r_margin
.left
;
1150 pixels
= old_left
- ctx
->text
.margin
.left
;
1154 rect
.width
= (unsigned short) pixels
+ ctx
->text
.margin
.right
;
1155 rect
.x
= (short) ctx
->core
.width
- (short) rect
.width
;
1156 rect
.y
= (short) ctx
->text
.margin
.top
;
1157 rect
.height
= (unsigned short) ctx
->core
.height
- rect
.y
;
1159 XCopyArea(XtDisplay(tw
), XtWindow(tw
), XtWindow(tw
), ctx
->text
.gc
,
1160 pixels
, (int) rect
.y
,
1161 (unsigned int) rect
.x
, (unsigned int) ctx
->core
.height
,
1164 else if (pixels
< 0) {
1167 if (ctx
->text
.vbar
!= NULL
)
1168 rect
.x
+= (short) (ctx
->text
.vbar
->core
.width
+
1169 ctx
->text
.vbar
->core
.border_width
);
1171 rect
.width
= (Position
) - pixels
;
1172 rect
.y
= ctx
->text
.margin
.top
;
1173 rect
.height
= ctx
->core
.height
- rect
.y
;
1175 XCopyArea(XtDisplay(tw
), XtWindow(tw
), XtWindow(tw
), ctx
->text
.gc
,
1176 (int) rect
.x
, (int) rect
.y
,
1177 (unsigned int) ctx
->core
.width
- rect
.width
,
1178 (unsigned int) rect
.height
,
1179 (int) rect
.x
+ rect
.width
, (int) rect
.y
);
1182 * Redraw the line overflow marks.
1185 t_rect
.x
= ctx
->core
.width
- ctx
->text
.margin
.right
;
1186 t_rect
.width
= ctx
->text
.margin
.right
;
1188 t_rect
.height
= rect
.height
;
1190 SinkClearToBG(ctx
->text
.sink
, (Position
) t_rect
.x
, (Position
) t_rect
.y
,
1191 (Dimension
) t_rect
.width
, (Dimension
) t_rect
.height
);
1193 UpdateTextInRectangle(ctx
, &t_rect
);
1197 * Put in the text that just became visable.
1200 if ( pixels
!= 0 ) {
1201 SinkClearToBG(ctx
->text
.sink
, (Position
) rect
.x
, (Position
) rect
.y
,
1202 (Dimension
) rect
.width
, (Dimension
) rect
.height
);
1204 UpdateTextInRectangle(ctx
, &rect
);
1206 _XawTextExecuteUpdate(ctx
);
1207 _XawTextSetScrollBars(ctx
);
1212 HJump(w
, closure
, callData
)
1214 caddr_t closure
, callData
; /* closure = TextWidget, callData = percent. */
1216 TextWidget ctx
= (TextWidget
) closure
;
1217 float * percent
= (float *) callData
;
1218 Position move
, new_left
, old_left
= ctx
->text
.margin
.left
;
1220 new_left
= ctx
->text
.r_margin
.left
;
1221 new_left
-= (Position
) (*percent
* GetWidestLine(ctx
));
1222 move
= old_left
- new_left
;
1224 if (abs(move
) < ctx
->core
.width
) {
1225 HScroll(w
, (caddr_t
) ctx
, (caddr_t
) move
);
1228 _XawTextPrepareToUpdate(ctx
);
1229 ctx
->text
.margin
.left
= new_left
;
1230 if (XtIsRealized((Widget
) ctx
)) DisplayTextWindow((Widget
) ctx
);
1231 _XawTextExecuteUpdate(ctx
);
1234 /* Function Name: UpdateTextInLine
1235 * Description: Updates some text in a given line.
1236 * Arguments: ctx - the text widget.
1237 * line - the line number (in the line table) of this line.
1238 * left, right - left and right pixel offsets of the
1244 UpdateTextInLine(ctx
, line
, left
, right
)
1247 Position left
, right
;
1249 XawTextPosition pos1
, pos2
;
1250 int width
, height
, local_left
, local_width
;
1251 XawTextLineTableEntry
* lt
= ctx
->text
.lt
.info
+ line
;
1253 if ( ((lt
->textWidth
+ ctx
->text
.margin
.left
) < left
) ||
1254 ( ctx
->text
.margin
.left
> right
) )
1255 return; /* no need to update. */
1257 local_width
= left
- ctx
->text
.margin
.left
;
1258 XawTextSinkFindPosition(ctx
->text
.sink
, lt
->position
,
1259 (int) ctx
->text
.margin
.left
,
1260 local_width
, FALSE
, &pos1
, &width
, &height
);
1262 if (right
>= (Position
) lt
->textWidth
- ctx
->text
.margin
.left
)
1263 if ( (IsValidLine(ctx
, line
+ 1)) &&
1264 (ctx
->text
.lt
.info
[line
+ 1].position
<= ctx
->text
.lastPos
) )
1265 pos2
= SrcScan( ctx
->text
.source
, (lt
+ 1)->position
, XawstPositions
,
1266 XawsdLeft
, 1, TRUE
);
1270 XawTextPosition t_pos
;
1272 local_left
= ctx
->text
.margin
.left
+ width
;
1273 local_width
= right
- local_left
;
1274 XawTextSinkFindPosition(ctx
->text
.sink
, pos1
, local_left
,
1275 local_width
, FALSE
, &pos2
, &width
, &height
);
1277 t_pos
= SrcScan( ctx
->text
.source
, pos2
,
1278 XawstPositions
, XawsdRight
, 1, TRUE
);
1279 if (t_pos
< (lt
+ 1)->position
)
1283 _XawTextNeedsUpdating(ctx
, pos1
, pos2
);
1287 * The routine will scroll the displayed text by pixels. If the calldata is
1288 * positive, move up; otherwise, move down.
1293 VScroll(w
, closure
, callData
)
1295 caddr_t closure
; /* TextWidget */
1296 caddr_t callData
; /* #pixels */
1298 TextWidget ctx
= (TextWidget
)closure
;
1299 int height
, lines
= (int) callData
;
1301 height
= ctx
->core
.height
- VMargins(ctx
);
1304 lines
= (int) (lines
* (int) ctx
->text
.lt
.lines
) / height
;
1305 _XawTextPrepareToUpdate(ctx
);
1306 _XawTextVScroll(ctx
, lines
);
1307 _XawTextExecuteUpdate(ctx
);
1311 * The routine "thumbs" the displayed text. Thumbing means reposition the
1312 * displayed view of the source to a new position determined by a fraction
1313 * of the way from beginning to end. Ideally, this should be determined by
1314 * the number of displayable lines in the source. This routine does it as a
1315 * fraction of the first position and last position and then normalizes to
1316 * the start of the line containing the position.
1318 * BUG/deficiency: The normalize to line portion of this routine will
1319 * cause thumbing to always position to the start of the source.
1324 VJump(w
, closure
, callData
)
1326 caddr_t closure
, callData
; /* closuer = TextWidget, callData = percent. */
1328 float * percent
= (float *) callData
;
1329 TextWidget ctx
= (TextWidget
)closure
;
1330 XawTextPosition position
, old_top
, old_bot
;
1331 XawTextLineTable
* lt
= &(ctx
->text
.lt
);
1333 _XawTextPrepareToUpdate(ctx
);
1335 if ( (lt
->lines
> 0) && (IsValidLine(ctx
, lt
->lines
- 1)) )
1336 old_bot
= lt
->info
[lt
->lines
- 1].position
;
1338 old_bot
= ctx
->text
.lastPos
;
1340 position
= (long) (*percent
* (float) ctx
->text
.lastPos
);
1341 position
= SrcScan(ctx
->text
.source
, position
, XawstEOL
, XawsdLeft
, 1, FALSE
);
1342 if ( (position
>= old_top
) && (position
<= old_bot
) ) {
1344 for (;(line
< lt
->lines
) && (position
> lt
->info
[line
].position
) ; line
++);
1345 _XawTextVScroll(ctx
, line
);
1348 XawTextPosition new_bot
;
1349 _XawTextBuildLineTable(ctx
, position
, FALSE
);
1350 new_bot
= IsValidLine(ctx
, lt
->lines
-1) ? lt
->info
[lt
->lines
-1].position
1351 : ctx
->text
.lastPos
;
1353 if ((old_top
>= lt
->top
) && (old_top
<= new_bot
)) {
1355 for (;(line
< lt
->lines
) && (old_top
> lt
->info
[line
].position
); line
++);
1356 _XawTextBuildLineTable(ctx
, old_top
, FALSE
);
1357 _XawTextVScroll(ctx
, -line
);
1360 DisplayTextWindow( (Widget
) ctx
);
1362 _XawTextExecuteUpdate(ctx
);
1367 ConvertSelection(w
, selection
, target
, type
, value
, length
, format
)
1369 Atom
*selection
, *target
, *type
;
1371 unsigned long *length
;
1374 Display
* d
= XtDisplay(w
);
1375 TextWidget ctx
= (TextWidget
)w
;
1376 Widget src
= ctx
->text
.source
;
1377 XawTextEditType edit_mode
;
1380 if (*target
== XA_TARGETS(d
)) {
1381 Atom
* targetP
, * std_targets
;
1382 unsigned long std_length
;
1384 if ( SrcCvtSel(src
, selection
, target
, type
, value
, length
, format
) )
1387 XmuConvertStandardSelection(w
, ctx
->text
.time
, selection
,
1388 target
, type
, (caddr_t
*)&std_targets
,
1389 &std_length
, format
);
1391 *value
= XtMalloc((unsigned) sizeof(Atom
)*(std_length
+ 7));
1392 targetP
= *(Atom
**)value
;
1393 *length
= std_length
+ 6;
1394 *targetP
++ = XA_STRING
;
1395 *targetP
++ = XA_TEXT(d
);
1396 *targetP
++ = XA_COMPOUND_TEXT(d
);
1397 *targetP
++ = XA_LENGTH(d
);
1398 *targetP
++ = XA_LIST_LENGTH(d
);
1399 *targetP
++ = XA_CHARACTER_POSITION(d
);
1401 XtSetArg(args
[0], XtNeditType
,&edit_mode
);
1402 XtGetValues(src
, args
, ONE
);
1404 if (edit_mode
== XawtextEdit
) {
1405 *targetP
++ = XA_DELETE(d
);
1408 bcopy((char*)std_targets
, (char*)targetP
, sizeof(Atom
)*std_length
);
1409 XtFree((char*)std_targets
);
1415 if ( SrcCvtSel(src
, selection
, target
, type
, value
, length
, format
) )
1418 if (*target
== XA_STRING
||
1419 *target
== XA_TEXT(d
) ||
1420 *target
== XA_COMPOUND_TEXT(d
)) {
1421 if (*target
== XA_COMPOUND_TEXT(d
))
1425 *value
= _XawTextGetSTRING(ctx
, ctx
->text
.s
.left
, ctx
->text
.s
.right
);
1426 *length
= strlen(*value
);
1431 if ( (*target
== XA_LIST_LENGTH(d
)) || (*target
== XA_LENGTH(d
)) ) {
1434 temp
= (long *) XtMalloc(sizeof(long));
1435 if (*target
== XA_LIST_LENGTH(d
))
1437 else /* *target == XA_LENGTH(d) */
1438 *temp
= (long) (ctx
->text
.s
.right
- ctx
->text
.s
.left
);
1440 *value
= (caddr_t
) temp
;
1447 if (*target
== XA_CHARACTER_POSITION(d
)) {
1450 temp
= (long *) XtMalloc(2 * sizeof(long));
1451 temp
[0] = (long) (ctx
->text
.s
.left
+ 1);
1452 temp
[1] = ctx
->text
.s
.right
;
1453 *value
= (caddr_t
) temp
;
1460 if (*target
== XA_DELETE(d
)) {
1461 void _XawTextZapSelection(); /* From TextAction.c */
1463 _XawTextZapSelection( ctx
, (XEvent
*) NULL
, TRUE
);
1471 if (XmuConvertStandardSelection(w
, ctx
->text
.time
, selection
, target
, type
,
1472 value
, length
, format
))
1479 /* Function Name: GetCutBuffferNumber
1480 * Description: Returns the number of the cut buffer.
1481 * Arguments: atom - the atom to check.
1482 * Returns: the number of the cut buffer representing this atom or
1486 #define NOT_A_CUT_BUFFER -1
1489 GetCutBufferNumber(atom
)
1492 if (atom
== XA_CUT_BUFFER0
) return(0);
1493 if (atom
== XA_CUT_BUFFER1
) return(1);
1494 if (atom
== XA_CUT_BUFFER2
) return(2);
1495 if (atom
== XA_CUT_BUFFER3
) return(3);
1496 if (atom
== XA_CUT_BUFFER4
) return(4);
1497 if (atom
== XA_CUT_BUFFER5
) return(5);
1498 if (atom
== XA_CUT_BUFFER6
) return(6);
1499 if (atom
== XA_CUT_BUFFER7
) return(7);
1500 return(NOT_A_CUT_BUFFER
);
1504 LoseSelection(w
, selection
)
1508 TextWidget ctx
= (TextWidget
) w
;
1509 register Atom
* atomP
;
1512 _XawTextPrepareToUpdate(ctx
);
1514 atomP
= ctx
->text
.s
.selections
;
1515 for (i
= 0 ; i
< ctx
->text
.s
.atom_count
; i
++, atomP
++)
1516 if ( (*selection
== *atomP
) ||
1517 (GetCutBufferNumber(*atomP
) != NOT_A_CUT_BUFFER
) )/* is a cut buffer */
1520 while (ctx
->text
.s
.atom_count
&&
1521 ctx
->text
.s
.selections
[ctx
->text
.s
.atom_count
-1] == 0)
1522 ctx
->text
.s
.atom_count
--;
1525 * Must walk the selection list in opposite order from UnsetSelection.
1528 atomP
= ctx
->text
.s
.selections
;
1529 for (i
= 0 ; i
< ctx
->text
.s
.atom_count
; i
++, atomP
++)
1530 if (*atomP
== (Atom
)0) {
1531 *atomP
= ctx
->text
.s
.selections
[--ctx
->text
.s
.atom_count
];
1532 while (ctx
->text
.s
.atom_count
&&
1533 ctx
->text
.s
.selections
[ctx
->text
.s
.atom_count
-1] == 0)
1534 ctx
->text
.s
.atom_count
--;
1537 if (ctx
->text
.s
.atom_count
== 0)
1538 ModifySelection(ctx
, ctx
->text
.insertPos
, ctx
->text
.insertPos
);
1540 if (ctx
->text
.old_insert
>= 0) /* Update in progress. */
1541 _XawTextExecuteUpdate(ctx
);
1545 _SetSelection(ctx
, left
, right
, selections
, count
)
1547 XawTextPosition left
, right
;
1551 XawTextPosition pos
;
1553 if (left
< ctx
->text
.s
.left
) {
1554 pos
= Min(right
, ctx
->text
.s
.left
);
1555 _XawTextNeedsUpdating(ctx
, left
, pos
);
1557 if (left
> ctx
->text
.s
.left
) {
1558 pos
= Min(left
, ctx
->text
.s
.right
);
1559 _XawTextNeedsUpdating(ctx
, ctx
->text
.s
.left
, pos
);
1561 if (right
< ctx
->text
.s
.right
) {
1562 pos
= Max(right
, ctx
->text
.s
.left
);
1563 _XawTextNeedsUpdating(ctx
, pos
, ctx
->text
.s
.right
);
1565 if (right
> ctx
->text
.s
.right
) {
1566 pos
= Max(left
, ctx
->text
.s
.right
);
1567 _XawTextNeedsUpdating(ctx
, pos
, right
);
1570 ctx
->text
.s
.left
= left
;
1571 ctx
->text
.s
.right
= right
;
1573 SrcSetSelection(ctx
->text
.source
, left
, right
,
1574 (count
== 0) ? NULL
: selections
[0]);
1577 Widget w
= (Widget
) ctx
;
1581 Atom selection
= selections
[--count
];
1583 * If this is a cut buffer.
1586 if ((buffer
= GetCutBufferNumber(selection
)) != NOT_A_CUT_BUFFER
) {
1588 ptr
= _XawTextGetSTRING(ctx
, ctx
->text
.s
.left
, ctx
->text
.s
.right
);
1590 _CreateCutBuffers(XtDisplay(w
));
1591 XRotateBuffers(XtDisplay(w
), 1);
1593 XStoreBuffer(XtDisplay(w
), ptr
, Min(strlen(ptr
), MAXCUT
), buffer
);
1596 else /* This is a real selection. */
1597 XtOwnSelection(w
, selection
, ctx
->text
.time
,
1598 (XtConvertSelectionProc
)ConvertSelection
,
1599 LoseSelection
, NULL
);
1603 XawTextUnsetSelection((Widget
)ctx
);
1607 * This internal routine deletes the text from pos1 to pos2 in a source and
1608 * then inserts, at pos1, the text that was passed. As a side effect it
1609 * "invalidates" that portion of the displayed text (if any).
1611 * NOTE: It is illegal to call this routine unless there is a valid line table!
1615 _XawTextReplace (ctx
, pos1
, pos2
, text
)
1617 XawTextPosition pos1
, pos2
;
1620 int i
, line1
, delta
, error
;
1621 XawTextPosition updateFrom
, updateTo
;
1622 Widget src
= ctx
->text
.source
;
1623 XawTextEditType edit_mode
;
1626 ctx
->text
.update_disabled
= True
; /* No redisplay during replacement. */
1629 * The insertPos may not always be set to the right spot in XawtextAppend
1632 XtSetArg(args
[0], XtNeditType
, &edit_mode
);
1633 XtGetValues(src
, args
, ONE
);
1635 if ((pos1
== ctx
->text
.insertPos
) && (edit_mode
== XawtextAppend
)) {
1636 ctx
->text
.insertPos
= ctx
->text
.lastPos
;
1637 pos2
= SrcScan(src
, ctx
->text
.insertPos
, XawstPositions
, XawsdRight
,
1638 (ctx
->text
.insertPos
- pos1
), TRUE
);
1639 pos1
= ctx
->text
.insertPos
;
1640 if ( (pos1
== pos2
) && (text
->length
== 0) ) {
1641 ctx
->text
.update_disabled
= FALSE
; /* rearm redisplay. */
1642 return( XawEditError
);
1646 updateFrom
= SrcScan(src
, pos1
, XawstWhiteSpace
, XawsdLeft
, 1, TRUE
);
1647 updateFrom
= SrcScan(src
, updateFrom
, XawstPositions
, XawsdLeft
, 1, TRUE
);
1648 updateFrom
= Max(updateFrom
, ctx
->text
.lt
.top
);
1650 line1
= LineForPosition(ctx
, updateFrom
);
1651 if ( (error
= SrcReplace(src
, pos1
, pos2
, text
)) != 0) {
1652 ctx
->text
.update_disabled
= FALSE
; /* rearm redisplay. */
1656 XawTextUnsetSelection((Widget
)ctx
);
1658 ctx
->text
.lastPos
= GETLASTPOS
;
1659 if (ctx
->text
.lt
.top
>= ctx
->text
.lastPos
) {
1660 _XawTextBuildLineTable(ctx
, ctx
->text
.lastPos
, FALSE
);
1661 ClearWindow( (Widget
) ctx
);
1662 ctx
->text
.update_disabled
= FALSE
; /* rearm redisplay. */
1663 return(0); /* Things are fine. */
1666 delta
= text
->length
- (pos2
- pos1
);
1668 if ( abs(delta
) <= 1 )
1669 ctx
->text
.single_char
= TRUE
;
1671 ctx
->text
.single_char
= FALSE
;
1673 if (delta
< ctx
->text
.lastPos
) {
1674 for (pos2
+= delta
, i
= 0; i
< ctx
->text
.numranges
; i
++) {
1675 if (ctx
->text
.updateFrom
[i
] > pos1
)
1676 ctx
->text
.updateFrom
[i
] += delta
;
1677 if (ctx
->text
.updateTo
[i
] >= pos1
)
1678 ctx
->text
.updateTo
[i
] += delta
;
1683 * fixup all current line table entries to reflect edit.
1684 * %%% it is not legal to do arithmetic on positions.
1685 * using Scan would be more proper.
1688 XawTextLineTableEntry
*lineP
;
1689 i
= LineForPosition(ctx
, pos1
) + 1;
1690 for (lineP
= ctx
->text
.lt
.info
+ i
; i
<= ctx
->text
.lt
.lines
; i
++, lineP
++)
1691 lineP
->position
+= delta
;
1695 * Now process the line table and fixup in case edits caused
1696 * changes in line breaks. If we are breaking on word boundaries,
1697 * this code checks for moving words to and from lines.
1700 if (IsPositionVisible(ctx
, updateFrom
)) {
1701 updateTo
= _BuildLineTable(ctx
,
1702 ctx
->text
.lt
.info
[line1
].position
, pos1
, line1
);
1703 _XawTextNeedsUpdating(ctx
, updateFrom
, updateTo
);
1706 ctx
->text
.update_disabled
= FALSE
; /* rearm redisplay. */
1707 return(0); /* Things are fine. */
1711 * This routine will display text between two arbitrary source positions.
1712 * In the event that this span contains highlighted text for the selection,
1713 * only that portion will be displayed highlighted.
1715 * NOTE: it is illegal to call this routine unless there
1716 * is a valid line table!
1720 DisplayText(w
, pos1
, pos2
)
1722 XawTextPosition pos1
, pos2
;
1724 TextWidget ctx
= (TextWidget
)w
;
1726 int height
, line
, i
, lastPos
= ctx
->text
.lastPos
;
1727 XawTextPosition startPos
, endPos
;
1728 Boolean clear_eol
, done_painting
;
1730 pos1
= (pos1
< ctx
->text
.lt
.top
) ? ctx
->text
.lt
.top
: pos1
;
1731 pos2
= FindGoodPosition(ctx
, pos2
);
1732 if ( (pos1
>= pos2
) || !LineAndXYForPosition(ctx
, pos1
, &line
, &x
, &y
) )
1733 return; /* line not visible, or pos1 >= pos2. */
1735 for ( startPos
= pos1
, i
= line
; IsValidLine(ctx
, i
) &&
1736 (i
< ctx
->text
.lt
.lines
) ; i
++) {
1739 if ( (endPos
= ctx
->text
.lt
.info
[i
+ 1].position
) > pos2
) {
1740 clear_eol
= ((endPos
= pos2
) >= lastPos
);
1741 done_painting
= (!clear_eol
|| ctx
->text
.single_char
);
1745 done_painting
= FALSE
;
1748 height
= ctx
->text
.lt
.info
[i
+ 1].y
- ctx
->text
.lt
.info
[i
].y
;
1750 if ( (endPos
> startPos
) ) {
1751 if ( (x
== (Position
) ctx
->text
.margin
.left
) && (x
> 0) )
1752 SinkClearToBG (ctx
->text
.sink
,
1754 (Dimension
) ctx
->text
.margin
.left
, (Dimension
)height
);
1756 if ( (startPos
>= ctx
->text
.s
.right
) || (endPos
<= ctx
->text
.s
.left
) )
1757 XawTextSinkDisplayText(ctx
->text
.sink
, x
, y
, startPos
, endPos
, FALSE
);
1758 else if ((startPos
>= ctx
->text
.s
.left
) && (endPos
<= ctx
->text
.s
.right
))
1759 XawTextSinkDisplayText(ctx
->text
.sink
, x
, y
, startPos
, endPos
, TRUE
);
1761 DisplayText(w
, startPos
, ctx
->text
.s
.left
);
1762 DisplayText(w
, Max(startPos
, ctx
->text
.s
.left
),
1763 Min(endPos
, ctx
->text
.s
.right
));
1764 DisplayText(w
, ctx
->text
.s
.right
, endPos
);
1769 SinkClearToBG(ctx
->text
.sink
,
1770 (Position
) (ctx
->text
.lt
.info
[i
].textWidth
+
1771 ctx
->text
.margin
.left
),
1772 (Position
) y
, w
->core
.width
, (Dimension
) height
);
1775 * We only get here if single character is true, and we need
1776 * to clear to the end of the screen. We know that since there
1777 * was only on character deleted that this is the same
1778 * as clearing an extra line, so we do this, and are done.
1780 * This a performance hack, and a pretty gross one, but it works.
1782 * Chris Peterson 11/13/89.
1785 if (done_painting
) {
1787 SinkClearToBG(ctx
->text
.sink
,
1788 (Position
) ctx
->text
.margin
.left
, (Position
) y
,
1789 w
->core
.width
, (Dimension
) height
);
1791 break; /* set single_char to FALSE and return. */
1795 x
= (Position
) ctx
->text
.margin
.left
;
1796 y
= ctx
->text
.lt
.info
[i
+ 1].y
;
1797 if ( done_painting
|| (y
>= ctx
->core
.height
- ctx
->text
.margin
.bottom
) )
1800 ctx
->text
.single_char
= FALSE
;
1804 * This routine implements multi-click selection in a hardwired manner.
1805 * It supports multi-click entity cycling (char, word, line, file) and mouse
1806 * motion adjustment of the selected entitie (i.e. select a word then, with
1807 * button still down, adjust wich word you really meant by moving the mouse).
1808 * [NOTE: This routine is to be replaced by a set of procedures that
1809 * will allows clients to implements a wide class of draw through and
1810 * multi-click selection user interfaces.]
1814 DoSelection (ctx
, pos
, time
, motion
)
1816 XawTextPosition pos
;
1820 XawTextPosition newLeft
, newRight
;
1821 XawTextSelectType newType
, *sarray
;
1822 Widget src
= ctx
->text
.source
;
1825 newType
= ctx
->text
.s
.type
;
1827 if ( (abs((long) time
- (long) ctx
->text
.lasttime
) < MULTI_CLICK_TIME
) &&
1828 ((pos
>= ctx
->text
.s
.left
) && (pos
<= ctx
->text
.s
.right
))) {
1829 sarray
= ctx
->text
.sarray
;
1830 for (;*sarray
!= XawselectNull
&& *sarray
!= ctx
->text
.s
.type
; sarray
++);
1832 if (*sarray
== XawselectNull
)
1833 newType
= *(ctx
->text
.sarray
);
1835 newType
= *(sarray
+ 1);
1836 if (newType
== XawselectNull
)
1837 newType
= *(ctx
->text
.sarray
);
1840 else /* single-click event */
1841 newType
= *(ctx
->text
.sarray
);
1843 ctx
->text
.lasttime
= time
;
1846 case XawselectPosition
:
1847 newLeft
= newRight
= pos
;
1851 newRight
= SrcScan(src
, pos
, XawstPositions
, XawsdRight
, 1, FALSE
);
1854 newRight
= SrcScan(src
, pos
, XawstWhiteSpace
, XawsdRight
, 1, FALSE
);
1855 newLeft
= SrcScan(src
, newRight
, XawstWhiteSpace
, XawsdLeft
, 1, FALSE
);
1857 case XawselectParagraph
:
1858 newRight
= SrcScan(src
, pos
, XawstParagraph
, XawsdRight
, 1, FALSE
);
1859 newLeft
= SrcScan(src
, newRight
, XawstParagraph
, XawsdLeft
, 1, FALSE
);
1862 newLeft
= SrcScan(src
, pos
, XawstEOL
, XawsdLeft
, 1, FALSE
);
1863 newRight
= SrcScan(src
, pos
, XawstEOL
, XawsdRight
, 1, FALSE
);
1866 newLeft
= SrcScan(src
, pos
, XawstAll
, XawsdLeft
, 1, FALSE
);
1867 newRight
= SrcScan(src
, pos
, XawstAll
, XawsdRight
, 1, FALSE
);
1870 XtAppWarning(XtWidgetToApplicationContext((Widget
) ctx
),
1871 "Text Widget: empty selection array.");
1875 if ( (newLeft
!= ctx
->text
.s
.left
) || (newRight
!= ctx
->text
.s
.right
)
1876 || (newType
!= ctx
->text
.s
.type
)) {
1877 ModifySelection(ctx
, newLeft
, newRight
);
1878 if (pos
- ctx
->text
.s
.left
< ctx
->text
.s
.right
- pos
)
1879 ctx
->text
.insertPos
= newLeft
;
1881 ctx
->text
.insertPos
= newRight
;
1882 ctx
->text
.s
.type
= newType
;
1884 if (!motion
) { /* setup so we can freely mix select extend calls*/
1885 ctx
->text
.origSel
.type
= ctx
->text
.s
.type
;
1886 ctx
->text
.origSel
.left
= ctx
->text
.s
.left
;
1887 ctx
->text
.origSel
.right
= ctx
->text
.s
.right
;
1889 if (pos
>= ctx
->text
.s
.left
+ ((ctx
->text
.s
.right
- ctx
->text
.s
.left
) / 2))
1890 ctx
->text
.extendDir
= XawsdRight
;
1892 ctx
->text
.extendDir
= XawsdLeft
;
1897 * This routine implements extension of the currently selected text in
1898 * the "current" mode (i.e. char word, line, etc.). It worries about
1899 * extending from either end of the selection and handles the case when you
1900 * cross through the "center" of the current selection (e.g. switch which
1901 * end you are extending!).
1902 * [NOTE: This routine will be replaced by a set of procedures that
1903 * will allows clients to implements a wide class of draw through and
1904 * multi-click selection user interfaces.]
1908 ExtendSelection (ctx
, pos
, motion
)
1910 XawTextPosition pos
;
1913 XawTextScanDirection dir
;
1915 if (!motion
) { /* setup for extending selection */
1916 ctx
->text
.origSel
.type
= ctx
->text
.s
.type
;
1917 ctx
->text
.origSel
.left
= ctx
->text
.s
.left
;
1918 ctx
->text
.origSel
.right
= ctx
->text
.s
.right
;
1919 if (pos
>= ctx
->text
.s
.left
+ ((ctx
->text
.s
.right
- ctx
->text
.s
.left
) / 2))
1920 ctx
->text
.extendDir
= XawsdRight
;
1922 ctx
->text
.extendDir
= XawsdLeft
;
1924 else /* check for change in extend direction */
1925 if ((ctx
->text
.extendDir
== XawsdRight
&& pos
< ctx
->text
.origSel
.left
) ||
1926 (ctx
->text
.extendDir
== XawsdLeft
&& pos
> ctx
->text
.origSel
.right
)) {
1927 ctx
->text
.extendDir
= (ctx
->text
.extendDir
== XawsdRight
) ?
1928 XawsdLeft
: XawsdRight
;
1929 ModifySelection(ctx
, ctx
->text
.origSel
.left
, ctx
->text
.origSel
.right
);
1932 dir
= ctx
->text
.extendDir
;
1933 switch (ctx
->text
.s
.type
) {
1935 pos
= SrcScan(ctx
->text
.source
, pos
, XawstWhiteSpace
, dir
, 1, FALSE
);
1938 pos
= SrcScan(ctx
->text
.source
, pos
, XawstEOL
, dir
, 1, dir
== XawsdRight
);
1940 case XawselectParagraph
:
1941 pos
= SrcScan(ctx
->text
.source
, pos
, XawstParagraph
, dir
, 1, FALSE
);
1944 pos
= ctx
->text
.insertPos
;
1945 case XawselectPosition
: /* fall through. */
1950 if (ctx
->text
.extendDir
== XawsdRight
)
1951 ModifySelection(ctx
, ctx
->text
.s
.left
, pos
);
1953 ModifySelection(ctx
, pos
, ctx
->text
.s
.right
);
1955 ctx
->text
.insertPos
= pos
;
1959 * Clear the window to background color.
1966 TextWidget ctx
= (TextWidget
) w
;
1968 if (XtIsRealized(w
))
1969 SinkClearToBG(ctx
->text
.sink
,
1970 (Position
) 0, (Position
) 0,
1971 w
->core
.width
, w
->core
.height
);
1974 /* Function Name: _XawTextClearAndCenterDisplay
1975 * Description: Redraws the display with the cursor in insert point
1976 * centered vertically.
1977 * Arguments: ctx - the text widget.
1982 _XawTextClearAndCenterDisplay(ctx
)
1985 int insert_line
= LineForPosition(ctx
, ctx
->text
.insertPos
);
1986 int scroll_by
= insert_line
- ctx
->text
.lt
.lines
/2;
1988 _XawTextVScroll(ctx
, scroll_by
);
1989 DisplayTextWindow( (Widget
) ctx
);
1993 * Internal redisplay entire window.
1994 * Legal to call only if widget is realized.
1998 DisplayTextWindow (w
)
2001 TextWidget ctx
= (TextWidget
) w
;
2003 _XawTextBuildLineTable(ctx
, ctx
->text
.lt
.top
, FALSE
);
2004 _XawTextNeedsUpdating(ctx
, zeroPosition
, ctx
->text
.lastPos
);
2005 _XawTextSetScrollBars(ctx
);
2009 * This routine checks to see if the window should be resized (grown or
2010 * shrunk) when text to be painted overflows to the right or
2011 * the bottom of the window. It is used by the keyboard input routine.
2015 _XawTextCheckResize(ctx
)
2018 Widget w
= (Widget
) ctx
;
2019 int line
= 0, old_height
;
2020 XtWidgetGeometry rbox
;
2022 if ( (ctx
->text
.resize
== XawtextResizeWidth
) ||
2023 (ctx
->text
.resize
== XawtextResizeBoth
) ) {
2024 XawTextLineTableEntry
*lt
;
2026 for (lt
= ctx
->text
.lt
.info
;
2027 IsValidLine(ctx
, line
) && (line
< ctx
->text
.lt
.lines
) ; line
++, lt
++)
2028 AssignMax(rbox
.width
, lt
->textWidth
+ ctx
->text
.margin
.left
);
2030 rbox
.width
+= ctx
->text
.margin
.right
;
2031 if (rbox
.width
> ctx
->core
.width
) { /* Only get wider. */
2032 rbox
.request_mode
= CWWidth
;
2033 if (XtMakeGeometryRequest(w
, &rbox
, &rbox
) == XtGeometryAlmost
)
2034 (void) XtMakeGeometryRequest(w
, &rbox
, &rbox
);
2038 if ( !((ctx
->text
.resize
== XawtextResizeHeight
) ||
2039 (ctx
->text
.resize
== XawtextResizeBoth
)) )
2042 if (IsPositionVisible(ctx
, ctx
->text
.lastPos
))
2043 line
= LineForPosition(ctx
, ctx
->text
.lastPos
);
2045 line
= ctx
->text
.lt
.lines
;
2047 if ( (line
+ 1) == ctx
->text
.lt
.lines
) return;
2049 old_height
= ctx
->core
.height
;
2050 rbox
.request_mode
= CWHeight
;
2051 rbox
.height
= XawTextSinkMaxHeight(ctx
->text
.sink
, line
+ 1) + VMargins(ctx
);
2053 if (rbox
.height
< old_height
) return; /* It will only get taller. */
2055 if (XtMakeGeometryRequest(w
, &rbox
, &rbox
) == XtGeometryAlmost
)
2056 if (XtMakeGeometryRequest(w
, &rbox
, &rbox
) != XtGeometryYes
)
2059 _XawTextBuildLineTable(ctx
, ctx
->text
.lt
.top
, TRUE
);
2063 * Converts (params, num_params) to a list of atoms & caches the
2064 * list in the TextWidget instance.
2068 _XawTextSelectionList(ctx
, list
, nelems
)
2073 Atom
* sel
= ctx
->text
.s
.selections
;
2075 if (nelems
> ctx
->text
.s
.array_size
) {
2076 sel
= (Atom
*) XtRealloc((caddr_t
)sel
, sizeof(Atom
) * nelems
);
2077 ctx
->text
.s
.array_size
= nelems
;
2079 XmuInternStrings(XtDisplay((Widget
)ctx
), list
, nelems
, sel
);
2080 ctx
->text
.s
.atom_count
= nelems
;
2081 return(ctx
->text
.s
.selections
= sel
);
2084 /* Function Name: SetSelection
2085 * Description: Sets the current selection.
2086 * Arguments: ctx - the text widget.
2087 * defaultSel - the default selection.
2088 * l, r - the left and right ends of the selection.
2089 * list, nelems - the selection list (as strings).
2092 * NOTE: if (ctx->text.s.left >= ctx->text.s.right) then the selection
2097 _XawTextSetSelection(ctx
, l
, r
, list
, nelems
)
2099 XawTextPosition l
, r
;
2104 String defaultSel
= "PRIMARY";
2108 _SetSelection(ctx
, l
, r
, _XawTextSelectionList(ctx
, list
, nelems
), nelems
);
2112 /* Function Name: ModifySelection
2113 * Description: Modifies the current selection.
2114 * Arguments: ctx - the text widget.
2115 * left, right - the left and right ends of the selection.
2118 * NOTE: if (ctx->text.s.left >= ctx->text.s.right) then the selection
2123 ModifySelection(ctx
, left
, right
)
2125 XawTextPosition left
, right
;
2128 ctx
->text
.insertPos
= left
;
2129 _SetSelection( ctx
, left
, right
, (Atom
*)NULL
, ZERO
);
2133 * This routine is used to perform various selection functions. The goal is
2134 * to be able to specify all the more popular forms of draw-through and
2135 * multi-click selection user interfaces from the outside.
2139 _XawTextAlterSelection (ctx
, mode
, action
, params
, num_params
)
2141 XawTextSelectionMode mode
; /* {XawsmTextSelect, XawsmTextExtend} */
2142 XawTextSelectionAction action
; /* {XawactionStart,
2143 XawactionAdjust, XawactionEnd} */
2145 Cardinal
*num_params
;
2147 XawTextPosition position
;
2151 * This flag is used by TextPop.c:DoReplace() to determine if the selection
2152 * is okay to use, or if it has been modified.
2155 if (ctx
->text
.search
!= NULL
)
2156 ctx
->text
.search
->selection_changed
= TRUE
;
2158 position
= PositionForXY (ctx
, (int) ctx
->text
.ev_x
, (int) ctx
->text
.ev_y
);
2160 flag
= (action
!= XawactionStart
);
2161 if (mode
== XawsmTextSelect
)
2162 DoSelection (ctx
, position
, ctx
->text
.time
, flag
);
2163 else /* mode == XawsmTextExtend */
2164 ExtendSelection (ctx
, position
, flag
);
2166 if (action
== XawactionEnd
)
2167 _XawTextSetSelection(ctx
, ctx
->text
.s
.left
, ctx
->text
.s
.right
,
2168 params
, *num_params
);
2171 /* Function Name: RectanglesOverlap
2172 * Description: Returns TRUE if two rectangles overlap.
2173 * Arguments: rect1, rect2 - the two rectangles to check.
2174 * Returns: TRUE iff these rectangles overlap.
2178 RectanglesOverlap(rect1
, rect2
)
2179 XRectangle
*rect1
, *rect2
;
2181 return ( (rect1
->x
< rect2
->x
+ (short) rect2
->width
) &&
2182 (rect2
->x
< rect1
->x
+ (short) rect1
->width
) &&
2183 (rect1
->y
< rect2
->y
+ (short) rect2
->height
) &&
2184 (rect2
->y
< rect1
->y
+ (short) rect1
->height
) );
2187 /* Function Name: UpdateTextInRectangle.
2188 * Description: Updates the text in a rectangle.
2189 * Arguments: ctx - the text widget.
2190 * rect - the rectangle to update.
2195 UpdateTextInRectangle(ctx
, rect
)
2199 XawTextLineTableEntry
*info
= ctx
->text
.lt
.info
;
2200 int line
, x
= rect
->x
, y
= rect
->y
;
2201 int right
= rect
->width
+ x
, bottom
= rect
->height
+ y
;
2203 for (line
= 0;( (line
< ctx
->text
.lt
.lines
) &&
2204 IsValidLine(ctx
, line
) && (info
->y
< bottom
)); line
++, info
++)
2205 if ( (info
+ 1)->y
>= y
)
2206 UpdateTextInLine(ctx
, line
, x
, right
);
2210 * This routine processes all "expose region" XEvents. In general, its job
2211 * is to the best job at minimal re-paint of the text, displayed in the
2212 * window, that it can.
2217 ProcessExposeRegion(w
, event
, region
)
2220 Region region
; /* Unused. */
2222 TextWidget ctx
= (TextWidget
) w
;
2223 XRectangle expose
, cursor
;
2225 if (event
->type
== Expose
) {
2226 expose
.x
= event
->xexpose
.x
;
2227 expose
.y
= event
->xexpose
.y
;
2228 expose
.width
= event
->xexpose
.width
;
2229 expose
.height
= event
->xexpose
.height
;
2231 else { /* Graphics Expose. */
2232 expose
.x
= event
->xgraphicsexpose
.x
;
2233 expose
.y
= event
->xgraphicsexpose
.y
;
2234 expose
.width
= event
->xgraphicsexpose
.width
;
2235 expose
.height
= event
->xgraphicsexpose
.height
;
2238 _XawTextPrepareToUpdate(ctx
);
2239 UpdateTextInRectangle(ctx
, &expose
);
2240 XawTextSinkGetCursorBounds(ctx
->text
.sink
, &cursor
);
2241 if (RectanglesOverlap(&cursor
, &expose
)) {
2242 SinkClearToBG(ctx
->text
.sink
, (Position
) cursor
.x
, (Position
) cursor
.y
,
2243 (Dimension
) cursor
.width
, (Dimension
) cursor
.height
);
2244 UpdateTextInRectangle(ctx
, &cursor
);
2246 _XawTextExecuteUpdate(ctx
);
2250 * This routine does all setup required to syncronize batched screen updates
2254 _XawTextPrepareToUpdate(ctx
)
2257 if (ctx
->text
.old_insert
< 0) {
2258 InsertCursor((Widget
)ctx
, XawisOff
);
2259 ctx
->text
.numranges
= 0;
2260 ctx
->text
.showposition
= FALSE
;
2261 ctx
->text
.old_insert
= ctx
->text
.insertPos
;
2266 * This is a private utility routine used by _XawTextExecuteUpdate. It
2267 * processes all the outstanding update requests and merges update
2268 * ranges where possible.
2272 void FlushUpdate(ctx
)
2276 XawTextPosition updateFrom
, updateTo
;
2277 if (!XtIsRealized((Widget
)ctx
)) {
2278 ctx
->text
.numranges
= 0;
2281 while (ctx
->text
.numranges
> 0) {
2282 updateFrom
= ctx
->text
.updateFrom
[0];
2284 for (i
= 1 ; i
< ctx
->text
.numranges
; i
++) {
2285 if (ctx
->text
.updateFrom
[i
] < updateFrom
) {
2286 updateFrom
= ctx
->text
.updateFrom
[i
];
2290 updateTo
= ctx
->text
.updateTo
[w
];
2291 ctx
->text
.numranges
--;
2292 ctx
->text
.updateFrom
[w
] = ctx
->text
.updateFrom
[ctx
->text
.numranges
];
2293 ctx
->text
.updateTo
[w
] = ctx
->text
.updateTo
[ctx
->text
.numranges
];
2294 for (i
= ctx
->text
.numranges
- 1 ; i
>= 0 ; i
--) {
2295 while (ctx
->text
.updateFrom
[i
] <= updateTo
&& i
< ctx
->text
.numranges
) {
2296 updateTo
= ctx
->text
.updateTo
[i
];
2297 ctx
->text
.numranges
--;
2298 ctx
->text
.updateFrom
[i
] = ctx
->text
.updateFrom
[ctx
->text
.numranges
];
2299 ctx
->text
.updateTo
[i
] = ctx
->text
.updateTo
[ctx
->text
.numranges
];
2302 DisplayText((Widget
)ctx
, updateFrom
, updateTo
);
2307 * This is a private utility routine used by _XawTextExecuteUpdate. This
2308 * routine worries about edits causing new data or the insertion point becoming
2309 * invisible (off the screen, or under the horiz. scrollbar). Currently
2310 * it always makes it visible by scrolling. It probably needs
2311 * generalization to allow more options.
2314 void _XawTextShowPosition(ctx
)
2317 int x
, y
, number
, lines
;
2318 XawTextPosition max_pos
, top
, first
, second
;
2320 if ( (!XtIsRealized((Widget
)ctx
)) || (ctx
->text
.lt
.lines
<= 0) )
2324 lines
= ctx
->text
.lt
.lines
;
2325 if ( IsValidLine(ctx
, lines
))
2326 max_pos
= ctx
->text
.lt
.info
[lines
].position
;
2328 max_pos
= ctx
->text
.lastPos
+ 1;
2329 #else /* Using this code now... */
2332 * Find out the bottom the visable window, and make sure that the
2333 * cursor does not go past the end of this space.
2335 * This makes sure that the cursor does not go past the end of the
2339 x
= ctx
->text
.margin
.left
;
2340 y
= ctx
->core
.height
- ctx
->text
.margin
.left
;
2341 if (ctx
->text
.hbar
!= NULL
)
2342 y
-= ctx
->text
.hbar
->core
.height
- 2 * ctx
->text
.hbar
->core
.border_width
;
2344 max_pos
= PositionForXY (ctx
, x
, y
);
2345 max_pos
= SrcScan(ctx
->text
.source
, max_pos
, XawstEOL
, XawsdRight
, 1, FALSE
);
2347 lines
= LineForPosition(ctx
, max_pos
); /* number of visable lines. */
2350 if ( (ctx
->text
.insertPos
>= ctx
->text
.lt
.top
) &&
2351 ((ctx
->text
.insertPos
< max_pos
) || ( max_pos
> ctx
->text
.lastPos
)) )
2354 first
= ctx
->text
.lt
.top
;
2355 if (IsValidLine(ctx
, 1))
2356 second
= ctx
->text
.lt
.info
[1].position
;
2360 if (ctx
->text
.insertPos
< first
)
2365 top
= SrcScan(ctx
->text
.source
, ctx
->text
.insertPos
,
2366 XawstEOL
, XawsdLeft
, number
, FALSE
);
2368 _XawTextBuildLineTable(ctx
, top
, FALSE
);
2369 while (ctx
->text
.insertPos
>= ctx
->text
.lt
.info
[lines
].position
) {
2370 if (ctx
->text
.lt
.info
[lines
].position
> ctx
->text
.lastPos
)
2372 _XawTextBuildLineTable(ctx
, ctx
->text
.lt
.info
[1].position
, FALSE
);
2374 if (ctx
->text
.lt
.top
== second
) {
2375 _XawTextBuildLineTable(ctx
, first
, FALSE
);
2376 _XawTextVScroll(ctx
, 1);
2377 } else if (ctx
->text
.lt
.info
[1].position
== first
) {
2378 _XawTextBuildLineTable(ctx
, first
, FALSE
);
2379 _XawTextVScroll(ctx
, -1);
2381 ctx
->text
.numranges
= 0;
2382 if (ctx
->text
.lt
.top
!= first
)
2383 DisplayTextWindow((Widget
)ctx
);
2388 * This routine causes all batched screen updates to be performed
2392 _XawTextExecuteUpdate(ctx
)
2395 if ( ctx
->text
.update_disabled
|| (ctx
->text
.old_insert
< 0) )
2398 if((ctx
->text
.old_insert
!= ctx
->text
.insertPos
) || (ctx
->text
.showposition
))
2399 _XawTextShowPosition(ctx
);
2401 InsertCursor((Widget
)ctx
, XawisOn
);
2402 ctx
->text
.old_insert
= -1;
2410 TextWidget ctx
= (TextWidget
)w
;
2412 if (ctx
->text
.file_insert
!= NULL
)
2413 XtDestroyWidget(ctx
->text
.file_insert
);
2415 DestroyHScrollBar(ctx
);
2416 DestroyVScrollBar(ctx
);
2418 XtFree((char *)ctx
->text
.updateFrom
);
2419 XtFree((char *)ctx
->text
.updateTo
);
2423 * by the time we are managed (and get this far) we had better
2424 * have both a source and a sink
2431 TextWidget ctx
= (TextWidget
) w
;
2433 PositionVScrollBar(ctx
);
2434 PositionHScrollBar(ctx
);
2436 _XawTextBuildLineTable(ctx
, ctx
->text
.lt
.top
, TRUE
);
2437 _XawTextSetScrollBars(ctx
);
2441 * This routine allow the application program to Set attributes.
2446 SetValues(current
, request
, new, args
, num_args
)
2447 Widget current
, request
, new;
2451 TextWidget oldtw
= (TextWidget
) current
;
2452 TextWidget newtw
= (TextWidget
) new;
2453 Boolean redisplay
= FALSE
;
2454 Boolean display_caret
= newtw
->text
.display_caret
;
2458 /*******************************
2459 * For Compatability. */
2461 if (newtw
->text
.options
!= oldtw
->text
.options
)
2462 XawTextChangeOptions((Widget
) newtw
, newtw
->text
.options
);
2463 /*******************************/
2466 newtw
->text
.display_caret
= oldtw
->text
.display_caret
;
2467 _XawTextPrepareToUpdate(newtw
);
2468 newtw
->text
.display_caret
= display_caret
;
2470 if (oldtw
->text
.r_margin
.left
!= newtw
->text
.r_margin
.left
) {
2471 newtw
->text
.margin
.left
= newtw
->text
.r_margin
.left
;
2472 if (newtw
->text
.vbar
!= NULL
)
2473 newtw
->text
.margin
.left
+= newtw
->text
.vbar
->core
.width
+
2474 newtw
->text
.vbar
->core
.border_width
;
2478 if (oldtw
->text
.scroll_vert
!= newtw
->text
.scroll_vert
) {
2479 if (newtw
->text
.scroll_vert
== XawtextScrollNever
)
2480 DestroyVScrollBar(newtw
);
2481 else if (newtw
->text
.scroll_vert
== XawtextScrollAlways
)
2482 CreateVScrollBar(newtw
);
2486 if (oldtw
->text
.r_margin
.bottom
!= newtw
->text
.r_margin
.bottom
) {
2487 newtw
->text
.margin
.bottom
= newtw
->text
.r_margin
.bottom
;
2488 if (newtw
->text
.hbar
!= NULL
)
2489 newtw
->text
.margin
.bottom
+= newtw
->text
.hbar
->core
.height
+
2490 newtw
->text
.hbar
->core
.border_width
;
2494 if (oldtw
->text
.scroll_horiz
!= newtw
->text
.scroll_horiz
) {
2495 if (newtw
->text
.scroll_horiz
== XawtextScrollNever
)
2496 DestroyHScrollBar(newtw
);
2497 else if (newtw
->text
.scroll_horiz
== XawtextScrollAlways
)
2498 CreateHScrollBar(newtw
);
2502 if ( oldtw
->text
.source
!= newtw
->text
.source
)
2503 XawTextSetSource( (Widget
) newtw
, newtw
->text
.source
, newtw
->text
.lt
.top
);
2505 newtw
->text
.redisplay_needed
= False
;
2506 XtSetValues( (Widget
)newtw
->text
.source
, args
, *num_args
);
2507 XtSetValues( (Widget
)newtw
->text
.sink
, args
, *num_args
);
2509 if ( oldtw
->text
.wrap
!= newtw
->text
.wrap
||
2510 oldtw
->text
.lt
.top
!= newtw
->text
.lt
.top
||
2511 oldtw
->text
.r_margin
.right
!= newtw
->text
.r_margin
.right
||
2512 oldtw
->text
.r_margin
.top
!= newtw
->text
.r_margin
.top
||
2513 oldtw
->text
.sink
!= newtw
->text
.sink
||
2514 newtw
->text
.redisplay_needed
)
2516 _XawTextBuildLineTable(newtw
, newtw
->text
.lt
.top
, TRUE
);
2520 if (oldtw
->text
.insertPos
!= newtw
->text
.insertPos
)
2521 newtw
->text
.showposition
= TRUE
;
2523 _XawTextExecuteUpdate(newtw
);
2525 _XawTextSetScrollBars(newtw
);
2530 /* Function Name: GetValuesHook
2531 * Description: This is a get values hook routine that gets the
2532 * values in the text source and sink.
2533 * Arguments: w - the Text Widget.
2534 * args - the argument list.
2535 * num_args - the number of args.
2540 GetValuesHook(w
, args
, num_args
)
2543 Cardinal
* num_args
;
2545 XtGetValues( ((TextWidget
) w
)->text
.source
, args
, *num_args
);
2546 XtGetValues( ((TextWidget
) w
)->text
.sink
, args
, *num_args
);
2549 /* Function Name: FindGoodPosition
2550 * Description: Returns a valid position given any postition
2551 * Arguments: pos - any position.
2552 * Returns: a position between (0 and lastPos);
2555 static XawTextPosition
2556 FindGoodPosition(ctx
, pos
)
2558 XawTextPosition pos
;
2560 if (pos
< 0) return(0);
2561 return ( ((pos
> ctx
->text
.lastPos
) ? ctx
->text
.lastPos
: pos
) );
2564 /*******************************************************************
2565 The following routines provide procedural interfaces to Text window state
2566 setting and getting. They need to be redone so than the args code can use
2567 them. I suggest we create a complete set that takes the context as an
2568 argument and then have the public version lookp the context and call the
2569 internal one. The major value of this set is that they have actual application
2570 clients and therefore the functionality provided is required for any future
2572 ********************************************************************/
2578 if (!XtIsRealized(w
)) return;
2580 _XawTextPrepareToUpdate( (TextWidget
) w
);
2581 DisplayTextWindow(w
);
2582 _XawTextExecuteUpdate( (TextWidget
) w
);
2586 XawTextSetSelectionArray(w
, sarray
)
2588 XawTextSelectType
*sarray
;
2590 ((TextWidget
)w
)->text
.sarray
= sarray
;
2594 XawTextGetSelectionPos(w
, left
, right
)
2596 XawTextPosition
*left
, *right
;
2598 *left
= ((TextWidget
) w
)->text
.s
.left
;
2599 *right
= ((TextWidget
) w
)->text
.s
.right
;
2604 XawTextSetSource(w
, source
, startPos
)
2606 XawTextPosition startPos
;
2608 TextWidget ctx
= (TextWidget
) w
;
2610 ctx
->text
.source
= source
;
2611 ctx
->text
.lt
.top
= startPos
;
2612 ctx
->text
.s
.left
= ctx
->text
.s
.right
= 0;
2613 ctx
->text
.insertPos
= startPos
;
2614 ctx
->text
.lastPos
= GETLASTPOS
;
2616 _XawTextBuildLineTable(ctx
, ctx
->text
.lt
.top
, TRUE
);
2621 * This public routine deletes the text from startPos to endPos in a source and
2622 * then inserts, at startPos, the text that was passed. As a side effect it
2623 * "invalidates" that portion of the displayed text (if any), so that things
2624 * will be repainted properly.
2628 XawTextReplace(w
, startPos
, endPos
, text
)
2630 XawTextPosition startPos
, endPos
;
2633 TextWidget ctx
= (TextWidget
) w
;
2636 _XawTextPrepareToUpdate(ctx
);
2637 endPos
= FindGoodPosition(ctx
, endPos
);
2638 startPos
= FindGoodPosition(ctx
, startPos
);
2639 if ((result
= _XawTextReplace(ctx
, startPos
, endPos
, text
)) == XawEditDone
) {
2640 int delta
= text
->length
- (endPos
- startPos
);
2641 if (ctx
->text
.insertPos
>= (endPos
+ delta
)) {
2642 XawTextScanDirection sd
= (delta
< 0) ? XawsdLeft
: XawsdRight
;
2643 ctx
->text
.insertPos
= SrcScan(ctx
->text
.source
, ctx
->text
.insertPos
,
2644 XawstPositions
, sd
, abs(delta
), TRUE
);
2648 _XawTextCheckResize(ctx
);
2649 _XawTextExecuteUpdate(ctx
);
2650 _XawTextSetScrollBars(ctx
);
2656 XawTextTopPosition(w
)
2659 return( ((TextWidget
) w
)->text
.lt
.top
);
2663 XawTextSetInsertionPoint(w
, position
)
2665 XawTextPosition position
;
2667 TextWidget ctx
= (TextWidget
) w
;
2669 _XawTextPrepareToUpdate(ctx
);
2670 ctx
->text
.insertPos
= FindGoodPosition(ctx
, position
);
2671 ctx
->text
.showposition
= TRUE
;
2672 _XawTextExecuteUpdate(ctx
);
2676 XawTextGetInsertionPoint(w
)
2679 return( ((TextWidget
) w
)->text
.insertPos
);
2683 * NOTE: Must walk the selection list in opposite order from LoseSelection.
2687 XawTextUnsetSelection(w
)
2690 register TextWidget ctx
= (TextWidget
)w
;
2692 while (ctx
->text
.s
.atom_count
!= 0) {
2693 Atom sel
= ctx
->text
.s
.selections
[ctx
->text
.s
.atom_count
- 1];
2694 if ( sel
!= (Atom
) 0 ) {
2696 * As selections are lost the atom_count will decrement.
2698 if (GetCutBufferNumber(sel
) == NOT_A_CUT_BUFFER
)
2699 XtDisownSelection(w
, sel
, ctx
->text
.time
);
2700 LoseSelection(w
, &sel
); /* In case this is a cut buffer, or
2701 XtDisownSelection failed to call us. */
2708 XawTextChangeOptions(w
, options
)
2712 TextWidget ctx
= (TextWidget
) w
;
2714 ctx
->text
.options
= options
;
2716 if (ctx
->text
.options
& scrollVertical
)
2717 ctx
->text
.scroll_vert
= XawtextScrollAlways
;
2719 ctx
->text
.scroll_vert
= XawtextScrollNever
;
2721 if (ctx
->text
.options
& scrollHorizontal
)
2722 ctx
->text
.scroll_horiz
= XawtextScrollAlways
;
2724 ctx
->text
.scroll_horiz
= XawtextScrollNever
;
2726 if (ctx
->text
.options
& resizeWidth
) /* Set up resize options. */
2727 if (ctx
->text
.options
& resizeHeight
)
2728 ctx
->text
.resize
= XawtextResizeBoth
;
2730 ctx
->text
.resize
= XawtextResizeWidth
;
2731 else if (ctx
->text
.options
& resizeHeight
)
2732 ctx
->text
.resize
= XawtextResizeHeight
;
2734 ctx
->text
.resize
= XawtextResizeNever
;
2736 if (ctx
->text
.options
& wordBreak
)
2737 ctx
->text
.wrap
= XawtextWrapWord
;
2739 ctx
->text
.wrap
= XawtextWrapNever
;
2743 XawTextGetOptions(w
)
2746 return(((TextWidget
) w
)->text
.options
);
2751 XawTextSetSelection (w
, left
, right
)
2753 XawTextPosition left
, right
;
2755 TextWidget ctx
= (TextWidget
) w
;
2757 _XawTextPrepareToUpdate(ctx
);
2758 _XawTextSetSelection(ctx
, FindGoodPosition(ctx
, left
),
2759 FindGoodPosition(ctx
, right
), (String
*)NULL
, ZERO
);
2760 _XawTextExecuteUpdate(ctx
);
2764 XawTextInvalidate(w
, from
, to
)
2766 XawTextPosition from
,to
;
2768 TextWidget ctx
= (TextWidget
) w
;
2770 from
= FindGoodPosition(ctx
, from
);
2771 to
= FindGoodPosition(ctx
, to
);
2772 ctx
->text
.lastPos
= GETLASTPOS
;
2773 _XawTextPrepareToUpdate(ctx
);
2774 _XawTextNeedsUpdating(ctx
, from
, to
);
2775 _XawTextBuildLineTable(ctx
, ctx
->text
.lt
.top
, TRUE
);
2776 _XawTextExecuteUpdate(ctx
);
2781 XawTextDisableRedisplay(w
)
2784 ((TextWidget
) w
)->text
.update_disabled
= True
;
2785 _XawTextPrepareToUpdate( (TextWidget
) w
);
2789 XawTextEnableRedisplay(w
)
2792 register TextWidget ctx
= (TextWidget
)w
;
2793 XawTextPosition lastPos
;
2795 if (!ctx
->text
.update_disabled
) return;
2797 ctx
->text
.update_disabled
= False
;
2798 lastPos
= ctx
->text
.lastPos
= GETLASTPOS
;
2799 ctx
->text
.lt
.top
= FindGoodPosition(ctx
, ctx
->text
.lt
.top
);
2800 ctx
->text
.insertPos
= FindGoodPosition(ctx
, ctx
->text
.insertPos
);
2801 if ( (ctx
->text
.s
.left
> lastPos
) || (ctx
->text
.s
.right
> lastPos
) )
2802 ctx
->text
.s
.left
= ctx
->text
.s
.right
= 0;
2804 _XawTextBuildLineTable(ctx
, ctx
->text
.lt
.top
, TRUE
);
2805 if (XtIsRealized(w
))
2806 DisplayTextWindow(w
);
2807 _XawTextExecuteUpdate(ctx
);
2814 return ((TextWidget
)w
)->text
.source
;
2818 XawTextDisplayCaret (w
, display_caret
)
2820 Boolean display_caret
;
2822 TextWidget ctx
= (TextWidget
) w
;
2824 if (ctx
->text
.display_caret
== display_caret
) return;
2826 if (XtIsRealized(w
)) {
2827 _XawTextPrepareToUpdate(ctx
);
2828 ctx
->text
.display_caret
= display_caret
;
2829 _XawTextExecuteUpdate(ctx
);
2832 ctx
->text
.display_caret
= display_caret
;
2835 /* Function Name: XawTextSearch(w, dir, text).
2836 * Description: searches for the given text block.
2837 * Arguments: w - The text widget.
2838 * dir - The direction to search.
2839 * text - The text block containing info about the string
2841 * Returns: The position of the text found, or XawTextSearchError on
2846 XawTextSearch(w
, dir
, text
)
2848 XawTextScanDirection dir
;
2849 XawTextBlock
* text
;
2851 TextWidget ctx
= (TextWidget
) w
;
2853 return(SrcSearch(ctx
->text
.source
, ctx
->text
.insertPos
, dir
, text
));
2856 TextClassRec textClassRec
= {
2858 /* superclass */ (WidgetClass
) &simpleClassRec
,
2859 /* class_name */ "Text",
2860 /* widget_size */ sizeof(TextRec
),
2861 /* class_initialize */ ClassInitialize
,
2862 /* class_part_init */ NULL
,
2863 /* class_inited */ FALSE
,
2864 /* initialize */ Initialize
,
2865 /* initialize_hook */ NULL
,
2866 /* realize */ Realize
,
2867 /* actions */ textActionsTable
,
2868 /* num_actions */ 0, /* Set in ClassInitialize. */
2869 /* resources */ resources
,
2870 /* num_ resource */ XtNumber(resources
),
2871 /* xrm_class */ NULLQUARK
,
2872 /* compress_motion */ TRUE
,
2873 /* compress_exposure*/ XtExposeGraphicsExpose
,
2874 /* compress_enterleave*/ TRUE
,
2875 /* visible_interest */ FALSE
,
2876 /* destroy */ TextDestroy
,
2877 /* resize */ Resize
,
2878 /* expose */ ProcessExposeRegion
,
2879 /* set_values */ SetValues
,
2880 /* set_values_hook */ NULL
,
2881 /* set_values_almost*/ XtInheritSetValuesAlmost
,
2882 /* get_values_hook */ GetValuesHook
,
2883 /* accept_focus */ NULL
,
2884 /* version */ XtVersion
,
2885 /* callback_private */ NULL
,
2886 /* tm_table */ NULL
, /* set in ClassInitialize */
2887 /* query_geometry */ XtInheritQueryGeometry
,
2888 /* display_accelerator*/ XtInheritDisplayAccelerator
,
2889 /* extension */ NULL
2891 { /* Simple fields */
2892 /* change_sensitive */ XtInheritChangeSensitive
2899 WidgetClass textWidgetClass
= (WidgetClass
)&textClassRec
;