gtk+3: fix dependencies for new gnome/accessibility/at-spi2-core
[oi-userland.git] / components / x11 / libXaw5 / src / Text.c
blob64b1eaea6b064b1f69e5d9bd9943386eb1edce9a
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.
31 All Rights Reserved
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
47 SOFTWARE.
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>
56 #include "XawI18n.h"
57 #include <stdio.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>
68 #include "TextP.h"
69 #include <X11/Xaw/MultiSinkP.h>
70 #include <X11/Xaw/XawImP.h>
72 #include <X11/Xfuncs.h>
73 #include <ctype.h> /* for isprint() */
75 #ifndef MAX_LEN_CT
76 #define MAX_LEN_CT 6 /* for sequence: ESC $ ( A \xx \xx */
77 #endif
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) )
106 * Defined in Text.c
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}
178 #undef offset
180 /* ARGSUSED */
181 static void
182 CvtStringToScrollMode(args, num_args, fromVal, toVal)
183 XrmValuePtr args; /* unused */
184 Cardinal *num_args; /* unused */
185 XrmValuePtr fromVal;
186 XrmValuePtr toVal;
188 static XawTextScrollMode scrollMode;
189 static XrmQuark QScrollNever, QScrollAlways, QScrollWhenNeeded;
190 XrmQuark q;
191 char lowerName[40];
192 static Boolean inited = FALSE;
194 if ( !inited ) {
195 QScrollNever = XrmPermStringToQuark(XtEtextScrollNever);
196 QScrollWhenNeeded = XrmPermStringToQuark(XtEtextScrollWhenNeeded);
197 QScrollAlways = XrmPermStringToQuark(XtEtextScrollAlways);
198 inited = TRUE;
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;
208 else {
209 toVal->size = 0;
210 toVal->addr = NULL;
211 return;
213 toVal->size = sizeof scrollMode;
214 toVal->addr = (XPointer) &scrollMode;
215 return;
217 toVal->size = 0;
218 toVal->addr = NULL;
221 /* ARGSUSED */
222 static void
223 CvtStringToWrapMode(args, num_args, fromVal, toVal)
224 XrmValuePtr args; /* unused */
225 Cardinal *num_args; /* unused */
226 XrmValuePtr fromVal;
227 XrmValuePtr toVal;
229 static XawTextWrapMode wrapMode;
230 static XrmQuark QWrapNever, QWrapLine, QWrapWord;
231 XrmQuark q;
232 char lowerName[BUFSIZ];
233 static Boolean inited = FALSE;
235 if ( !inited ) {
236 QWrapNever = XrmPermStringToQuark(XtEtextWrapNever);
237 QWrapLine = XrmPermStringToQuark(XtEtextWrapLine);
238 QWrapWord = XrmPermStringToQuark(XtEtextWrapWord);
239 inited = TRUE;
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;
249 else {
250 toVal->size = 0;
251 toVal->addr = NULL;
252 return;
254 toVal->size = sizeof wrapMode;
255 toVal->addr = (XPointer) &wrapMode;
256 return;
258 toVal->size = 0;
259 toVal->addr = NULL;
262 /* ARGSUSED */
263 static void
264 CvtStringToResizeMode(args, num_args, fromVal, toVal)
265 XrmValuePtr args; /* unused */
266 Cardinal *num_args; /* unused */
267 XrmValuePtr fromVal;
268 XrmValuePtr toVal;
270 static XawTextResizeMode resizeMode;
271 static XrmQuark QResizeNever, QResizeWidth, QResizeHeight, QResizeBoth;
272 XrmQuark q;
273 char lowerName[40];
274 static Boolean inited = FALSE;
276 if ( !inited ) {
277 QResizeNever = XrmPermStringToQuark(XtEtextResizeNever);
278 QResizeWidth = XrmPermStringToQuark(XtEtextResizeWidth);
279 QResizeHeight = XrmPermStringToQuark(XtEtextResizeHeight);
280 QResizeBoth = XrmPermStringToQuark(XtEtextResizeBoth);
281 inited = TRUE;
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;
292 else {
293 toVal->size = 0;
294 toVal->addr = NULL;
295 return;
297 toVal->size = sizeof resizeMode;
298 toVal->addr = (XPointer) &resizeMode;
299 return;
301 toVal->size = 0;
302 toVal->addr = NULL;
305 static void
306 ClassInitialize()
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));
313 char *cp = buf;
315 if (!XawFmt8Bit)
316 FMT8BIT = XawFmt8Bit = XrmPermStringToQuark("FMT8BIT");
317 if (!XawFmtWide)
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.
345 * Returns: none
348 static void
349 PositionHScrollBar(ctx)
350 TextWidget ctx;
352 Widget vbar = ctx->text.vbar, hbar = ctx->text.hbar;
353 Position top, left = 0;
355 if (ctx->text.hbar == NULL) return;
357 if (vbar != NULL)
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.
372 * Returns: none.
375 static void
376 PositionVScrollBar(ctx)
377 TextWidget ctx;
379 Widget vbar = ctx->text.vbar;
380 Dimension bw;
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 );
389 static void
390 CreateVScrollBar(ctx)
391 TextWidget ctx;
393 Widget vbar;
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,
404 (XtPointer) NULL);
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);
414 XtMapWidget(vbar);
418 /* Function Name: DestroyVScrollBar
419 * Description: Removes a vertical ScrollBar.
420 * Arguments: ctx - the parent text widget.
421 * Returns: none.
424 static void
425 DestroyVScrollBar(ctx)
426 TextWidget 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,
436 (XtPointer) NULL);
437 XtDestroyWidget(vbar);
438 ctx->text.vbar = NULL;
439 PositionHScrollBar(ctx);
442 static void
443 CreateHScrollBar(ctx)
444 TextWidget ctx;
446 Arg args[1];
447 Widget hbar;
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,
458 (XtPointer) NULL);
460 PositionHScrollBar(ctx);
461 if (XtIsRealized((Widget)ctx)) {
462 XtRealizeWidget(hbar);
463 XtMapWidget(hbar);
467 /* Function Name: DestroyHScrollBar
468 * Description: Removes a horizontal ScrollBar.
469 * Arguments: ctx - the parent text widget.
470 * Returns: none.
473 static void
474 DestroyHScrollBar(ctx)
475 TextWidget 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,
487 (XtPointer) NULL);
488 XtDestroyWidget(hbar);
489 ctx->text.hbar = NULL;
492 static void warn_msg (w, dir, desc)
493 Widget w;
494 char* dir;
495 char* 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];
499 char* errorp;
500 int len;
502 if ((len = strlen (fmt) + strlen (w->core.name) + 2 * strlen (dir) + strlen (desc)) < sizeof error_buf)
503 errorp = error_buf;
504 else
505 errorp = XtMalloc (len + 1);
507 if (errorp == NULL) {
508 errorp = error_buf;
509 strcpy (errorp, "Scrolling has been DEACTIVATED");
510 } else
511 (void) sprintf (errorp, fmt, w->core.name, dir, desc, dir);
512 XtAppWarning (XtWidgetToApplicationContext (w), errorp);
515 /* ARGSUSED */
516 static void
517 Initialize(request, new, args, num_args)
518 Widget request, new;
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;
546 ctx->text.mult = 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);
580 static void
581 Realize( w, valueMask, attributes )
582 Widget w;
583 Mask *valueMask;
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);
607 /*ARGSUSED*/
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;
615 if (ctx->text.hbar)
616 XtUnrealizeWidget(ctx->text.hbar);
617 if (ctx->text.vbar)
618 XtUnrealizeWidget(ctx->text.vbar);
621 /* Utility routines for support of Text */
623 static void
624 _CreateCutBuffers(d)
625 Display *d;
627 static struct _DisplayRec {
628 struct _DisplayRec *next;
629 Display *dpy;
630 } *dpy_list = NULL;
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;
638 dpy_ptr->dpy = d;
639 dpy_list = dpy_ptr;
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 );
654 #undef Create
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.
663 static void
664 InsertCursor (w, state)
665 Widget w;
666 XawTextInsertState state;
668 TextWidget ctx = (TextWidget)w;
669 Position x, y;
670 int line;
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;
677 else
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);
683 ctx->text.ev_x = x;
684 ctx->text.ev_y = y;
686 /* Keep Input Method up to speed */
688 if ( ctx->simple.international ) {
689 Arg list[1];
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
699 * updates.
702 void
703 _XawTextNeedsUpdating(ctx, left, right)
704 TextWidget ctx;
705 XawTextPosition left, right;
707 int i;
708 size_t len;
709 if (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]);
714 return;
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].
737 char *
738 _XawTextGetText(ctx, left, right)
739 TextWidget ctx;
740 XawTextPosition left, right;
742 char *result, *tempResult;
743 XawTextBlock text;
744 int bytes;
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 */
751 bytes = 1;
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));
757 if (!text.length)
758 break;
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;
765 else
766 *tempResult = '\0';
767 return(result);
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
772 cut buffer. */
774 char *
775 _XawTextGetSTRING(ctx, left, right)
776 TextWidget ctx;
777 XawTextPosition left, right;
779 unsigned char *s;
780 unsigned char c;
781 long i, j, n;
782 wchar_t *ws, wc;
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);
788 n = wcslen(ws);
789 for (j = 0, i = 0; j < n; j++) {
790 wc = ws[j];
791 if (XwcTextEscapement (sink->multi_sink.fontset, &wc, 1) ||
792 (wc == _Xaw_atowc(XawTAB)) || (wc == _Xaw_atowc(XawLF)) || (wc == _Xaw_atowc(XawESC)))
793 ws[i++] = wc;
795 ws[i] = (wchar_t)0;
796 return (char *)ws;
797 } else {
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);
801 i = 0;
802 for (j = 0; j < n; j++) {
803 c = s[j];
804 if (((c >= 0x20) && c <= 0x7f) ||
805 (c >= 0xa0) || (c == XawTAB) || (c == XawLF) || (c == XawESC)) {
806 s[i] = c;
807 i++;
810 s[i] = 0;
811 return (char *)s;
813 #undef ESC
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)
828 TextWidget ctx;
829 Position 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)
838 break;
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);
850 return(position);
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!
860 static int
861 LineForPosition (ctx, position)
862 TextWidget ctx;
863 XawTextPosition position;
865 int line;
867 for (line = 0; line < ctx->text.lt.lines; line++)
868 if (position < ctx->text.lt.info[line + 1].position)
869 break;
870 return(line);
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!
880 static Boolean
881 LineAndXYForPosition (ctx, pos, line, x, y)
882 TextWidget ctx;
883 XawTextPosition pos;
884 int *line;
885 Position *x, *y;
887 XawTextPosition linePos, endPos;
888 Boolean visible;
889 int realW, realH;
891 *line = 0;
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);
901 *x += realW;
903 return(visible);
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.).
914 void
915 #if NeedFunctionPrototypes
916 _XawTextBuildLineTable (
917 TextWidget ctx,
918 XawTextPosition position,
919 _XtBoolean force_rebuild)
920 #else
921 _XawTextBuildLineTable (ctx, position, force_rebuild)
922 TextWidget ctx;
923 XawTextPosition position;
924 Boolean force_rebuild;
925 #endif
927 Dimension height = 0;
928 int lines = 0;
929 Cardinal size;
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.
939 lt.info, size);
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)
956 TextWidget ctx;
957 XawTextPosition position, min_pos;
958 int line;
960 XawTextLineTableEntry * lt = ctx->text.lt.info + line;
961 XawTextPosition endPos;
962 Position y;
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) )
969 width = BIGNUM;
970 else
971 width = Max(0, ((int)ctx->core.width - (int)HMargins(ctx)));
973 y = ( (line == 0) ? ctx->text.margin.top : lt->y );
975 /* CONSTCOND */
976 while ( TRUE ) {
977 lt->y = 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;
984 y += realH;
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)
991 break;
994 ++lt;
995 ++line;
996 if ( (line > ctx->text.lt.lines) ||
997 ((lt->position == (position = endPos)) && (position > min_pos)) )
998 return(position);
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
1010 * minimum.
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;
1019 lt->textWidth = 0;
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;
1029 return(endPos);
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.
1041 static Dimension
1042 GetWidestLine(ctx)
1043 TextWidget ctx;
1045 int i;
1046 Dimension widest;
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;
1053 return(widest);
1056 static void
1057 CheckVBarScrolling(ctx)
1058 TextWidget ctx;
1060 float first, last;
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;
1071 else
1072 last = 1.0;
1074 if (ctx->text.scroll_vert == XawtextScrollWhenNeeded) {
1075 int line;
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);
1088 else
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.
1114 void
1115 _XawTextSetScrollBars(ctx)
1116 TextWidget 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);
1129 else
1130 widest = ctx->core.width;
1131 widest /= (last = GetWidestLine(ctx));
1132 if (ctx->text.scroll_horiz == XawtextScrollWhenNeeded)
1133 if (widest < 1.0)
1134 CreateHScrollBar(ctx);
1135 else
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;
1146 first /= last;
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);
1156 FlushUpdate(ctx);
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].
1166 void
1167 _XawTextVScroll(ctx, n)
1168 TextWidget ctx;
1169 int n;
1171 XawTextPosition top, target;
1172 int y;
1173 Arg list[1];
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;
1179 if (n == 0) return;
1181 if (n > 0) {
1182 if ( IsValidLine(ctx, n) )
1183 top = Min(lt->info[n].position, ctx->text.lastPos);
1184 else
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);
1191 else {
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,
1198 (Position) 0,
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,
1204 ctx->text.lastPos);
1205 _XawTextSetScrollBars(ctx);
1208 else {
1209 XawTextPosition updateTo;
1210 unsigned int height, clear_height;
1212 n = -n;
1213 target = lt->top;
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);
1224 else
1225 height = 0;
1226 if (y > (int) ctx->text.margin.top)
1227 clear_height = y - ctx->text.margin.top;
1228 else
1229 clear_height = 0;
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);
1248 /*ARGSUSED*/
1249 static void
1250 HScroll(w, closure, callData)
1251 Widget w;
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;
1269 if (pixels > 0) {
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,
1278 0, (int) rect.y);
1280 PushCopyQueue(ctx, (int) -pixels, 0);
1282 else if (pixels < 0) {
1283 rect.x = 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;
1307 t_rect.y = rect.y;
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);
1330 /*ARGSUSED*/
1331 static void
1332 HJump(w, closure, callData)
1333 Widget w;
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);
1348 return;
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
1361 * area to update.
1362 * Returns: none.
1365 static void
1366 UpdateTextInLine(ctx, line, left, right)
1367 TextWidget ctx;
1368 int line;
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);
1389 else
1390 pos2 = GETLASTPOS;
1391 else {
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)
1402 pos2 = t_pos;
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.
1413 /*ARGSUSED*/
1414 static void
1415 VScroll(w, closure, callData)
1416 Widget w;
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);
1424 if (height < 1)
1425 height = 1;
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.
1444 /*ARGSUSED*/
1445 static void
1446 VJump(w, closure, callData)
1447 Widget w;
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);
1456 old_top = lt->top;
1457 if ( (lt->lines > 0) && (IsValidLine(ctx, lt->lines - 1)) )
1458 old_bot = lt->info[lt->lines - 1].position;
1459 else
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) ) {
1465 int line = 0;
1466 for (;(line < lt->lines) && (position > lt->info[line].position) ; line++);
1467 _XawTextVScroll(ctx, line);
1469 else {
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)) {
1476 int line = 0;
1477 for (;(line < lt->lines) && (old_top > lt->info[line].position); line++);
1478 _XawTextBuildLineTable(ctx, old_top, FALSE);
1479 _XawTextVScroll(ctx, -line);
1481 else
1482 DisplayTextWindow( (Widget) ctx);
1484 _XawTextExecuteUpdate(ctx);
1487 static Boolean
1488 MatchSelection(selection, s)
1489 Atom selection;
1490 XawTextSelection *s;
1492 Atom *match;
1493 int count;
1495 for (count = 0, match = s->selections; count < s->atom_count; match++, count++)
1496 if (*match == selection)
1497 return True;
1498 return False;
1501 static Boolean
1502 ConvertSelection(w, selection, target, type, value, length, format)
1503 Widget w;
1504 Atom *selection, *target, *type;
1505 XtPointer *value;
1506 unsigned long *length;
1507 int *format;
1509 Display* d = XtDisplay(w);
1510 TextWidget ctx = (TextWidget)w;
1511 Widget src = ctx->text.source;
1512 XawTextEditType edit_mode;
1513 Arg args[1];
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) )
1523 return True;
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);
1544 (*length)++;
1546 (void) memmove((char*)targetP, (char*)std_targets, sizeof(Atom)*std_length);
1547 XtFree((char*)std_targets);
1548 *type = XA_ATOM;
1549 *format = 32;
1550 return True;
1553 if ( SrcCvtSel(src, selection, target, type, value, length, format) )
1554 return True;
1556 if (MatchSelection (*selection, &ctx->text.s))
1557 s = &ctx->text.s;
1558 else
1560 for (salt = ctx->text.salt; salt; salt = salt->next)
1561 if (MatchSelection (*selection, &salt->s))
1562 break;
1563 if (!salt)
1564 return False;
1565 s = &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);
1573 else
1574 *type = XA_STRING;
1575 } else {
1576 *type = *target;
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.
1585 if (!salt) {
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)
1591 < Success) {
1592 XtFree(*value);
1593 return False;
1595 XtFree(*value);
1596 *value = (XtPointer)textprop.value;
1597 *length = textprop.nitems;
1598 } else {
1599 *length = strlen(*value);
1601 } else {
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;
1608 wchar_t **wlist;
1609 int count;
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)
1615 < Success) {
1616 XtFree(*value);
1617 return False;
1619 XtFree(*value);
1620 if (XwcTextListToTextProperty( d, (wchar_t **)wlist, 1,
1621 XStringStyle, &textprop) < Success) {
1622 XwcFreeStringList( (wchar_t**) wlist );
1623 return False;
1625 *value = (XtPointer) textprop.value;
1626 *length = textprop.nitems;
1627 XwcFreeStringList( (wchar_t**) wlist );
1629 *format = 8;
1630 return True;
1633 if ( (*target == XA_LIST_LENGTH(d)) || (*target == XA_LENGTH(d)) ) {
1634 long * temp;
1636 temp = (long *) XtMalloc( (unsigned) sizeof(long) );
1637 if (*target == XA_LIST_LENGTH(d))
1638 *temp = 1L;
1639 else /* *target == XA_LENGTH(d) */
1640 *temp = (long) (s->right - s->left);
1642 *value = (XPointer) temp;
1643 *type = XA_INTEGER;
1644 *length = 1L;
1645 *format = 32;
1646 return True;
1649 if (*target == XA_CHARACTER_POSITION(d)) {
1650 long * temp;
1652 temp = (long *) XtMalloc( (unsigned)( 2 * sizeof(long) ) );
1653 temp[0] = (long) (s->left + 1);
1654 temp[1] = s->right;
1655 *value = (XPointer) temp;
1656 *type = XA_SPAN(d);
1657 *length = 2L;
1658 *format = 32;
1659 return True;
1662 if (*target == XA_DELETE(d)) {
1663 void _XawTextZapSelection(); /* From TextAction.c */
1665 if (!salt)
1666 _XawTextZapSelection( ctx, (XEvent *) NULL, TRUE);
1667 *value = NULL;
1668 *type = XA_NULL(d);
1669 *length = 0;
1670 *format = 32;
1671 return True;
1674 if (XmuConvertStandardSelection(w, ctx->text.time, selection, target, type,
1675 (XPointer *)value, length, format))
1676 return True;
1678 /* else */
1679 return False;
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
1686 * NOT_A_CUT_BUFFER.
1689 #define NOT_A_CUT_BUFFER -1
1691 static int
1692 GetCutBufferNumber(atom)
1693 Atom 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);
1706 static void
1707 LoseSelection(w, selection)
1708 Widget w;
1709 Atom *selection;
1711 TextWidget ctx = (TextWidget) w;
1712 Atom* atomP;
1713 int i;
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 */
1722 *atomP = (Atom)0;
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);
1747 prevSalt = 0;
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)
1754 *atomP = (Atom)0;
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);
1779 if (prevSalt)
1780 prevSalt->next = nextSalt;
1781 else
1782 ctx->text.salt = nextSalt;
1783 XtFree ((char *) salt);
1785 else
1786 prevSalt = salt;
1790 void
1791 _XawTextSaltAwaySelection (ctx, selections, num_atoms)
1792 TextWidget ctx;
1793 Atom* selections;
1794 int num_atoms;
1796 XawTextSelectionSalt *salt;
1797 int i, j;
1799 for (i = 0; i < num_atoms; i++)
1800 LoseSelection ((Widget) ctx, selections + i);
1801 if (num_atoms == 0)
1802 return;
1803 salt = (XawTextSelectionSalt *)
1804 XtMalloc( (unsigned) sizeof(XawTextSelectionSalt) );
1805 if (!salt)
1806 return;
1807 salt->s.selections = (Atom *)
1808 XtMalloc( (unsigned) ( num_atoms * sizeof (Atom) ) );
1809 if (!salt->s.selections)
1811 XtFree ((char *) salt);
1812 return;
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);
1824 salt->length = 0;
1825 return;
1827 XtFree(salt->contents);
1828 salt->contents = (char *)textprop.value;
1829 salt->length = textprop.nitems;
1830 } else
1831 salt->length = strlen (salt->contents);
1832 salt->next = ctx->text.salt;
1833 ctx->text.salt = salt;
1834 j = 0;
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;
1847 static void
1848 _SetSelection(ctx, left, right, selections, count)
1849 TextWidget ctx;
1850 XawTextPosition left, right;
1851 Atom *selections;
1852 Cardinal count;
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]);
1879 if (left < right) {
1880 Widget w = (Widget) ctx;
1881 int buffer;
1883 while (count) {
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));
1893 unsigned long len;
1895 tptr= ptr= (unsigned char *) _XawTextGetSTRING(ctx, ctx->text.s.left,
1896 ctx->text.s.right);
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);
1906 return;
1908 XtFree((char *)ptr);
1909 tptr = ptr = textprop.value;
1911 if (buffer == 0) {
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) {
1920 len -= max_len;
1921 tptr += max_len;
1922 amount = Min (len, max_len);
1923 XChangeProperty(XtDisplay(w), RootWindow(XtDisplay(w), 0),
1924 selection, XA_STRING, 8, PropModeAppend,
1925 tptr, amount);
1927 XtFree ((char *)ptr);
1929 else /* This is a real selection */
1930 XtOwnSelection(w, selection, ctx->text.time, ConvertSelection,
1931 LoseSelection, (XtSelectionDoneProc)NULL);
1934 else
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!
1946 int
1947 _XawTextReplace (ctx, pos1, pos2, text)
1948 TextWidget ctx;
1949 XawTextPosition pos1, pos2;
1950 XawTextBlock *text;
1952 int i, line1, error;
1953 long delta;
1954 XawTextPosition updateFrom, updateTo;
1955 Widget src = ctx->text.source;
1956 XawTextEditType edit_mode;
1957 Arg args[1];
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 */
1986 return(error);
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.
2017 if (delta != 0) {
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!
2049 static void
2050 DisplayText(w, pos1, pos2)
2051 Widget w;
2052 XawTextPosition pos1, pos2;
2054 TextWidget ctx = (TextWidget)w;
2055 Position x, y;
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);
2073 else {
2074 clear_eol = TRUE;
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,
2083 (Position) 0, y,
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);
2090 else {
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);
2097 startPos = endPos;
2098 if (clear_eol) {
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) {
2116 y += height;
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;
2127 if ( done_painting
2128 || (y >= (int)(ctx->core.height - ctx->text.margin.bottom)) )
2129 break;
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.]
2144 static void
2145 DoSelection (ctx, pos, time, motion)
2146 TextWidget ctx;
2147 XawTextPosition pos;
2148 Time time;
2149 Boolean motion;
2151 XawTextPosition newLeft, newRight;
2152 XawTextSelectType newType, *sarray;
2153 Widget src = ctx->text.source;
2155 if (motion)
2156 newType = ctx->text.s.type;
2157 else {
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);
2165 else {
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;
2176 switch (newType) {
2177 case XawselectPosition:
2178 newLeft = newRight = pos;
2179 break;
2180 case XawselectChar:
2181 newLeft = pos;
2182 newRight = SrcScan(src, pos, XawstPositions, XawsdRight, 1, FALSE);
2183 break;
2184 case XawselectWord:
2185 case XawselectParagraph:
2187 XawTextScanType stype;
2189 if (newType == XawselectWord)
2190 stype = XawstWhiteSpace;
2191 else
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);
2207 else
2208 newLeft = pos;
2210 newLeft =SrcScan(ctx->text.source, newLeft, stype, XawsdRight,1,FALSE);
2212 if (newLeft > newRight) {
2213 XawTextPosition temp = newLeft;
2214 newLeft = newRight;
2215 newRight = temp;
2218 break;
2219 case XawselectLine:
2220 newLeft = SrcScan(src, pos, XawstEOL, XawsdLeft, 1, FALSE);
2221 newRight = SrcScan(src, pos, XawstEOL, XawsdRight, 1, FALSE);
2222 break;
2223 case XawselectAll:
2224 newLeft = SrcScan(src, pos, XawstAll, XawsdLeft, 1, FALSE);
2225 newRight = SrcScan(src, pos, XawstAll, XawsdRight, 1, FALSE);
2226 break;
2227 default:
2228 XtAppWarning(XtWidgetToApplicationContext((Widget) ctx),
2229 "Text Widget: empty selection array.");
2230 return;
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;
2238 else
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;
2249 else
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!).
2262 static void
2263 ExtendSelection (ctx, pos, motion)
2264 TextWidget ctx;
2265 XawTextPosition pos;
2266 Boolean motion;
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;
2273 else {
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;
2282 else
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) {
2295 case XawselectWord:
2296 case XawselectParagraph:
2298 XawTextPosition left_pos, right_pos;
2299 XawTextScanType stype;
2301 if (ctx->text.s.type == XawselectWord)
2302 stype = XawstWhiteSpace;
2303 else
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);
2319 else
2320 left_pos = pos;
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);
2329 break;
2330 case XawselectLine:
2331 pos = SrcScan(ctx->text.source, pos, XawstEOL, dir, 1, dir == XawsdRight);
2332 break;
2333 case XawselectAll:
2334 pos = ctx->text.insertPos;
2335 case XawselectPosition: /* fall through. */
2336 default:
2337 break;
2340 if (dir == XawsdRight)
2341 ModifySelection(ctx, ctx->text.s.left, pos);
2342 else
2343 ModifySelection(ctx, pos, ctx->text.s.right);
2345 ctx->text.insertPos = pos;
2349 * Clear the window to background color.
2352 static void
2353 ClearWindow (w)
2354 Widget w;
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.
2368 * Returns: none.
2371 void
2372 _XawTextClearAndCenterDisplay(ctx)
2373 TextWidget 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.
2387 static void
2388 DisplayTextWindow (w)
2389 Widget w;
2391 TextWidget ctx = (TextWidget) w;
2392 ClearWindow(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.
2404 void
2405 _XawTextCheckResize(ctx)
2406 TextWidget 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;
2415 rbox.width = 0;
2416 for (lt = ctx->text.lt.info;
2417 IsValidLine(ctx, line) && (line < ctx->text.lt.lines);
2418 line++, lt++) {
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)) )
2433 return;
2435 if (IsPositionVisible(ctx, ctx->text.lastPos))
2436 line = LineForPosition(ctx, ctx->text.lastPos);
2437 else
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)
2450 return;
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.
2460 Atom*
2461 _XawTextSelectionList(ctx, list, nelems)
2462 TextWidget ctx;
2463 String *list;
2464 Cardinal nelems;
2466 Atom * sel = ctx->text.s.selections;
2467 Display *dpy = XtDisplay((Widget) ctx);
2468 int n;
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).
2487 * Returns: none.
2489 * NOTE: if (ctx->text.s.left >= ctx->text.s.right) then the selection
2490 * is unset.
2493 void
2494 _XawTextSetSelection(ctx, l, r, list, nelems)
2495 TextWidget ctx;
2496 XawTextPosition l, r;
2497 String *list;
2498 Cardinal nelems;
2500 if (nelems == 1 && !strcmp (list[0], "none"))
2501 return;
2502 if (nelems == 0) {
2503 String defaultSel = "PRIMARY";
2504 list = &defaultSel;
2505 nelems = 1;
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.
2515 * Returns: none.
2517 * NOTE: if (ctx->text.s.left >= ctx->text.s.right) then the selection
2518 * is unset.
2521 static void
2522 ModifySelection(ctx, left, right)
2523 TextWidget ctx;
2524 XawTextPosition left, right;
2526 if (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.
2537 void
2538 _XawTextAlterSelection (ctx, mode, action, params, num_params)
2539 TextWidget ctx;
2540 XawTextSelectionMode mode; /* {XawsmTextSelect, XawsmTextExtend} */
2541 XawTextSelectionAction action; /* {XawactionStart,
2542 XawactionAdjust, XawactionEnd} */
2543 String *params;
2544 Cardinal *num_params;
2546 XawTextPosition position;
2547 Boolean flag;
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.
2576 static Boolean
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.
2590 * Returns: none.
2593 static void
2594 UpdateTextInRectangle(ctx, rect)
2595 TextWidget ctx;
2596 XRectangle * 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.
2614 /* ARGSUSED */
2615 static void
2616 ProcessExposeRegion(w, event, region)
2617 Widget w;
2618 XEvent *event;
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 */
2638 PopCopyQueue(ctx);
2639 return; /* no more processing necessary. */
2642 need_to_draw = TranslateExposeRegion(ctx, &expose);
2643 if ((event->type == GraphicsExpose) && (event->xgraphicsexpose.count == 0))
2644 PopCopyQueue(ctx);
2646 if (!need_to_draw)
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
2664 void
2665 _XawTextPrepareToUpdate(ctx)
2666 TextWidget 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.
2682 static
2683 void FlushUpdate(ctx)
2684 TextWidget ctx;
2686 int i, w;
2687 XawTextPosition updateFrom, updateTo;
2688 if (!XtIsRealized((Widget)ctx)) {
2689 ctx->text.numranges = 0;
2690 return;
2692 while (ctx->text.numranges > 0) {
2693 updateFrom = ctx->text.updateFrom[0];
2694 w = 0;
2695 for (i = 1 ; i < ctx->text.numranges ; i++) {
2696 if (ctx->text.updateFrom[i] < updateFrom) {
2697 updateFrom = ctx->text.updateFrom[i];
2698 w = 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.
2725 void
2726 _XawTextShowPosition(ctx)
2727 TextWidget ctx;
2729 int x, y, lines, number;
2730 Boolean no_scroll;
2731 XawTextPosition max_pos, top, first;
2733 if ( (!XtIsRealized((Widget)ctx)) || (ctx->text.lt.lines <= 0) )
2734 return;
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
2741 * visable window.
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))
2754 return;
2756 first = ctx->text.lt.top;
2757 no_scroll = FALSE;
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 */
2765 number = 0;
2766 while (first > top) {
2767 first = SrcScan(ctx->text.source, first,
2768 XawstEOL, XawsdLeft, 1, TRUE);
2770 if ( - number > lines )
2771 break;
2773 number--;
2776 if (first <= top) { /* If we found the proper number
2777 of lines. */
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. */
2786 if (first <= top)
2787 number++;
2789 lines = number;
2791 else
2792 no_scroll = TRUE;
2794 else { /* We need to Scroll up */
2795 top = SrcScan(ctx->text.source, ctx->text.insertPos,
2796 XawstEOL, XawsdLeft, lines, FALSE);
2798 if (top < max_pos)
2799 lines = LineForPosition(ctx, top);
2800 else
2801 no_scroll = TRUE;
2804 if (no_scroll) {
2805 _XawTextBuildLineTable(ctx, top, FALSE);
2806 DisplayTextWindow((Widget)ctx);
2808 else
2809 _XawTextVScroll(ctx, lines);
2811 _XawTextSetScrollBars(ctx);
2815 * This routine causes all batched screen updates to be performed
2818 void
2819 _XawTextExecuteUpdate(ctx)
2820 TextWidget ctx;
2822 if ( ctx->text.update_disabled || (ctx->text.old_insert < 0) )
2823 return;
2825 if((ctx->text.old_insert != ctx->text.insertPos) || (ctx->text.showposition))
2826 _XawTextShowPosition(ctx);
2827 FlushUpdate(ctx);
2828 InsertCursor((Widget)ctx, XawisOn);
2829 ctx->text.old_insert = -1;
2833 static void
2834 TextDestroy(w)
2835 Widget w;
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
2854 static void
2855 Resize(w)
2856 Widget w;
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.
2871 /*ARGSUSED*/
2872 static Boolean
2873 SetValues(current, request, new, args, num_args)
2874 Widget current, request, new;
2875 ArgList args;
2876 Cardinal *num_args;
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;
2893 redisplay = TRUE;
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);
2901 redisplay = TRUE;
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;
2909 redisplay = TRUE;
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);
2917 redisplay = TRUE;
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);
2935 redisplay = TRUE;
2938 if (oldtw->text.insertPos != newtw->text.insertPos) {
2939 newtw->text.showposition = TRUE;
2940 redisplay = TRUE;
2943 _XawTextExecuteUpdate(newtw);
2944 if (redisplay)
2945 _XawTextSetScrollBars(newtw);
2947 return redisplay;
2950 /* invoked by the Simple widget's SetValues */
2951 static Boolean ChangeSensitive(w)
2952 Widget w; /* the new widget */
2954 Arg args[1];
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));
2961 if (tw->text.vbar)
2962 XtSetValues(tw->text.vbar, args, ONE);
2963 if (tw->text.hbar)
2964 XtSetValues(tw->text.hbar, args, ONE);
2965 return False;
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.
2974 * Returns: none.
2977 static void
2978 GetValuesHook(w, args, num_args)
2979 Widget w;
2980 ArgList 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)
2995 TextWidget ctx;
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.
3012 * Returns: none
3015 static void
3016 PushCopyQueue(ctx, h, v)
3017 TextWidget ctx;
3018 int h, v;
3020 struct text_move * offsets = XtNew(struct text_move);
3022 offsets->h = h;
3023 offsets->v = v;
3024 offsets->next = NULL;
3026 if (ctx->text.copy_area_offsets == NULL)
3027 ctx->text.copy_area_offsets = offsets;
3028 else {
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.
3038 * Returns: none.
3041 static void
3042 PopCopyQueue(ctx)
3043 TextWidget ctx;
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 ) );
3050 else {
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.
3067 static Boolean
3068 TranslateExposeRegion(ctx, expose)
3069 TextWidget ctx;
3070 XRectangle * expose;
3072 struct text_move * offsets = ctx->text.copy_area_offsets;
3073 int value;
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))
3081 return(TRUE);
3083 x = expose->x;
3084 y = expose->y;
3085 width = expose->width;
3086 height = expose->height;
3088 while (offsets) {
3089 x += offsets->h;
3090 y += offsets->v;
3091 offsets = offsets->next;
3095 * remove that area of the region that is now outside the window.
3098 if (y < 0) {
3099 height += y;
3100 y = 0;
3103 value = y + height - ctx->core.height;
3104 if (value > 0)
3105 height -= value;
3107 if (height <= 0)
3108 return(FALSE); /* no need to draw outside the window. */
3111 * and now in the horiz direction...
3114 if (x < 0) {
3115 width += x;
3116 x = 0;
3119 value = x + width - ctx->core.width;
3120 if (value > 0)
3121 width -= value;
3123 if (width <= 0)
3124 return(FALSE); /* no need to draw outside the window. */
3126 expose->x = x;
3127 expose->y = y;
3128 expose->width = width;
3129 expose->height = height;
3130 return(TRUE);
3133 /* Li wrote this so the IM can find a given text position's screen position. */
3135 void
3136 #if NeedFunctionPrototypes
3137 _XawTextPosToXY(
3138 Widget w,
3139 XawTextPosition pos,
3140 Position* x,
3141 Position* y )
3142 #else
3143 _XawTextPosToXY( w, pos, x, y )
3144 Widget w;
3145 XawTextPosition pos;
3146 Position *x, *y;
3147 #endif
3149 int line;
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
3160 version of Text.
3161 ********************************************************************/
3163 void
3164 #if NeedFunctionPrototypes
3165 XawTextDisplay (Widget w)
3166 #else
3167 XawTextDisplay (w)
3168 Widget w;
3169 #endif
3171 if (!XtIsRealized(w)) return;
3173 _XawTextPrepareToUpdate( (TextWidget) w);
3174 DisplayTextWindow(w);
3175 _XawTextExecuteUpdate( (TextWidget) w);
3178 void
3179 #if NeedFunctionPrototypes
3180 XawTextSetSelectionArray(Widget w, XawTextSelectType *sarray)
3181 #else
3182 XawTextSetSelectionArray(w, sarray)
3183 Widget w;
3184 XawTextSelectType *sarray;
3185 #endif
3187 ((TextWidget)w)->text.sarray = sarray;
3190 void
3191 #if NeedFunctionPrototypes
3192 XawTextGetSelectionPos(Widget w, XawTextPosition *left, XawTextPosition *right)
3193 #else
3194 XawTextGetSelectionPos(w, left, right)
3195 Widget w;
3196 XawTextPosition* left,* right;
3197 #endif
3199 *left = ((TextWidget) w)->text.s.left;
3200 *right = ((TextWidget) w)->text.s.right;
3204 void
3205 #if NeedFunctionPrototypes
3206 XawTextSetSource(Widget w, Widget source, XawTextPosition startPos)
3207 #else
3208 XawTextSetSource(w, source, startPos)
3209 Widget w, source;
3210 XawTextPosition startPos;
3211 #endif
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);
3222 XawTextDisplay(w);
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.
3232 int
3233 #if NeedFunctionPrototypes
3234 XawTextReplace(Widget w, XawTextPosition startPos, XawTextPosition endPos,
3235 XawTextBlock *text)
3236 #else
3237 XawTextReplace(w, startPos, endPos, text)
3238 Widget w;
3239 XawTextPosition startPos, endPos;
3240 XawTextBlock *text;
3241 #endif
3243 TextWidget ctx = (TextWidget) w;
3244 int result;
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);
3262 return result;
3265 XawTextPosition
3266 #if NeedFunctionPrototypes
3267 XawTextTopPosition(Widget w)
3268 #else
3269 XawTextTopPosition(w)
3270 Widget w;
3271 #endif
3273 return( ((TextWidget) w)->text.lt.top );
3276 void
3277 #if NeedFunctionPrototypes
3278 XawTextSetInsertionPoint(Widget w, XawTextPosition position)
3279 #else
3280 XawTextSetInsertionPoint(w, position)
3281 Widget w;
3282 XawTextPosition position;
3283 #endif
3285 TextWidget ctx = (TextWidget) w;
3287 _XawTextPrepareToUpdate(ctx);
3288 ctx->text.insertPos = FindGoodPosition(ctx, position);
3289 ctx->text.showposition = TRUE;
3291 _XawTextExecuteUpdate(ctx);
3294 XawTextPosition
3295 #if NeedFunctionPrototypes
3296 XawTextGetInsertionPoint(Widget w)
3297 #else
3298 XawTextGetInsertionPoint(w)
3299 Widget w;
3300 #endif
3302 return( ((TextWidget) w)->text.insertPos);
3306 * NOTE: Must walk the selection list in opposite order from LoseSelection.
3309 void
3310 #if NeedFunctionPrototypes
3311 XawTextUnsetSelection(Widget w)
3312 #else
3313 XawTextUnsetSelection(w)
3314 Widget w;
3315 #endif
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. */
3333 void
3334 #if NeedFunctionPrototypes
3335 XawTextSetSelection (Widget w, XawTextPosition left, XawTextPosition right)
3336 #else
3337 XawTextSetSelection (w, left, right)
3338 Widget w;
3339 XawTextPosition left, right;
3340 #endif
3342 TextWidget ctx = (TextWidget) w;
3344 _XawTextPrepareToUpdate(ctx);
3345 _XawTextSetSelection(ctx, FindGoodPosition(ctx, left),
3346 FindGoodPosition(ctx, right), (String*)NULL, ZERO);
3347 _XawTextExecuteUpdate(ctx);
3350 void
3351 #if NeedFunctionPrototypes
3352 XawTextInvalidate(Widget w, XawTextPosition from, XawTextPosition to)
3353 #else
3354 XawTextInvalidate(w, from, to)
3355 Widget w;
3356 XawTextPosition from,to;
3357 #endif
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);
3370 /*ARGSUSED*/
3371 void
3372 #if NeedFunctionPrototypes
3373 XawTextDisableRedisplay(Widget w)
3374 #else
3375 XawTextDisableRedisplay(w)
3376 Widget w;
3377 #endif
3379 ((TextWidget) w)->text.update_disabled = True;
3380 _XawTextPrepareToUpdate( (TextWidget) w);
3383 void
3384 #if NeedFunctionPrototypes
3385 XawTextEnableRedisplay(Widget w)
3386 #else
3387 XawTextEnableRedisplay(w)
3388 Widget w;
3389 #endif
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);
3409 Widget
3410 #if NeedFunctionPrototypes
3411 XawTextGetSource(Widget w)
3412 #else
3413 XawTextGetSource(w)
3414 Widget w;
3415 #endif
3417 return ((TextWidget)w)->text.source;
3420 void
3421 #if NeedFunctionPrototypes
3422 XawTextDisplayCaret (Widget w,
3423 #if NeedWidePrototypes
3424 /* Boolean */ int display_caret)
3425 #else
3426 Boolean display_caret)
3427 #endif
3428 #else
3429 XawTextDisplayCaret (w, display_caret)
3430 Widget w;
3431 Boolean display_caret;
3432 #endif
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);
3443 else
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
3452 * to search for.
3453 * Returns: The position of the text found, or XawTextSearchError on
3454 * an error.
3457 XawTextPosition
3458 #if NeedFunctionPrototypes
3459 XawTextSearch(Widget w,
3460 #if NeedWidePrototypes
3461 /* XawTextScanDirection */ int dir,
3462 #else
3463 XawTextScanDirection dir,
3464 #endif
3465 XawTextBlock *text)
3466 #else
3467 XawTextSearch(w, dir, text)
3468 Widget w;
3469 XawTextScanDirection dir;
3470 XawTextBlock * text;
3471 #endif
3473 TextWidget ctx = (TextWidget) w;
3475 return(SrcSearch(ctx->text.source, ctx->text.insertPos, dir, text));
3478 TextClassRec textClassRec = {
3479 { /* core fields */
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
3516 { /* text fields */
3517 /* empty */ 0
3521 WidgetClass textWidgetClass = (WidgetClass)&textClassRec;