Merge branch 'master' into xcircuit-3.10
[xcircuit.git] / Xw / TextEdit.c
blobf94bcd9c27cb63e61ca1bbbf094124c5a71e20d5
1 /*************************************<+>*************************************
2 *****************************************************************************
3 **
4 ** File: TextEdit.c
5 **
6 ** Project: X Widgets
7 **
8 ** Description: Code for TextEdit widget
9 **
10 *****************************************************************************
11 **
12 ** Copyright (c) 1988 by Hewlett-Packard Company
13 ** Copyright (c) 1987, 1988 by Digital Equipment Corporation, Maynard,
14 ** Massachusetts, and the Massachusetts Institute of Technology,
15 ** Cambridge, Massachusetts
16 **
17 ** Permission to use, copy, modify, and distribute this software
18 ** and its documentation for any purpose and without fee is hereby
19 ** granted, provided that the above copyright notice appear in all
20 ** copies and that both that copyright notice and this permission
21 ** notice appear in supporting documentation, and that the names of
22 ** Hewlett-Packard, Digital or M.I.T. not be used in advertising or
23 ** publicity pertaining to distribution of the software without
24 ** written prior permission.
25 **
26 ** DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
27 ** ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
28 ** DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
29 ** ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
30 ** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
31 ** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
32 ** SOFTWARE.
33 **
34 *****************************************************************************
35 *************************************<+>*************************************/
37 #include <stdio.h>
38 #ifdef SYSV
39 #include <fcntl.h>
40 #include <string.h>
41 #else
42 #include <strings.h>
43 #endif /* SYSV */
44 #include <X11/Xos.h>
46 #include <X11/Xlib.h>
47 #include <X11/cursorfont.h>
48 #include <X11/IntrinsicP.h>
49 #include <X11/StringDefs.h>
50 #include <Xw/Xw.h>
51 #include <Xw/XwP.h>
53 #include <Xw/TextEdit.h>
54 #include <Xw/TextEditP.h>
55 #include <X11/Xutil.h> /* This include depends on something above it */
57 #define BufMax 1000
58 #define abs(x) (((x) < 0) ? (-(x)) : (x))
59 #define min(x,y) ((x) < (y) ? (x) : (y))
60 #define max(x,y) ((x) > (y) ? (x) : (y))
61 #define GETLASTPOS(ctx) ((*(ctx->text.source->getLastPos)) (ctx->text.source))
63 #define BUTTONMASK 0x143d
65 #define zeroPosition ((XwTextPosition) 0)
67 /******************************************************************************
69 * Resources for TextEdit
71 ******************************************************************************/
73 static XtResource resources[] = {
74 /* Resources from other classes with new defaults */
75 {XtNheight,
76 XtCHeight,
77 XtRDimension,
78 sizeof(Dimension),
79 XtOffset(XwTextEditWidget, core.height),
80 XtRString,
81 "200"},
82 {XtNwidth,
83 XtCWidth,
84 XtRDimension,
85 sizeof(Dimension),
86 XtOffset(XwTextEditWidget, core.width),
87 XtRString,
88 "200"},
89 /* New resources for TextEdit */
90 {XtNdisplayPosition,
91 XtCTextPosition,
92 XtRInt,
93 sizeof (XwTextPosition),
94 XtOffset(XwTextEditWidget, text.lt.top),
95 XtRString, "0"},
96 {XtNinsertPosition,
97 XtCTextPosition,
98 XtRInt,
99 sizeof(XwTextPosition),
100 XtOffset(XwTextEditWidget, text.insertPos),
101 XtRString,
102 "0"},
103 {XtNleftMargin,
104 XtCMargin,
105 XtRDimension,
106 sizeof (Dimension),
107 XtOffset(XwTextEditWidget, text.leftmargin),
108 XtRString,
109 "2"},
110 {XtNrightMargin,
111 XtCMargin,
112 XtRDimension,
113 sizeof (Dimension),
114 XtOffset(XwTextEditWidget, text.rightmargin),
115 XtRString,
116 "2"},
117 {XtNtopMargin,
118 XtCMargin,
119 XtRDimension,
120 sizeof (Dimension),
121 XtOffset(XwTextEditWidget, text.topmargin),
122 XtRString,
123 "2"},
124 {XtNbottomMargin,
125 XtCMargin,
126 XtRDimension,
127 sizeof (Dimension),
128 XtOffset(XwTextEditWidget, text.bottommargin),
129 XtRString,
130 "2"},
131 {XtNsourceType,
132 XtCSourceType,
133 XtRSourceType,
134 sizeof(XwSourceType),
135 XtOffset(XwTextEditWidget, text.srctype),
136 XtRString,
137 "stringsrc"},
138 {XtNtextSource,
139 XtCTextSource,
140 XtRPointer,
141 sizeof (caddr_t),
142 XtOffset(XwTextEditWidget, text.source),
143 XtRPointer,
144 NULL},
145 {XtNselection,
146 XtCSelection,
147 XtRPointer,
148 sizeof(caddr_t),
149 XtOffset(XwTextEditWidget, text.s),
150 XtRPointer,
151 NULL},
152 {XtNmotionVerification,
153 XtCCallback,
154 XtRCallback,
155 sizeof(XtCallbackProc),
156 XtOffset(XwTextEditWidget, text.motion_verification),
157 XtRCallback,
158 (caddr_t) NULL},
159 {XtNmodifyVerification,
160 XtCCallback,
161 XtRCallback,
162 sizeof(XtCallbackProc),
163 XtOffset(XwTextEditWidget, text.modify_verification),
164 XtRCallback,
165 (caddr_t) NULL},
166 {XtNleaveVerification,
167 XtCCallback,
168 XtRCallback,
169 sizeof(XtCallbackProc),
170 XtOffset(XwTextEditWidget, text.leave_verification),
171 XtRCallback,
172 (caddr_t) NULL},
173 {XtNexecute,
174 XtCCallback,
175 XtRCallback,
176 sizeof(XtCallbackProc),
177 XtOffset(XwTextEditWidget, text.execute),
178 XtRCallback,
179 (caddr_t) NULL},
180 {XtNwrap,
181 XtCWrap,
182 XtRWrap,
183 sizeof (XwWrap),
184 XtOffset (XwTextEditWidget, text.wrap_mode),
185 XtRString,
186 "softwrap"},
187 {XtNwrapForm,
188 XtCWrapForm,
189 XtRWrapForm,
190 sizeof (XwWrapForm),
191 XtOffset (XwTextEditWidget, text.wrap_form),
192 XtRString,
193 "sourceform"},
194 {XtNwrapBreak,
195 XtCWrapBreak,
196 XtRWrapBreak,
197 sizeof (XwWrapBreak),
198 XtOffset (XwTextEditWidget, text.wrap_break),
199 XtRString,
200 "wrapwhitespace"},
201 {XtNscroll,
202 XtCScroll,
203 XtRScroll,
204 sizeof (XwScroll),
205 XtOffset (XwTextEditWidget, text.scroll_mode),
206 XtRString,
207 "autoscrolloff"},
208 {XtNgrow,
209 XtCGrow,
210 XtRGrow,
211 sizeof (XwGrow),
212 XtOffset (XwTextEditWidget, text.grow_mode),
213 XtRString,
214 "growoff"},
218 /******************************************************************************
220 * Forward declarations of functions to put into the class record
222 ******************************************************************************/
223 static void Initialize();
224 static void Realize();
225 static void TextDestroy();
226 static void Resize();
227 static void ProcessExposeRegion();
228 static Boolean SetValues();
229 static unsigned char* _XwTextCopySubString();
231 /******************************************************************************
233 * Forward declarations of action functions to put into the action table
235 ******************************************************************************/
236 static void TraverseUp();
237 static void TraverseDown();
238 static void TraverseLeft();
239 static void TraverseRight();
240 static void TraverseNext();
241 static void TraversePrev();
242 static void TraverseHome();
243 static void TraverseNextTop();
244 static void Enter();
245 static void Leave();
246 static void Execute();
247 static void RedrawDisplay();
248 static void InsertChar();
249 static void TextFocusIn();
250 static void TextFocusOut();
251 static void MoveForwardChar();
252 static void MoveBackwardChar();
253 static void MoveForwardWord();
254 static void MoveBackwardWord();
255 static void MoveForwardParagraph();
256 static void MoveBackwardParagraph();
257 static void MoveToLineStart();
258 static void MoveToLineEnd();
259 static void MoveNextLine();
260 static void MovePreviousLine();
261 static void MoveNextPage();
262 static void MovePreviousPage();
263 static void MoveBeginningOfFile();
264 static void MoveEndOfFile();
265 static void ScrollOneLineUp();
266 static void ScrollOneLineDown();
267 static void DeleteForwardChar();
268 static void DeleteBackwardChar();
269 static void DeleteBackwardNormal();
270 static void DeleteForwardWord();
271 static void DeleteBackwardWord();
272 static void DeleteCurrentSelection();
273 static void KillForwardWord();
274 static void KillBackwardWord();
275 static void KillCurrentSelection();
276 static void KillToEndOfLine();
277 static void KillToEndOfParagraph();
278 static void UnKill();
279 static void Stuff();
280 static void InsertNewLineAndIndent();
281 static void InsertNewLineAndBackup();
282 static XwEditResult InsertNewLine();
283 static void SelectWord();
284 static void SelectAll();
285 static void SelectStart();
286 static void SelectAdjust();
287 static void SelectEnd();
288 static void ExtendStart();
289 static void ExtendAdjust();
290 static void ExtendEnd();
292 /******************************************************************************
294 * TextEdit Actions Table
296 ******************************************************************************/
297 XtActionsRec texteditActionsTable [] = {
298 /* motion bindings */
299 {"forward-character", MoveForwardChar},
300 {"backward-character", MoveBackwardChar},
301 {"forward-word", MoveForwardWord},
302 {"backward-word", MoveBackwardWord},
303 {"forward-paragraph", MoveForwardParagraph},
304 {"backward-paragraph", MoveBackwardParagraph},
305 {"beginning-of-line", MoveToLineStart},
306 {"end-of-line", MoveToLineEnd},
307 {"next-line", MoveNextLine},
308 {"previous-line", MovePreviousLine},
309 {"next-page", MoveNextPage},
310 {"previous-page", MovePreviousPage},
311 {"beginning-of-file", MoveBeginningOfFile},
312 {"end-of-file", MoveEndOfFile},
313 {"scroll-one-line-up", ScrollOneLineUp},
314 {"scroll-one-line-down", ScrollOneLineDown},
315 /* delete bindings */
316 {"delete-next-character", DeleteForwardChar},
317 {"delete-previous-character", DeleteBackwardNormal},
318 {"delete-next-word", DeleteForwardWord},
319 {"delete-previous-word", DeleteBackwardWord},
320 {"delete-selection", DeleteCurrentSelection},
321 /* kill bindings */
322 {"kill-word", KillForwardWord},
323 {"backward-kill-word", KillBackwardWord},
324 {"kill-selection", KillCurrentSelection},
325 {"kill-to-end-of-line", KillToEndOfLine},
326 {"kill-to-end-of-paragraph", KillToEndOfParagraph},
327 /* unkill bindings */
328 {"unkill", UnKill},
329 {"stuff", Stuff},
330 /* new line stuff */
331 {"newline-and-indent", InsertNewLineAndIndent},
332 {"newline-and-backup", InsertNewLineAndBackup},
333 {"newline", (XtActionProc)InsertNewLine},
334 /* Selection stuff */
335 {"select-word", SelectWord},
336 {"select-all", SelectAll},
337 {"select-start", SelectStart},
338 {"select-adjust", SelectAdjust},
339 {"select-end", SelectEnd},
340 {"extend-start", ExtendStart},
341 {"extend-adjust", ExtendAdjust},
342 {"extend-end", ExtendEnd},
343 /* Miscellaneous */
344 {"redraw-display", RedrawDisplay},
345 {"insert-char", InsertChar},
346 {"focus-in", TextFocusIn},
347 {"focus-out", TextFocusOut},
348 /* traversal direction functions */
349 {"traverse-left", TraverseLeft},
350 {"traverse-right", TraverseRight},
351 {"traverse-next", TraverseNext},
352 {"traverse-prev", TraversePrev},
353 {"traverse-up", TraverseUp},
354 {"traverse-down", TraverseDown},
355 {"traverse-home", TraverseHome},
356 {"traverse-next-top", TraverseNextTop},
357 /* highlighting */
358 {"enter", Enter},
359 {"leave", Leave},
360 {"execute", Execute},
361 {NULL,NULL}
364 /****************************************************************************
366 * TextEdit Default Event Translations
368 ****************************************************************************/
369 char defaultTextEditTranslations[] =
370 "Ctrl<Key>F: forward-character()\n\
371 Ctrl<Key>Right: traverse-right()\n\
372 <Key>Right: forward-character()\n\
373 Ctrl<Key>B: backward-character()\n\
374 Ctrl<Key>Left: traverse-left()\n\
375 <Key>Left: backward-character()\n\
376 Meta<Key>F: forward-word()\n\
377 Meta<Key>B: backward-word()\n\
378 Meta<Key>]: forward-paragraph()\n\
379 Ctrl<Key>[: backward-paragraph()\n\
380 Ctrl<Key>A: beginning-of-line()\n\
381 Ctrl<Key>E: end-of-line()\n\
382 Ctrl<Key>N: next-line()\n\
383 Ctrl<Key>Down: traverse-down()\n\
384 <Key>Down: next-line()\n\
385 Ctrl<Key>P: previous-line()\n\
386 Ctrl<Key>Up: traverse-up()\n\
387 <Key>Up: previous-line()\n\
388 Ctrl<Key>V: next-page()\n\
389 Ctrl<Key>Next: traverse-next()\n\
390 <Key>Next: next-page()\n\
391 Meta<Key>V: previous-page()\n\
392 Ctrl<Key>Prior: traverse-prev()\n\
393 <Key>Prior: previous-page()\n\
394 Meta<Key>\\<: beginning-of-file()\n\
395 Meta<Key>\\>: end-of-file()\n\
396 Ctrl<Key>Home: traverse-home()\n\
397 Shift<Key>Home: end-of-file()\n\
398 <Key>Home: beginning-of-file()\n\
399 Ctrl<Key>Z: scroll-one-line-up()\n\
400 Meta<Key>Z: scroll-one-line-down()\n\
401 Ctrl<Key>D: delete-next-character()\n\
402 <Key>Delete: delete-previous-character()\n\
403 <Key>BackSpace: delete-previous-character()\n\
404 Ctrl<Key>H: delete-previous-character()\n\
405 Meta<Key>D: delete-next-word()\n\
406 Meta<Key>H: delete-previous-word()\n\
407 Shift Meta<Key>D: kill-word()\n\
408 Shift Meta<Key>H: backward-kill-word()\n\
409 Ctrl<Key>W: kill-selection()\n\
410 Ctrl<Key>K: kill-to-end-of-line()\n\
411 Meta<Key>K: kill-to-end-of-paragraph()\n\
412 Ctrl<Key>Y: unkill()\n\
413 Meta<Key>Y: stuff()\n\
414 Ctrl<Key>J: newline-and-indent()\n\
415 Ctrl<Key>O: newline-and-backup()\n\
416 Ctrl<Key>M: newline()\n\
417 <Key>Return: newline()\n\
418 <Key>Linefeed: newline-and-indent()\n\
419 Ctrl<Key>L: redraw-display()\n\
420 <FocusIn>: focus-in()\n\
421 <FocusOut>: focus-out()\n\
422 <Btn1Down>: select-start()\n\
423 Button1<PtrMoved>: extend-adjust()\n\
424 <Btn1Up>: extend-end()\n\
425 <Btn2Down>: stuff()\n\
426 <Btn3Down>: extend-start()\n\
427 Button3<PtrMoved>: extend-adjust()\n\
428 <Btn3Up>: extend-end()\n\
429 <Key>Execute: execute()\n\
430 <Key>: insert-char()\n\
431 Shift<Key>: insert-char()\n\
432 <EnterWindow>: enter()\n\
433 <LeaveWindow>: leave()";
436 /* Utility routines for support of TextEdit */
437 #include "sub.c"
439 /******************************************************************************
441 * Functions to support selection
443 ******************************************************************************/
444 /*--------------------------------------------------------------------------+*/
445 static void _XtTextSetNewSelection(ctx, left, right)
446 /*--------------------------------------------------------------------------+*/
447 XwTextEditWidget ctx;
448 XwTextPosition left, right;
450 XwTextPosition pos;
452 if (left < ctx->text.s.left) {
453 pos = min(right, ctx->text.s.left);
454 _XtTextNeedsUpdating(ctx, left, pos);
456 if (left > ctx->text.s.left) {
457 pos = min(left, ctx->text.s.right);
458 _XtTextNeedsUpdating(ctx, ctx->text.s.left, pos);
460 if (right < ctx->text.s.right) {
461 pos = max(right, ctx->text.s.left);
462 _XtTextNeedsUpdating(ctx, pos, ctx->text.s.right);
464 if (right > ctx->text.s.right) {
465 pos = max(left, ctx->text.s.right);
466 _XtTextNeedsUpdating(ctx, pos, right);
469 ctx->text.s.left = left;
470 ctx->text.s.right = right;
475 * This routine implements multi-click selection in a hardwired manner.
476 * It supports multi-click entity cycling (char, word, line, file) and mouse
477 * motion adjustment of the selected entitie (i.e. select a word then, with
478 * button still down, adjust wich word you really meant by moving the mouse).
479 * [NOTE: This routine is to be replaced by a set of procedures that
480 * will allows clients to implements a wide class of draw through and
481 * multi-click selection user interfaces.]
483 /*--------------------------------------------------------------------------+*/
484 static void DoSelection (ctx, position, time, motion)
485 /*--------------------------------------------------------------------------+*/
486 XwTextEditWidget ctx;
487 XwTextPosition position;
488 Time time;
489 Boolean motion;
491 int delta;
492 XwTextPosition newLeft, newRight;
493 XwSelectType newType;
494 XwSelectType *sarray;
496 delta = (time < ctx->text.lasttime) ?
497 ctx->text.lasttime - time : time - ctx->text.lasttime;
498 if (motion)
499 newType = ctx->text.s.type;
500 else {/* multi-click event */
501 if ((delta < 500) && ((position >= ctx->text.s.left)
502 && (position <= ctx->text.s.right))) {
503 sarray = ctx->text.sarray;
504 for (sarray = ctx->text.sarray;
505 *sarray != XwselectNull && *sarray != ctx->text.s.type;
506 sarray++) ;
507 if (*sarray != XwselectNull) sarray++;
508 if (*sarray == XwselectNull) sarray = ctx->text.sarray;
509 newType = *sarray;
510 } else { /* single-click event */
511 newType = *(ctx->text.sarray);
513 ctx->text.lasttime = time;
515 switch (newType) {
516 case XwselectPosition:
517 newLeft = newRight = position;
518 break;
519 case XwselectChar:
520 newLeft = position;
521 newRight = (*(ctx->text.source->scan))(
522 ctx->text.source, position, position, XwsdRight, 1, FALSE);
523 break;
524 case XwselectWord:
525 newLeft = (*(ctx->text.source->scan))
526 (ctx->text.source, position, XwstWhiteSpace, XwsdLeft, 1, FALSE);
527 newRight = (*(ctx->text.source->scan))
528 (ctx->text.source, position, XwstWhiteSpace, XwsdRight, 1, FALSE);
529 break;
530 case XwselectLine:
531 case XwselectParagraph: /* need "para" scan mode to implement pargraph */
532 newLeft = (*(ctx->text.source->scan))(
533 ctx->text.source, position, XwstEOL, XwsdLeft, 1, FALSE);
534 newRight = (*(ctx->text.source->scan))(
535 ctx->text.source, position, XwstEOL, XwsdRight, 1, FALSE);
536 break;
537 case XwselectAll:
538 newLeft = (*(ctx->text.source->scan))(
539 ctx->text.source, position, XwstLast, XwsdLeft, 1, FALSE);
540 newRight = (*(ctx->text.source->scan))(
541 ctx->text.source, position, XwstLast, XwsdRight, 1, FALSE);
542 break;
543 default:
544 break;
546 if ((newLeft != ctx->text.s.left) || (newRight != ctx->text.s.right)
547 || (newType != ctx->text.s.type)) {
548 _XtTextSetNewSelection(ctx, newLeft, newRight);
549 ctx->text.s.type = newType;
550 if (position - ctx->text.s.left < ctx->text.s.right - position)
551 ctx->text.insertPos = newLeft;
552 else
553 ctx->text.insertPos = newRight;
555 if (!motion) { /* setup so we can freely mix select extend calls*/
556 ctx->text.origSel.type = ctx->text.s.type;
557 ctx->text.origSel.left = ctx->text.s.left;
558 ctx->text.origSel.right = ctx->text.s.right;
559 if (position >= ctx->text.s.left +
560 ((ctx->text.s.right - ctx->text.s.left) / 2))
561 ctx->text.extendDir = XwsdRight;
562 else
563 ctx->text.extendDir = XwsdLeft;
568 * This routine implements extension of the currently selected text in
569 * the "current" mode (i.e. char word, line, etc.). It worries about
570 * extending from either end of the selection and handles the case when you
571 * cross through the "center" of the current selection (e.g. switch which
572 * end you are extending!).
573 * [NOTE: This routine will be replaced by a set of procedures that
574 * will allows clients to implements a wide class of draw through and
575 * multi-click selection user interfaces.]
577 /*--------------------------------------------------------------------------+*/
578 static void ExtendSelection (ctx, position, motion)
579 /*--------------------------------------------------------------------------+*/
580 XwTextEditWidget ctx;
581 XwTextPosition position;
582 Boolean motion;
584 XwTextPosition newLeft, newRight;
587 if (!motion) { /* setup for extending selection */
588 ctx->text.origSel.type = ctx->text.s.type;
589 ctx->text.origSel.left = ctx->text.s.left;
590 ctx->text.origSel.right = ctx->text.s.right;
591 if (position >= ctx->text.s.left +
592 ((ctx->text.s.right - ctx->text.s.left) / 2))
593 ctx->text.extendDir = XwsdRight;
594 else
595 ctx->text.extendDir = XwsdLeft;
597 else /* check for change in extend direction */
598 if ((ctx->text.extendDir == XwsdRight &&
599 position < ctx->text.origSel.left) ||
600 (ctx->text.extendDir == XwsdLeft &&
601 position > ctx->text.origSel.right)) {
602 ctx->text.extendDir =
603 (ctx->text.extendDir == XwsdRight)? XwsdLeft : XwsdRight;
604 _XtTextSetNewSelection(ctx, ctx->text.origSel.left,
605 ctx->text.origSel.right);
607 newLeft = ctx->text.s.left;
608 newRight = ctx->text.s.right;
609 switch (ctx->text.s.type) {
610 case XwselectPosition:
611 if (ctx->text.extendDir == XwsdRight)
612 newRight = position;
613 else
614 newLeft = position;
615 break;
616 case XwselectWord:
617 if (ctx->text.extendDir == XwsdRight)
618 newRight = position = (*(ctx->text.source->scan))
619 (ctx->text.source, position, XwstWhiteSpace, XwsdRight, 1, FALSE);
620 else
621 newLeft = position = (*(ctx->text.source->scan))
622 (ctx->text.source, position, XwstWhiteSpace, XwsdLeft, 1, FALSE);
623 break;
624 case XwselectLine:
625 case XwselectParagraph: /* need "para" scan mode to implement pargraph */
626 if (ctx->text.extendDir == XwsdRight)
627 newRight = position = (*(ctx->text.source->scan))
628 (ctx->text.source, position, XwstEOL, XwsdRight, 1, TRUE);
629 else
630 newLeft = position = (*(ctx->text.source->scan))
631 (ctx->text.source, position, XwstEOL, XwsdLeft, 1, FALSE);
632 break;
633 case XwselectAll:
634 position = ctx->text.insertPos;
635 break;
636 default:
637 break;
639 _XtTextSetNewSelection(ctx, newLeft, newRight);
640 ctx->text.insertPos = position;
645 * This routine is used to perform various selection functions. The goal is
646 * to be able to specify all the more popular forms of draw-through and
647 * multi-click selection user interfaces from the outside.
649 /*--------------------------------------------------------------------------+*/
650 static void AlterSelection (ctx, mode, action)
651 /*--------------------------------------------------------------------------+*/
652 XwTextEditWidget ctx;
653 XwSelectionMode mode; /* {XwsmTextSelect, XwsmTextExtend} */
654 XwSelectionAction action; /* {XwactionStart, XwactionAdjust, XwactionEnd} */
656 XwTextPosition position;
657 unsigned char *ptr;
659 position = PositionForXY (ctx, (int) ctx->text.ev_x, (int) ctx->text.ev_y);
660 if (action == XwactionStart) {
661 switch (mode) {
662 case XwsmTextSelect:
663 DoSelection (ctx, position, ctx->text.time, FALSE);
664 break;
665 case XwsmTextExtend:
666 ExtendSelection (ctx, position, FALSE);
667 break;
670 else {
671 switch (mode) {
672 case XwsmTextSelect:
673 DoSelection (ctx, position, ctx->text.time, TRUE);
674 break;
675 case XwsmTextExtend:
676 ExtendSelection (ctx, position, TRUE);
677 break;
680 if (action == XwactionEnd && ctx->text.s.left < ctx->text.s.right) {
681 ptr = _XwTextCopySubString (ctx, ctx->text.s.left, ctx->text.s.right);
682 XStoreBuffer (XtDisplay(ctx), ptr, min (XwStrlen (ptr), MAXCUT), 0);
683 XtFree (ptr);
687 /******************************************************************************
689 * TextEdit Class Methods
691 ******************************************************************************/
693 /*****************************************************************************
694 * This method deletes the text from startPos to endPos in a source and
695 * then inserts, at startPos, the text that was passed. As a side effect it
696 * "invalidates" that portion of the displayed text (if any), so that things
697 * will be repainted properly.
698 ******************************************************************************/
700 /*--------------------------------------------------------------------------+*/
701 static int _XwTextSubString(ctx, left, right, target, size, used)
702 /*--------------------------------------------------------------------------+*/
703 XwTextEditWidget ctx;
704 XwTextPosition left, right;
705 unsigned char *target; /* Memory to copy into */
706 int size, /* Size of memory */
707 *used; /* Memory used by copy */
709 unsigned char *tempResult;
710 int length, n;
711 XwTextBlock text;
712 XwTextPosition end, nend;
714 end = (*(ctx->text.source->read))(ctx->text.source, left, &text,
715 right - left);
716 n = length = min(text.length,size);
717 strncpy(target, text.ptr, n);
718 while (n && (end < right) && (length < size)) {
719 nend = (*(ctx->text.source->read))(ctx->text.source, end, &text,
720 right - end);
721 n = text.length;
722 if (length + n > size) n = size - length;
723 tempResult = target + length;
724 strncpy(tempResult, text.ptr, n);
725 length += n;
726 end = nend;
728 *used = length;
729 return length; /* return the number of positions transfered to target */
732 /*--------------------------------------------------------------------------+*/
733 static unsigned char *_XwTextCopySubString(ctx, left, right)
734 /*--------------------------------------------------------------------------+*/
735 XwTextEditWidget ctx;
736 XwTextPosition left, right;
738 unsigned char *result;
739 int length, resultLength;
740 int dummy;
742 resultLength = right - left + 10; /* Bogus? %%% */
743 result = (unsigned char *)XtMalloc((unsigned) resultLength);
745 length = _XwTextSubString(ctx, left, right, result, resultLength, &dummy);
747 result[length] = 0;
748 return result;
751 /*--------------------------------------------------------------------------+*/
752 static unsigned char *_XwTextCopySelection(ctx)
753 /*--------------------------------------------------------------------------+*/
754 XwTextEditWidget ctx;
756 return( _XwTextCopySubString(ctx, ctx->text.s.left, ctx->text.s.right));
759 /*--------------------------------------------------------------------------+*/
760 static void _XwTextSetSelection(w, left, right)
761 /*--------------------------------------------------------------------------+*/
762 Widget w;
763 Position left, right;
765 XwTextEditWidget ctx = (XwTextEditWidget) w;
767 _XtTextPrepareToUpdate(ctx);
768 _XtTextSetNewSelection(ctx, (XwTextPosition)left, (XwTextPosition)right);
769 _XtTextExecuteUpdate(ctx);
772 /*--------------------------------------------------------------------------+*/
773 static void _XwTextUnsetSelection(w)
774 /*--------------------------------------------------------------------------+*/
775 Widget w;
777 XwTextEditWidget ctx = (XwTextEditWidget) w;
779 _XtTextPrepareToUpdate(ctx);
780 _XtTextSetNewSelection(ctx, zeroPosition, zeroPosition);
781 _XtTextExecuteUpdate(ctx);
784 /*--------------------------------------------------------------------------+*/
785 static XwEditResult _XwTextReplace(w, startPos, endPos, text, verify)
786 /*--------------------------------------------------------------------------+*/
787 Widget w;
788 XwTextPosition startPos, endPos;
789 XwTextBlock *text;
790 Boolean verify;
792 XwTextEditWidget ctx = (XwTextEditWidget) w;
793 XwEditResult result;
795 _XtTextPrepareToUpdate(ctx);
796 result = ReplaceText(ctx, startPos, endPos, text, verify);
797 _XtTextExecuteUpdate(ctx);
798 return result;
801 /*--------------------------------------------------------------------------+*/
802 static void _XwTextRedraw (w)
803 /*--------------------------------------------------------------------------+*/
804 Widget w;
806 XwTextEditWidget ctx = (XwTextEditWidget) w;
808 _XtTextPrepareToUpdate(ctx);
809 ForceBuildLineTable(ctx);
810 DisplayAllText(ctx);
811 _XtTextExecuteUpdate(ctx);
812 if (ctx->primitive.highlighted)
813 _XwHighlightBorder(ctx);
817 /******************************************************************************
819 * Utilities
821 ******************************************************************************/
822 /*--------------------------------------------------------------------------+*/
823 static XwEditResult _XwSetCursorPos(ctx, newposition)
824 /*--------------------------------------------------------------------------+*/
825 XwTextEditWidget ctx;
826 XwTextPosition newposition;
828 XwTextVerifyCD cbdata;
830 cbdata.operation = motionVerify;
831 cbdata.doit = TRUE;
832 cbdata.currInsert = ctx->text.insertPos;
833 cbdata.newInsert = newposition;
835 XtCallCallbacks((Widget)ctx, XtNmotionVerification, &cbdata);
837 if (!cbdata.doit) return XweditReject;
839 ctx->text.insertPos = cbdata.newInsert;
841 return XweditDone;
844 /*--------------------------------------------------------------------------+*/
845 static void StartAction(ctx, event)
846 /*--------------------------------------------------------------------------+*/
847 XwTextEditWidget ctx;
848 XEvent *event;
850 _XtTextPrepareToUpdate(ctx);
851 if (event) {
852 ctx->text.time = event->xbutton.time;
853 ctx->text.ev_x = event->xbutton.x;
854 ctx->text.ev_y = event->xbutton.y;
858 /*--------------------------------------------------------------------------+*/
859 static void EndAction(ctx)
860 /*--------------------------------------------------------------------------+*/
861 XwTextEditWidget ctx;
863 CheckResizeOrOverflow(ctx);
864 _XtTextExecuteUpdate(ctx);
867 /*--------------------------------------------------------------------------+*/
868 static void DeleteOrKill(ctx, from, to, kill)
869 /*--------------------------------------------------------------------------+*/
870 XwTextEditWidget ctx;
871 XwTextPosition from, to;
872 Boolean kill;
874 XwTextBlock text;
875 unsigned char *ptr;
876 XwEditResult result;
878 if (kill && from < to)
879 ptr = _XwTextCopySubString(ctx, from, to);
881 text.length = 0;
883 if (result = ReplaceText(ctx, from, to, &text, TRUE)) {
884 if (result != XweditReject)
885 XBell(XtDisplay(ctx), 50);
886 if (kill && from < to)
887 XtFree(ptr);
888 return;
891 if (kill && from < to) {
892 XStoreBuffer(XtDisplay(ctx), ptr, XwStrlen(ptr), 1);
893 XtFree(ptr);
895 _XwSetCursorPos(ctx, from);
896 ctx->text.showposition = TRUE;
898 from = ctx->text.insertPos;
899 _XtTextSetNewSelection(ctx, from, from);
903 /*--------------------------------------------------------------------------+*/
904 static void StuffFromBuffer(ctx, buffer)
905 /*--------------------------------------------------------------------------+*/
906 XwTextEditWidget ctx;
907 int buffer;
909 extern char *XFetchBuffer();
910 XwTextBlock text;
911 XwEditResult result;
912 XwTextPosition nextcursorpos;
914 text.ptr =
915 (unsigned char*)XFetchBuffer(XtDisplay(ctx), &(text.length), buffer);
916 if (result =
917 ReplaceText(ctx, ctx->text.insertPos, ctx->text.insertPos,
918 &text, TRUE)) {
919 if (result != XweditReject)
920 XBell(XtDisplay(ctx), 50);
921 XtFree(text.ptr);
922 return;
924 nextcursorpos = (*(ctx->text.source->scan))
925 (ctx->text.source, ctx->text.insertPos, XwstPositions, XwsdRight,
926 text.length, TRUE);
927 _XwSetCursorPos(ctx, nextcursorpos);
928 nextcursorpos = ctx->text.insertPos;
929 _XtTextSetNewSelection(ctx, nextcursorpos, nextcursorpos);
930 XtFree(text.ptr);
933 /*--------------------------------------------------------------------------+*/
934 static XwTextPosition NextPosition(ctx, position, kind, direction)
935 /*--------------------------------------------------------------------------+*/
936 XwTextEditWidget ctx;
937 XwTextPosition position;
938 XwScanType kind;
939 XwScanDirection direction;
941 XwTextPosition pos;
943 pos = (*(ctx->text.source->scan))(
944 ctx->text.source, position, kind, direction, 1, FALSE);
945 if (pos == ctx->text.insertPos)
946 pos = (*(ctx->text.source->scan))(
947 ctx->text.source, position, kind, direction, 2, FALSE);
948 return pos;
951 /*--------------------------------------------------------------------------+*/
952 static XwEditResult InsertNewLineAndBackupInternal(ctx)
953 /*--------------------------------------------------------------------------+*/
954 XwTextEditWidget ctx;
956 XwTextBlock text;
957 XwEditResult result;
959 text.length = 1;
960 text.ptr = (unsigned char*)"\n";
961 text.firstPos = 0;
962 if (result =
963 ReplaceText(ctx, ctx->text.insertPos, ctx->text.insertPos,
964 &text, TRUE)) {
965 if (result != XweditReject)
966 XBell( XtDisplay(ctx), 50);
967 return(result);
969 _XtTextSetNewSelection(ctx, (XwTextPosition) 0, (XwTextPosition) 0);
970 ctx->text.showposition = TRUE;
971 return(result);
973 /* Insert a file of the given name into the text. Returns 0 if file found,
974 -1 if not. */
976 /* Unadvertized function */
977 /*--------------------------------------------------------------------------+*/
978 int XwTextInsertFile(ctx, str)
979 /*--------------------------------------------------------------------------+*/
980 XwTextEditWidget ctx;
981 unsigned char *str;
983 int fid;
984 XwTextBlock text;
985 unsigned char buf[1000];
986 XwTextPosition position;
988 if (str == NULL || XwStrlen(str) == 0) return -1;
989 fid = open(str, O_RDONLY);
990 if (fid <= 0) return -1;
991 _XtTextPrepareToUpdate(ctx);
992 position = ctx->text.insertPos;
993 while ((text.length = read(fid, buf, 512)) > 0) {
994 text.ptr = buf;
995 ReplaceText(ctx, position, position, &text, TRUE);
996 position = (*(ctx->text.source->scan))(ctx->text.source, position,
997 XwstPositions, XwsdRight, text.length, TRUE);
999 close(fid);
1000 ctx->text.insertPos = position;
1001 _XtTextExecuteUpdate(ctx);
1002 return 0;
1005 /******************************************************************************
1007 * Action Table Functions
1009 ******************************************************************************/
1010 /*--------------------------------------------------------------------------+*/
1011 static Boolean VerifyLeave(ctx,event)
1012 /*--------------------------------------------------------------------------+*/
1013 XwTextEditWidget ctx;
1014 XEvent *event;
1016 XwTextVerifyCD cbdata;
1018 StartAction(ctx, event);
1019 cbdata.operation = leaveVerify;
1020 cbdata.doit = TRUE;
1021 cbdata.currInsert = ctx->text.insertPos;
1022 cbdata.newInsert = ctx->text.insertPos;
1023 cbdata.startPos = ctx->text.insertPos;
1024 cbdata.endPos = ctx->text.insertPos;
1025 cbdata.text = NULL;
1026 cbdata.xevent = event;
1027 XtCallCallbacks((Widget)ctx, XtNleaveVerification, &cbdata);
1028 ctx->text.insertPos = cbdata.newInsert;
1029 EndAction(ctx);
1030 return( cbdata.doit );
1033 /*--------------------------------------------------------------------------+*/
1034 static void TraverseUp(ctx, event)
1035 /*--------------------------------------------------------------------------+*/
1036 XwTextEditWidget ctx;
1037 XEvent *event;
1039 /* Allow the verification routine to control the traversal */
1040 if (VerifyLeave(ctx, event))
1041 _XwTraverseUp((Widget)ctx, event);
1044 /*--------------------------------------------------------------------------+*/
1045 static void TraverseDown(ctx, event)
1046 /*--------------------------------------------------------------------------+*/
1047 XwTextEditWidget ctx;
1048 XEvent *event;
1050 /* Allow the verification routine to control the traversal */
1051 if (VerifyLeave(ctx, event))
1052 _XwTraverseDown((Widget)ctx, event);
1055 /*--------------------------------------------------------------------------+*/
1056 static void TraversePrev(ctx, event)
1057 /*--------------------------------------------------------------------------+*/
1058 XwTextEditWidget ctx;
1059 XEvent *event;
1061 /* Allow the verification routine to control the traversal */
1062 if (VerifyLeave(ctx, event))
1063 _XwTraversePrev((Widget)ctx, event);
1066 /*--------------------------------------------------------------------------+*/
1067 static void TraverseNext(ctx, event)
1068 /*--------------------------------------------------------------------------+*/
1069 XwTextEditWidget ctx;
1070 XEvent *event;
1072 /* Allow the verification routine to control the traversal */
1073 if (VerifyLeave(ctx, event))
1074 _XwTraverseNext((Widget)ctx, event);
1077 /*--------------------------------------------------------------------------+*/
1078 static void TraverseLeft(ctx, event)
1079 /*--------------------------------------------------------------------------+*/
1080 XwTextEditWidget ctx;
1081 XEvent *event;
1083 /* Allow the verification routine to control the traversal */
1084 if (VerifyLeave(ctx, event))
1085 _XwTraverseLeft((Widget)ctx, event);
1088 /*--------------------------------------------------------------------------+*/
1089 static void TraverseRight(ctx, event)
1090 /*--------------------------------------------------------------------------+*/
1091 XwTextEditWidget ctx;
1092 XEvent *event;
1094 /* Allow the verification routine to control the traversal */
1095 if (VerifyLeave(ctx, event))
1096 _XwTraverseRight((Widget)ctx, event);
1099 /*--------------------------------------------------------------------------+*/
1100 static void TraverseHome(ctx, event)
1101 /*--------------------------------------------------------------------------+*/
1102 XwTextEditWidget ctx;
1103 XEvent *event;
1105 /* Allow the verification routine to control the traversal */
1106 if (VerifyLeave(ctx, event))
1107 _XwTraverseHome((Widget)ctx, event);
1110 /*--------------------------------------------------------------------------+*/
1111 static void TraverseNextTop(ctx, event)
1112 /*--------------------------------------------------------------------------+*/
1113 XwTextEditWidget ctx;
1114 XEvent *event;
1116 /* Allow the verification routine to control the traversal */
1117 if (VerifyLeave(ctx, event))
1118 _XwTraverseNextTop((Widget)ctx, event);
1121 /*--------------------------------------------------------------------------+*/
1122 static void Enter(ctx, event)
1123 /*--------------------------------------------------------------------------+*/
1124 XwTextEditWidget ctx;
1125 XEvent *event;
1127 _XwPrimitiveEnter((Widget)ctx, event);
1130 /*--------------------------------------------------------------------------+*/
1131 static void Leave(ctx, event)
1132 /*--------------------------------------------------------------------------+*/
1133 XwTextEditWidget ctx;
1134 XEvent *event;
1136 /* If traversal is on, then the leave verification callback is called
1137 in the focus out event handler */
1138 if (ctx->primitive.traversal_type != XwHIGHLIGHT_TRAVERSAL)
1139 VerifyLeave(ctx, event);
1141 _XwPrimitiveLeave((Widget)ctx, event);
1144 /*--------------------------------------------------------------------------+*/
1145 static void TextFocusIn (ctx, event)
1146 /*--------------------------------------------------------------------------+*/
1147 XwTextEditWidget ctx;
1148 XEvent *event;
1150 _XwPrimitiveFocusIn((XwPrimitiveWidget)ctx, event);
1151 ctx->text.hasfocus = TRUE;
1154 /*--------------------------------------------------------------------------+*/
1155 static void TextFocusOut(ctx, event)
1156 /*--------------------------------------------------------------------------+*/
1157 XwTextEditWidget ctx;
1158 XEvent *event;
1160 /* If traversal is on, then the leave verification callback is called in
1161 the traversal event handler */
1162 if (ctx->primitive.traversal_type != XwHIGHLIGHT_TRAVERSAL)
1163 VerifyLeave(ctx, event);
1165 _XwPrimitiveFocusOut((XwPrimitiveWidget)ctx, event);
1166 ctx->text.hasfocus = FALSE;
1169 /* Kill and Stuff */
1170 /*--------------------------------------------------------------------------+*/
1171 static void UnKill(ctx, event)
1172 /*--------------------------------------------------------------------------+*/
1173 XwTextEditWidget ctx;
1174 XEvent *event;
1176 StartAction(ctx, event);
1177 StuffFromBuffer(ctx, 1);
1178 EndAction(ctx);
1181 /*--------------------------------------------------------------------------+*/
1182 static void Stuff(ctx, event)
1183 /*--------------------------------------------------------------------------+*/
1184 XwTextEditWidget ctx;
1185 XEvent *event;
1187 StartAction(ctx, event);
1188 StuffFromBuffer(ctx, 0);
1189 EndAction(ctx);
1192 /* routines for moving around */
1194 /*--------------------------------------------------------------------------+*/
1195 static void MoveForwardChar(ctx, event)
1196 /*--------------------------------------------------------------------------+*/
1197 XwTextEditWidget ctx;
1198 XEvent *event;
1200 StartAction(ctx, event);
1201 _XwSetCursorPos(ctx, (*(ctx->text.source->scan))
1202 (ctx->text.source, ctx->text.insertPos, XwstPositions, XwsdRight, 1,
1203 TRUE)
1205 EndAction(ctx);
1208 /*--------------------------------------------------------------------------+*/
1209 static void MoveBackwardChar(ctx, event)
1210 /*--------------------------------------------------------------------------+*/
1211 XwTextEditWidget ctx;
1212 XEvent *event;
1214 StartAction(ctx, event);
1215 _XwSetCursorPos(ctx, (*(ctx->text.source->scan))
1216 (ctx->text.source, ctx->text.insertPos, XwstPositions, XwsdLeft, 1, TRUE)
1218 EndAction(ctx);
1221 /*--------------------------------------------------------------------------+*/
1222 static void MoveForwardWord(ctx, event)
1223 /*--------------------------------------------------------------------------+*/
1224 XwTextEditWidget ctx;
1225 XEvent *event;
1227 StartAction(ctx, event);
1228 _XwSetCursorPos(ctx,
1229 NextPosition(ctx, ctx->text.insertPos, XwstWhiteSpace, XwsdRight)
1231 EndAction(ctx);
1234 /*--------------------------------------------------------------------------+*/
1235 static void MoveBackwardWord(ctx, event)
1236 /*--------------------------------------------------------------------------+*/
1237 XwTextEditWidget ctx;
1238 XEvent *event;
1240 StartAction(ctx, event);
1241 _XwSetCursorPos(ctx,
1242 NextPosition(ctx, ctx->text.insertPos, XwstWhiteSpace, XwsdLeft)
1244 EndAction(ctx);
1247 /*--------------------------------------------------------------------------+*/
1248 static void MoveBackwardParagraph(ctx, event)
1249 /*--------------------------------------------------------------------------+*/
1250 XwTextEditWidget ctx;
1251 XEvent *event;
1253 StartAction(ctx, event);
1254 _XwSetCursorPos(ctx,
1255 NextPosition(ctx, ctx->text.insertPos, XwstEOL, XwsdLeft)
1257 EndAction(ctx);
1260 /*--------------------------------------------------------------------------+*/
1261 static void MoveForwardParagraph(ctx, event)
1262 /*--------------------------------------------------------------------------+*/
1263 XwTextEditWidget ctx;
1264 XEvent *event;
1266 StartAction(ctx, event);
1267 _XwSetCursorPos(ctx,
1268 NextPosition(ctx, ctx->text.insertPos, XwstEOL, XwsdRight)
1270 EndAction(ctx);
1273 /*--------------------------------------------------------------------------+*/
1274 static void MoveToLineStart(ctx, event)
1275 /*--------------------------------------------------------------------------+*/
1276 XwTextEditWidget ctx;
1277 XEvent *event;
1279 int line;
1280 StartAction(ctx, event);
1281 _XtTextShowPosition(ctx);
1282 line = LineForPosition(ctx, ctx->text.insertPos);
1283 _XwSetCursorPos(ctx, ctx->text.lt.info[line].position);
1284 EndAction(ctx);
1287 /*--------------------------------------------------------------------------+*/
1288 static void MoveToLineEnd(ctx, event)
1289 /*--------------------------------------------------------------------------+*/
1290 XwTextEditWidget ctx;
1291 XEvent *event;
1293 int line;
1294 XwTextPosition next, lastpos = GETLASTPOS(ctx);
1295 StartAction(ctx, event);
1296 _XtTextShowPosition(ctx);
1297 line = LineForPosition(ctx, ctx->text.insertPos);
1298 next = ctx->text.lt.info[line+1].position;
1299 if (next > lastpos)
1300 next = lastpos;
1301 else
1302 next = (*(ctx->text.source->scan))
1303 (ctx->text.source, next, XwstPositions, XwsdLeft, 1, TRUE);
1304 if (next <= ctx->text.lt.info[line].drawPos)
1305 next = ctx->text.lt.info[line].drawPos + 1 ;
1306 _XwSetCursorPos(ctx, next);
1307 EndAction(ctx);
1311 /*--------------------------------------------------------------------------+*/
1312 static void MoveNextLine(ctx, event)
1313 /*--------------------------------------------------------------------------+*/
1314 XwTextEditWidget ctx;
1315 XEvent *event;
1317 int width, width2, height, line;
1318 XwTextPosition position, maxp, lastpos = GETLASTPOS(ctx);
1319 XwTextSink *sink = ctx->text.sink ;
1321 StartAction(ctx, event);
1322 _XtTextShowPosition(ctx); /* Needed if cursor goes off screen ??? */
1323 line = LineForPosition(ctx, ctx->text.insertPos);
1325 if (ctx->text.lt.info[line+1].position != (lastpos + 1)) {
1326 if ((line == ctx->text.lt.lines - 1) && (line > 0)) {
1327 _XtTextScroll(ctx, 1);
1328 line = LineForPosition(ctx, ctx->text.insertPos);
1330 if (sink->LineLastPosition == ctx->text.insertPos)
1331 width = sink->LineLastWidth;
1332 else
1333 (*(ctx->text.sink->findDistance))
1334 (ctx, ctx->text.lt.info[line].position, ctx->text.lt.info[line].x,
1335 ctx->text.insertPos, &width, &position, &height);
1336 line++;
1337 if (ctx->text.lt.info[line].position > lastpos) {
1338 position = lastpos;
1340 else {
1341 (*(ctx->text.sink->findPosition))(ctx,
1342 ctx->text.lt.info[line].position, ctx->text.lt.info[line].x,
1343 width, FALSE, &position, &width2, &height);
1344 maxp = (*(ctx->text.source->scan))(ctx->text.source,
1345 ctx->text.lt.info[line+1].position,
1346 XwstPositions, XwsdLeft, 1, TRUE);
1347 if (position > maxp)
1348 position = maxp;
1350 if (_XwSetCursorPos(ctx, position) == XweditDone) {
1351 sink->LineLastWidth = width;
1352 sink->LineLastPosition = position;
1355 EndAction(ctx);
1358 /*--------------------------------------------------------------------------+*/
1359 static void MovePreviousLine(ctx, event)
1360 /*--------------------------------------------------------------------------+*/
1361 XwTextEditWidget ctx;
1362 XEvent *event;
1364 int width, width2, height, line;
1365 XwTextPosition position, maxp;
1366 XwTextSink *sink = ctx->text.sink ;
1368 StartAction(ctx, event);
1369 _XtTextShowPosition(ctx);
1370 line = LineForPosition(ctx, ctx->text.insertPos);
1371 if (line == 0) {
1372 _XtTextScroll(ctx, -1);
1373 line = LineForPosition(ctx, ctx->text.insertPos);
1375 if (line > 0) {
1376 if (sink->LineLastPosition == ctx->text.insertPos)
1377 width = sink->LineLastWidth;
1378 else
1379 (*(ctx->text.sink->findDistance))(ctx,
1380 ctx->text.lt.info[line].position,
1381 ctx->text.lt.info[line].x,
1382 ctx->text.insertPos, &width, &position, &height);
1383 line--;
1384 (*(ctx->text.sink->findPosition))(ctx,
1385 ctx->text.lt.info[line].position, ctx->text.lt.info[line].x,
1386 width, FALSE, &position, &width2, &height);
1387 maxp = (*(ctx->text.source->scan))(ctx->text.source,
1388 ctx->text.lt.info[line+1].position,
1389 XwstPositions, XwsdLeft, 1, TRUE);
1390 if (position > maxp)
1391 position = maxp;
1392 if (_XwSetCursorPos(ctx, position) == XweditDone) {
1393 sink->LineLastWidth = width;
1394 sink->LineLastPosition = position;
1397 EndAction(ctx);
1400 /*--------------------------------------------------------------------------+*/
1401 static void MoveBeginningOfFile(ctx, event)
1402 /*--------------------------------------------------------------------------+*/
1403 XwTextEditWidget ctx;
1404 XEvent *event;
1406 StartAction(ctx, event);
1407 _XwSetCursorPos(ctx, (*(ctx->text.source->scan))
1408 (ctx->text.source, ctx->text.insertPos, XwstLast, XwsdLeft, 1, TRUE)
1410 EndAction(ctx);
1413 /*--------------------------------------------------------------------------+*/
1414 static void MoveEndOfFile(ctx, event)
1415 /*--------------------------------------------------------------------------+*/
1416 XwTextEditWidget ctx;
1417 XEvent *event;
1419 StartAction(ctx, event);
1420 _XwSetCursorPos(ctx, (*(ctx->text.source->scan))
1421 (ctx->text.source, ctx->text.insertPos, XwstLast, XwsdRight, 1, TRUE)
1423 EndAction(ctx);
1426 /*--------------------------------------------------------------------------+*/
1427 static void ScrollOneLineUp(ctx, event)
1428 /*--------------------------------------------------------------------------+*/
1429 XwTextEditWidget ctx;
1430 XEvent *event;
1432 StartAction(ctx, event);
1433 _XtTextScroll(ctx, 1);
1434 EndAction(ctx);
1437 /*--------------------------------------------------------------------------+*/
1438 static void ScrollOneLineDown(ctx, event)
1439 /*--------------------------------------------------------------------------+*/
1440 XwTextEditWidget ctx;
1441 XEvent *event;
1443 StartAction(ctx, event);
1444 _XtTextScroll(ctx, -1);
1445 EndAction(ctx);
1448 /*--------------------------------------------------------------------------+*/
1449 static void MoveNextPage(ctx, event)
1450 /*--------------------------------------------------------------------------+*/
1451 XwTextEditWidget ctx;
1452 XEvent *event;
1454 XwLineTablePtr lt = &(ctx->text.lt) ;
1455 int cur_line;
1456 XwTextPosition line_offset, new_pos, lastpos = GETLASTPOS(ctx);
1458 StartAction(ctx, event);
1459 if (lt->info[(lt->lines)].position != (lastpos + 1)) {
1460 cur_line = LineForPosition(ctx, ctx->text.insertPos);
1461 line_offset = (ctx->text.insertPos - lt->info[cur_line].position);
1462 _XtTextScroll(ctx, max(1, lt->lines - 2));
1463 if (lt->info[cur_line].position > lastpos)
1464 cur_line = LineForPosition(ctx, lastpos);
1465 new_pos = (lt->info[cur_line].position + line_offset);
1466 new_pos = min(new_pos, lt->info[cur_line].drawPos);
1467 _XwSetCursorPos(ctx, new_pos);
1469 EndAction(ctx);
1472 /*--------------------------------------------------------------------------+*/
1473 static void MovePreviousPage(ctx, event)
1474 /*--------------------------------------------------------------------------+*/
1475 XwTextEditWidget ctx;
1476 XEvent *event;
1477 { XwLineTablePtr lt = &(ctx->text.lt) ;
1478 int cur_line = LineForPosition(ctx, ctx->text.insertPos);
1479 XwTextPosition line_offset =
1480 (ctx->text.insertPos - lt->info[cur_line].position);
1481 XwTextPosition new_pos;
1482 StartAction(ctx, event);
1483 _XtTextScroll(ctx, -max(1, lt->lines - 2));
1484 new_pos = (lt->info[cur_line].position + line_offset);
1485 _XwSetCursorPos(ctx, min(new_pos, lt->info[cur_line].drawPos));
1486 EndAction(ctx);
1489 /* delete routines */
1491 /*--------------------------------------------------------------------------+*/
1492 static void DeleteForwardChar(ctx, event)
1493 /*--------------------------------------------------------------------------+*/
1494 XwTextEditWidget ctx;
1495 XEvent *event;
1497 XwTextPosition next;
1499 StartAction(ctx, event);
1500 next = (*(ctx->text.source->scan))(
1501 ctx->text.source, ctx->text.insertPos, XwstPositions,
1502 XwsdRight, 1, TRUE);
1503 DeleteOrKill(ctx, ctx->text.insertPos, next, FALSE);
1504 EndAction(ctx);
1507 /*--------------------------------------------------------------------------+*/
1508 static void DeleteBackwardNormal(ctx, event)
1509 /*--------------------------------------------------------------------------+*/
1510 XwTextEditWidget ctx;
1511 XEvent *event;
1513 /* If there's a selection, delete it, otherwise, delete the character */
1515 if (ctx->text.s.left != ctx->text.s.right)
1516 DeleteCurrentSelection(ctx, event);
1517 else
1518 DeleteBackwardChar(ctx, event);
1521 /*--------------------------------------------------------------------------+*/
1522 static void DeleteBackwardChar(ctx, event)
1523 /*--------------------------------------------------------------------------+*/
1524 XwTextEditWidget ctx;
1525 XEvent *event;
1527 XwTextPosition next;
1529 StartAction(ctx, event);
1530 next = (*(ctx->text.source->scan))(
1531 ctx->text.source, ctx->text.insertPos, XwstPositions,
1532 XwsdLeft, 1, TRUE);
1533 DeleteOrKill(ctx, next, ctx->text.insertPos, FALSE);
1534 EndAction(ctx);
1537 /*--------------------------------------------------------------------------+*/
1538 static void DeleteForwardWord(ctx, event)
1539 /*--------------------------------------------------------------------------+*/
1540 XwTextEditWidget ctx;
1541 XEvent *event;
1543 XwTextPosition next;
1545 StartAction(ctx, event);
1546 next = NextPosition(ctx, ctx->text.insertPos, XwstWhiteSpace, XwsdRight);
1547 DeleteOrKill(ctx, ctx->text.insertPos, next, FALSE);
1548 EndAction(ctx);
1551 /*--------------------------------------------------------------------------+*/
1552 static void DeleteBackwardWord(ctx, event)
1553 /*--------------------------------------------------------------------------+*/
1554 XwTextEditWidget ctx;
1555 XEvent *event;
1557 XwTextPosition next;
1559 StartAction(ctx, event);
1560 next = NextPosition(ctx, ctx->text.insertPos, XwstWhiteSpace, XwsdLeft);
1561 DeleteOrKill(ctx, next, ctx->text.insertPos, FALSE);
1562 EndAction(ctx);
1565 /*--------------------------------------------------------------------------+*/
1566 static void KillForwardWord(ctx, event)
1567 /*--------------------------------------------------------------------------+*/
1568 XwTextEditWidget ctx;
1569 XEvent *event;
1571 XwTextPosition next;
1573 StartAction(ctx, event);
1574 next = NextPosition(ctx, ctx->text.insertPos, XwstWhiteSpace, XwsdRight);
1575 DeleteOrKill(ctx, ctx->text.insertPos, next, TRUE);
1576 EndAction(ctx);
1579 /*--------------------------------------------------------------------------+*/
1580 static void KillBackwardWord(ctx, event)
1581 /*--------------------------------------------------------------------------+*/
1582 XwTextEditWidget ctx;
1583 XEvent *event;
1585 XwTextPosition next;
1587 StartAction(ctx, event);
1588 next = NextPosition(ctx, ctx->text.insertPos, XwstWhiteSpace, XwsdLeft);
1589 DeleteOrKill(ctx, next, ctx->text.insertPos, TRUE);
1590 EndAction(ctx);
1593 /*--------------------------------------------------------------------------+*/
1594 static void KillCurrentSelection(ctx, event)
1595 /*--------------------------------------------------------------------------+*/
1596 XwTextEditWidget ctx;
1597 XEvent *event;
1599 StartAction(ctx, event);
1600 DeleteOrKill(ctx, ctx->text.s.left, ctx->text.s.right, TRUE);
1601 EndAction(ctx);
1604 /*--------------------------------------------------------------------------+*/
1605 static void DeleteCurrentSelection(ctx, event)
1606 /*--------------------------------------------------------------------------+*/
1607 XwTextEditWidget ctx;
1608 XEvent *event;
1610 StartAction(ctx, event);
1611 DeleteOrKill(ctx, ctx->text.s.left, ctx->text.s.right, FALSE);
1612 EndAction(ctx);
1615 /*--------------------------------------------------------------------------+*/
1616 static void KillToEndOfLine(ctx, event)
1617 /*--------------------------------------------------------------------------+*/
1618 XwTextEditWidget ctx;
1619 XEvent *event;
1621 int line;
1622 XwTextPosition last, next, lastpos = GETLASTPOS(ctx);
1623 StartAction(ctx, event);
1624 _XtTextShowPosition(ctx);
1625 line = LineForPosition(ctx, ctx->text.insertPos);
1626 last = ctx->text.lt.info[line + 1].position;
1627 next = (*(ctx->text.source->scan))(ctx->text.source, ctx->text.insertPos,
1628 XwstEOL, XwsdRight, 1, FALSE);
1629 if (last > lastpos)
1630 last = lastpos;
1631 if (last > next && ctx->text.insertPos < next)
1632 last = next;
1633 DeleteOrKill(ctx, ctx->text.insertPos, last, TRUE);
1634 EndAction(ctx);
1637 /*--------------------------------------------------------------------------+*/
1638 static void KillToEndOfParagraph(ctx, event)
1639 /*--------------------------------------------------------------------------+*/
1640 XwTextEditWidget ctx;
1641 XEvent *event;
1643 XwTextPosition next;
1645 StartAction(ctx, event);
1646 next = (*(ctx->text.source->scan))(ctx->text.source, ctx->text.insertPos,
1647 XwstEOL, XwsdRight, 1, FALSE);
1648 if (next == ctx->text.insertPos)
1649 next = (*(ctx->text.source->scan))(ctx->text.source, next, XwstEOL,
1650 XwsdRight, 1, TRUE);
1651 DeleteOrKill(ctx, ctx->text.insertPos, next, TRUE);
1652 EndAction(ctx);
1655 /*--------------------------------------------------------------------------+*/
1656 static void InsertNewLineAndBackup(ctx, event)
1657 /*--------------------------------------------------------------------------+*/
1658 XwTextEditWidget ctx;
1659 XEvent *event;
1661 StartAction(ctx, event);
1662 InsertNewLineAndBackupInternal(ctx);
1663 EndAction(ctx);
1666 /*--------------------------------------------------------------------------+*/
1667 static XwEditResult InsertNewLine(ctx, event)
1668 /*--------------------------------------------------------------------------+*/
1669 XwTextEditWidget ctx;
1670 XEvent *event;
1672 XwTextPosition next;
1673 XwEditResult result;
1675 StartAction(ctx, event);
1676 if (InsertNewLineAndBackupInternal(ctx)) {
1677 EndAction(ctx);
1678 return(XweditError);
1680 next = (*(ctx->text.source->scan))(ctx->text.source, ctx->text.insertPos,
1681 XwstPositions, XwsdRight, 1, TRUE);
1682 result = _XwSetCursorPos(ctx, next);
1683 EndAction(ctx);
1684 return(result);
1687 /*--------------------------------------------------------------------------+*/
1688 static void InsertNewLineAndIndent(ctx, event)
1689 /*--------------------------------------------------------------------------+*/
1690 XwTextEditWidget ctx;
1691 XEvent *event;
1693 XwTextBlock text;
1694 XwTextPosition pos1, pos2;
1695 XwEditResult result;
1697 StartAction(ctx, event);
1698 pos1 = (*(ctx->text.source->scan))(ctx->text.source, ctx->text.insertPos,
1699 XwstEOL, XwsdLeft, 1, FALSE);
1700 pos2 = (*(ctx->text.source->scan))(ctx->text.source, pos1, XwstEOL,
1701 XwsdLeft, 1, TRUE);
1702 pos2 = (*(ctx->text.source->scan))(ctx->text.source, pos2, XwstWhiteSpace,
1703 XwsdRight, 1, TRUE);
1704 text.ptr = _XwTextCopySubString(ctx, pos1, pos2);
1705 text.length = XwStrlen(text.ptr);
1706 if (InsertNewLine(ctx, event)) return;
1707 if (result =
1708 ReplaceText(ctx, ctx->text.insertPos, ctx->text.insertPos,
1709 &text, TRUE)) {
1710 if (result != XweditReject)
1711 XBell(XtDisplay(ctx), 50);
1712 XtFree(text.ptr);
1713 EndAction(ctx);
1714 return;
1716 _XwSetCursorPos(ctx, (*(ctx->text.source->scan))
1717 (ctx->text.source, ctx->text.insertPos, XwstPositions,
1718 XwsdRight, text.length, TRUE));
1719 XtFree(text.ptr);
1720 EndAction(ctx);
1723 /*--------------------------------------------------------------------------+*/
1724 static void NewSelection(ctx, l, r)
1725 /*--------------------------------------------------------------------------+*/
1726 XwTextEditWidget ctx;
1727 XwTextPosition l, r;
1729 unsigned char *ptr;
1730 _XtTextSetNewSelection(ctx, l, r);
1731 if (l < r) {
1732 ptr = _XwTextCopySubString(ctx, l, r);
1733 XStoreBuffer(XtDisplay(ctx), ptr, min(XwStrlen(ptr), MAXCUT), 0);
1734 XtFree(ptr);
1738 /*--------------------------------------------------------------------------+*/
1739 static void SelectWord(ctx, event)
1740 /*--------------------------------------------------------------------------+*/
1741 XwTextEditWidget ctx;
1742 XEvent *event;
1744 XwTextPosition l, r;
1745 StartAction(ctx, event);
1746 l = (*(ctx->text.source->scan))(ctx->text.source, ctx->text.insertPos,
1747 XwstWhiteSpace, XwsdLeft, 1, FALSE);
1748 r = (*(ctx->text.source->scan))(ctx->text.source, l, XwstWhiteSpace,
1749 XwsdRight, 1, FALSE);
1750 NewSelection(ctx, l, r);
1751 EndAction(ctx);
1754 /*--------------------------------------------------------------------------+*/
1755 static void SelectAll(ctx, event)
1756 /*--------------------------------------------------------------------------+*/
1757 XwTextEditWidget ctx;
1758 XEvent *event;
1760 StartAction(ctx, event);
1761 NewSelection(ctx, (XwTextPosition) 0, GETLASTPOS(ctx));
1762 EndAction(ctx);
1765 /*--------------------------------------------------------------------------+*/
1766 static void SelectStart(ctx, event)
1767 /*--------------------------------------------------------------------------+*/
1768 XwTextEditWidget ctx;
1769 XEvent *event;
1771 StartAction(ctx, event);
1772 AlterSelection(ctx, XwsmTextSelect, XwactionStart);
1773 EndAction(ctx);
1776 /*--------------------------------------------------------------------------+*/
1777 static void SelectAdjust(ctx, event)
1778 /*--------------------------------------------------------------------------+*/
1779 XwTextEditWidget ctx;
1780 XEvent *event;
1782 StartAction(ctx, event);
1783 AlterSelection(ctx, XwsmTextSelect, XwactionAdjust);
1784 EndAction(ctx);
1787 /*--------------------------------------------------------------------------+*/
1788 static void SelectEnd(ctx, event)
1789 /*--------------------------------------------------------------------------+*/
1790 XwTextEditWidget ctx;
1791 XEvent *event;
1793 StartAction(ctx, event);
1794 AlterSelection(ctx, XwsmTextSelect, XwactionEnd);
1795 EndAction(ctx);
1798 /*--------------------------------------------------------------------------+*/
1799 static void ExtendStart(ctx, event)
1800 /*--------------------------------------------------------------------------+*/
1801 XwTextEditWidget ctx;
1802 XEvent *event;
1804 StartAction(ctx, event);
1805 AlterSelection(ctx, XwsmTextExtend, XwactionStart);
1806 EndAction(ctx);
1809 /*--------------------------------------------------------------------------+*/
1810 static void ExtendAdjust(ctx, event)
1811 /*--------------------------------------------------------------------------+*/
1812 XwTextEditWidget ctx;
1813 XEvent *event;
1815 StartAction(ctx, event);
1816 AlterSelection(ctx, XwsmTextExtend, XwactionAdjust);
1817 EndAction(ctx);
1820 /*--------------------------------------------------------------------------+*/
1821 static void ExtendEnd(ctx, event)
1822 /*--------------------------------------------------------------------------+*/
1823 XwTextEditWidget ctx;
1824 XEvent *event;
1826 StartAction(ctx, event);
1827 AlterSelection(ctx, XwsmTextExtend, XwactionEnd);
1828 EndAction(ctx);
1831 /*--------------------------------------------------------------------------+*/
1832 static void RedrawDisplay(ctx, event)
1833 /*--------------------------------------------------------------------------+*/
1834 XwTextEditWidget ctx;
1835 XEvent *event;
1837 StartAction(ctx, event);
1838 ForceBuildLineTable(ctx);
1839 DisplayAllText(ctx);
1840 ClearWindow(ctx);
1841 EndAction(ctx);
1842 /* This seems like the wrong place for this */
1843 if (ctx->primitive.highlighted)
1844 _XwHighlightBorder(ctx);
1847 #define STRBUFSIZE 100
1848 static XComposeStatus compose_status = {NULL, 0};
1850 /*--------------------------------------------------------------------------+*/
1851 static void InsertChar(ctx, event)
1852 /*--------------------------------------------------------------------------+*/
1853 XwTextEditWidget ctx;
1854 XEvent *event;
1856 unsigned char strbuf[STRBUFSIZE];
1857 KeySym keysym;
1858 XwEditResult result;
1859 XwTextBlock text;
1861 text.length = XLookupString ((XKeyEvent *)event, strbuf, STRBUFSIZE,
1862 &keysym, &compose_status);
1863 if (text.length==0) return;
1864 StartAction(ctx, event);
1865 text.ptr = &strbuf[0];;
1866 text.firstPos = 0;
1867 if (result =
1868 ReplaceText(ctx, ctx->text.insertPos, ctx->text.insertPos,
1869 &text, TRUE)) {
1870 if (result != XweditReject)
1871 XBell(XtDisplay(ctx), 50);
1872 EndAction(ctx);
1873 return;
1875 _XwSetCursorPos(ctx,
1876 (*(ctx->text.source->scan))(ctx->text.source, ctx->text.insertPos,
1877 XwstPositions, XwsdRight, text.length, TRUE));
1878 _XtTextSetNewSelection(ctx, ctx->text.insertPos, ctx->text.insertPos);
1880 EndAction(ctx);
1883 /*--------------------------------------------------------------------------+*/
1884 static void Execute(ctx, event)
1885 /*--------------------------------------------------------------------------+*/
1886 XwTextEditWidget ctx;
1887 XEvent *event;
1890 XtCallCallbacks((Widget)ctx, XtNexecute, NULL);
1894 /*************************************************************************
1896 * Class Record Support Functions
1898 *************************************************************************/
1900 /******************************************************************************
1902 * Class Record Functions
1904 ******************************************************************************/
1906 /*--------------------------------------------------------------------------+*/
1907 static void ClassInitialize()
1908 /*--------------------------------------------------------------------------+*/
1912 } /* ClassInitialize */
1916 /******************************************************************************
1918 * External functions (Methods???) on the class
1920 ******************************************************************************/
1922 /*--------------------------------------------------------------------------+*/
1923 void XwTextClearBuffer(w)
1924 /*--------------------------------------------------------------------------+*/
1925 XwTextEditWidget w;
1927 _XtTextPrepareToUpdate(w);
1928 (*(w->text.source->setLastPos))(w->text.source, (XwTextPosition)0);
1929 w->text.insertPos = 0;
1930 ForceBuildLineTable(w);
1931 DisplayAllText(w);
1932 _XtTextExecuteUpdate(w);
1935 /*--------------------------------------------------------------------------+*/
1936 unsigned char *XwTextCopyBuffer(w)
1937 /*--------------------------------------------------------------------------+*/
1938 XwTextEditWidget w;
1941 return (*((XwTextEditClassRec *)(w->core.widget_class))->textedit_class.copy_substring)
1942 ((XwTextEditWidget)w, 0, GETLASTPOS(w));
1946 /*--------------------------------------------------------------------------+*/
1947 unsigned char *XwTextCopySelection(w)
1948 /*--------------------------------------------------------------------------+*/
1949 XwTextEditWidget w;
1951 return (*((XwTextEditClassRec *)(w->core.widget_class))->textedit_class.copy_selection)
1952 ((XwTextEditWidget)w);
1955 /*--------------------------------------------------------------------------+*/
1956 int XwTextReadSubString( w, startpos, endpos, target, targetsize, targetused )
1957 /*--------------------------------------------------------------------------+*/
1958 XwTextEditWidget w;
1959 XwTextPosition startpos, endpos;
1960 unsigned char *target;
1961 int targetsize,
1962 *targetused;
1964 return( _XwTextSubString(w, startpos, endpos, target, targetsize, targetused) );
1968 /*--------------------------------------------------------------------------+*/
1969 void XwTextUnsetSelection(w)
1970 /*--------------------------------------------------------------------------+*/
1971 XwTextEditWidget w;
1973 (*((XwTextEditClassRec *)(w->core.widget_class))->textedit_class.unset_selection)
1974 ((Widget)w);
1977 /*--------------------------------------------------------------------------+*/
1978 void XwTextSetSelection(w, left, right)
1979 /*--------------------------------------------------------------------------+*/
1980 XwTextEditWidget w;
1981 XwTextPosition left, right;
1983 (*((XwTextEditClassRec *)(w->core.widget_class))->textedit_class.set_selection)
1984 ((Widget)w, left, right);
1987 /*--------------------------------------------------------------------------+*/
1988 XwEditResult XwTextReplace(w, startPos, endPos, string)
1989 /*--------------------------------------------------------------------------+*/
1990 XwTextEditWidget w;
1991 XwTextPosition startPos, endPos;
1992 unsigned char *string;
1994 XwTextBlock blk;
1996 blk.ptr = string;
1997 blk.length = XwStrlen(string);
1998 blk.firstPos = (XwTextPosition)0;
2000 return (*((XwTextEditClassRec *)(w->core.widget_class))->textedit_class.replace_text)
2001 (w, startPos, endPos, &blk, FALSE);
2004 /*--------------------------------------------------------------------------+*/
2005 void XwTextRedraw(w)
2006 /*--------------------------------------------------------------------------+*/
2007 XwTextEditWidget w;
2009 (*((XwTextEditClassRec *)(w->core.widget_class))->textedit_class.redraw_text)
2010 ((Widget)w);
2013 /*--------------------------------------------------------------------------+*/
2014 void XwTextResize(w)
2015 /*--------------------------------------------------------------------------+*/
2016 XwTextEditWidget w;
2018 _XtTextPrepareToUpdate(w);
2019 CheckResizeOrOverflow(w);
2020 _XtTextExecuteUpdate(w);
2023 /*--------------------------------------------------------------------------+*/
2024 void XwTextUpdate( w, status )
2025 /*--------------------------------------------------------------------------+*/
2026 XwTextEditWidget w;
2027 Boolean status;
2029 w->text.update_flag = status;
2030 if (status) {
2031 _XtTextExecuteUpdate(w);
2033 else {
2034 w->text.numranges = 0;
2035 w->text.showposition = FALSE;
2036 w->text.oldinsert = w->text.insertPos;
2037 if ( XtIsRealized((Widget)w) ) InsertCursor(w, XwisOff);
2042 /*--------------------------------------------------------------------------+*/
2043 void XwTextInsert(w, string)
2044 /*--------------------------------------------------------------------------+*/
2045 XwTextEditWidget w;
2046 unsigned char *string;
2048 XwTextBlock blk;
2050 blk.ptr = string;
2051 blk.length = XwStrlen(string);
2052 blk.firstPos = (XwTextPosition) 0;
2054 _XtTextPrepareToUpdate(w);
2055 if (ReplaceText(w, w->text.insertPos,
2056 w->text.insertPos, &blk, FALSE) == XweditDone) {
2057 w->text.showposition = TRUE;
2058 w->text.insertPos = w->text.insertPos + blk.length;
2060 _XtTextExecuteUpdate(w);
2064 /*--------------------------------------------------------------------------+*/
2065 XwTextPosition XwTextGetLastPos (w)
2066 /*--------------------------------------------------------------------------+*/
2067 XwTextEditWidget w;
2069 return( GETLASTPOS(w) );
2072 /*--------------------------------------------------------------------------+*/
2073 void XwTextGetSelectionPos(w, left, right)
2074 /*--------------------------------------------------------------------------+*/
2075 XwTextEditWidget w;
2076 XwTextPosition *left, *right;
2079 *left = w->text.s.left;
2080 *right = w->text.s.right;
2083 /*--------------------------------------------------------------------------+*/
2084 void XwTextSetInsertPos(w, position)
2085 /*--------------------------------------------------------------------------+*/
2086 XwTextEditWidget w;
2087 XwTextPosition position;
2090 _XtTextPrepareToUpdate(w);
2091 w->text.insertPos = position;
2092 w->text.showposition = TRUE;
2093 _XtTextExecuteUpdate(w);
2096 /*--------------------------------------------------------------------------+*/
2097 XwTextPosition XwTextGetInsertPos(w)
2098 /*--------------------------------------------------------------------------+*/
2099 XwTextEditWidget w;
2102 return( w->text.insertPos );
2106 /*--------------------------------------------------------------------------+*/
2107 void XwTextSetSource(w, source, startpos)
2108 /*--------------------------------------------------------------------------+*/
2109 XwTextEditWidget w;
2110 XwTextSourcePtr source;
2111 XwTextPosition startpos;
2114 w->text.source = source;
2115 w->text.lt.top = startpos;
2116 w->text.s.left = w->text.s.right = 0;
2117 w->text.insertPos = startpos;
2119 ForceBuildLineTable(w);
2120 if (XtIsRealized((Widget)w)) {
2121 _XtTextPrepareToUpdate(w);
2122 DisplayAllText(w);
2123 _XtTextExecuteUpdate(w);
2126 /* Not advertised. Don't think it is necessary */
2127 /*--------------------------------------------------------------------------+*/
2128 unsigned char *XwTextCopySubString(w, left, right)
2129 /*--------------------------------------------------------------------------+*/
2130 XwTextEditWidget w;
2131 XwTextPosition left, right;
2133 return (*((XwTextEditClassRec *)(w->core.widget_class))->textedit_class.copy_substring)
2134 ((XwTextEditWidget)w, left, right);
2137 /*--------------------------------------------------------------------------+*/
2138 void XwTextInvalidate(w, from, to)
2139 /*--------------------------------------------------------------------------+*/
2140 XwTextEditWidget w;
2141 XwTextPosition from,to;
2143 _XtTextPrepareToUpdate(w);
2144 _XtTextNeedsUpdating(w, from, to);
2145 ForceBuildLineTable(w);
2146 _XtTextExecuteUpdate(w);
2149 /*--------------------------------------------------------------------------+*/
2150 XwTextPosition XwTextTopPosition(w)
2151 /*--------------------------------------------------------------------------+*/
2152 XwTextEditWidget w;
2154 return w->text.lt.top;
2157 /*****************************************************************************
2158 * Class Functions
2159 *****************************************************************************/
2161 /*--------------------------------------------------------------------------+*/
2162 static void Initialize(request, new)
2163 /*--------------------------------------------------------------------------+*/
2164 Widget request, new;
2166 XwTextEditWidget ctx = (XwTextEditWidget)new;
2167 XwTextEditPart *text = &(ctx->text);
2169 text->lt.lines = 0;
2170 text->lt.info = NULL;
2171 text->s.left = text->s.right = 0;
2172 text->s.type = XwselectPosition;
2173 text->sarray[0] = XwselectPosition;
2174 text->sarray[1] = XwselectWord;
2175 text->sarray[2] = XwselectLine;
2176 text->sarray[3] = XwselectParagraph;
2177 text->sarray[4] = XwselectAll;
2178 text->sarray[5] = XwselectNull;
2179 text->lasttime = 0; /* ||| correct? */
2180 text->time = 0; /* ||| correct? */
2182 text->oldinsert = -1 ;
2183 text->update_flag = FALSE;
2184 text->showposition = TRUE;
2185 text->updateFrom = (XwTextPosition *) XtMalloc(sizeof(XwTextPosition));
2186 text->updateTo = (XwTextPosition *) XtMalloc(sizeof(XwTextPosition));
2187 text->numranges = text->maxranges = 0;
2188 text->gc = DefaultGCOfScreen(XtScreen(ctx));
2189 text->hasfocus = FALSE;
2190 text->scroll_state = text->scroll_mode ;
2191 text->grow_state = text->grow_mode ;
2192 text->prevW = ctx->core.width ;
2193 text->prevH = ctx->core.height ;
2194 if (text->grow_mode & XwGrowHorizontal)
2195 { text->wrap_mode = XwWrapOff ;
2197 if (text->wrap_mode == XwWrapOff)
2198 { text->wrap_form = XwSourceForm ;
2199 text->wrap_break = XwWrapAny ;
2202 #ifdef GLSDEBUG
2203 fprintf (stderr, "%s: %d\n%s: %d\n%s: %d\n%s: %d\n%s: %d\n%s: %x\n"
2204 , " wrap mode", text->wrap_mode
2205 , " wrap form", text->wrap_form
2206 , " wrap break", text->wrap_break
2207 , "scroll mode", text->scroll_mode
2208 , " grow mode", text->grow_mode
2209 , " options", text->options
2211 #endif
2214 /*--------------------------------------------------------------------------+*/
2215 static void InitializeHook(widget, args, num_args)
2216 /*--------------------------------------------------------------------------+*/
2217 Widget widget;
2218 ArgList args;
2219 Cardinal *num_args;
2220 { XwTextEditWidget ctx = (XwTextEditWidget)widget;
2221 register XwTextEditPart *text = &(ctx->text);
2223 text->sink = XwAsciiSinkCreate(widget, args, *num_args);
2225 if (text->srctype == XwstringSrc)
2226 text->source = XwStringSourceCreate(widget, args, *num_args);
2227 else if (text->srctype != XwprogDefinedSrc)
2228 {XtWarning("XwSourceType not recognized. Using XwstringSrc.");
2229 text->source = XwStringSourceCreate(widget, args, *num_args);
2232 ForceBuildLineTable((XwTextEditWidget)widget);
2233 if (text->lt.lines > 1)
2234 { text->scroll_state &= ~XwAutoScrollHorizontal ;
2238 /*--------------------------------------------------------------------------+*/
2239 static void TextDestroy(ctx)
2240 /*--------------------------------------------------------------------------+*/
2241 XwTextEditWidget ctx;
2243 (*(ctx->text.source->destroy))(ctx->text.source);
2244 (*(ctx->text.sink->destroy))(ctx->text.sink);
2245 XtFree((char *)ctx->text.updateFrom);
2246 XtFree((char *)ctx->text.updateTo);
2247 XtRemoveAllCallbacks((Widget)ctx, XtNmotionVerification);
2248 XtRemoveAllCallbacks((Widget)ctx, XtNmodifyVerification);
2249 XtRemoveAllCallbacks((Widget)ctx, XtNleaveVerification);
2253 /*--------------------------------------------------------------------------+*/
2254 static void Resize(w)
2255 /*--------------------------------------------------------------------------+*/
2256 Widget w;
2258 XwTextEditWidget ctx = (XwTextEditWidget) w;
2259 XwTextEditPart *tp ;
2260 Dimension width, height ;
2261 Boolean realized = XtIsRealized(w);
2263 tp = &(ctx->text) ;
2264 width = ctx->core.width ;
2265 if ((width < tp->prevW) && (tp->grow_mode & XwGrowHorizontal))
2266 tp->grow_state |= XwGrowHorizontal ;
2267 height = ctx->core.height ;
2268 if ((height < tp->prevH) && (tp->grow_mode & XwGrowVertical))
2269 tp->grow_state |= XwGrowVertical ;
2271 if (realized) _XtTextPrepareToUpdate(ctx);
2272 ForceBuildLineTable(ctx);
2274 if (tp->lt.lines > 1)
2275 { tp->scroll_state &= ~XwAutoScrollHorizontal ;
2277 else
2278 { tp->scroll_state |= tp->scroll_mode & XwAutoScrollHorizontal ;
2281 if (realized)
2283 DisplayAllText(ctx);
2284 ClearWindow(ctx);
2287 if (realized) _XtTextExecuteUpdate(ctx);
2290 /*--------------------------------------------------------------------------+*/
2291 static Boolean SetValues(current, request, new)
2292 /*--------------------------------------------------------------------------+*/
2293 Widget current, request, new;
2295 XwTextEditWidget oldtw = (XwTextEditWidget) current;
2296 XwTextEditWidget newtw = (XwTextEditWidget) new;
2297 Boolean redisplay = FALSE;
2298 XwTextEditPart *oldtext = &(oldtw->text);
2299 XwTextEditPart *newtext = &(newtw->text);
2300 Boolean realized = XtIsRealized(current);
2302 if (realized) _XtTextPrepareToUpdate(oldtw);
2304 if (oldtext->source != newtext->source) {
2305 ForceBuildLineTable(oldtw);
2306 if ((oldtext->s.left == newtext->s.left) &&
2307 (oldtext->s.right == newtext->s.right)) {
2308 newtext->s.left = (XwTextPosition) 0;
2309 newtext->s.right = (XwTextPosition) 0;
2311 redisplay = TRUE;
2314 if (oldtext->sink != newtext->sink)
2315 redisplay = TRUE;
2317 if (oldtext->insertPos != newtext->insertPos)
2318 oldtext->showposition = TRUE;
2320 if (oldtext->lt.top != newtext->lt.top)
2321 redisplay = TRUE;
2323 if ((oldtext->leftmargin != newtext->leftmargin) ||
2324 (oldtext->topmargin != newtext->topmargin) ||
2325 (oldtext->rightmargin != newtext->rightmargin) ||
2326 (oldtext->bottommargin != newtext->bottommargin))
2327 redisplay = TRUE;
2329 if ((oldtext->s.left != newtext->s.left) ||
2330 (oldtext->s.right != newtext->s.right)) {
2331 if (newtext->s.left > newtext->s.right) {
2332 XwTextPosition temp = newtext->s.right;
2333 newtext->s.right = newtext->s.left;
2334 newtext->s.left = temp;
2335 redisplay = TRUE;
2340 /* ||| This may be the best way to do this, as some optimizations
2341 * can occur here that may be harder if we let XtSetValues
2342 * call our expose proc.
2345 if (redisplay && realized)
2346 DisplayAllText(newtw);
2348 if (realized) _XtTextExecuteUpdate(newtw);
2350 return ( FALSE );
2353 /*--------------------------------------------------------------------------+*/
2354 static Boolean SetValuesHook(widget, args, num_args)
2355 /*--------------------------------------------------------------------------+*/
2356 Widget widget;
2357 ArgList args;
2358 Cardinal *num_args;
2360 XwTextEditWidget ctx = (XwTextEditWidget)widget;
2361 XwTextSource *source = ctx->text.source;
2362 XwTextSink *sink = ctx->text.sink;
2363 Boolean realized = XtIsRealized(widget);
2365 if (realized) _XtTextPrepareToUpdate(ctx);
2367 /* This is ugly, but need to know if user set initial_string */
2368 ((StringSourcePtr)(source->data))->initial_string = NULL;
2370 XtSetSubvalues(source->data, source->resources,
2371 source->resource_num, args, *num_args);
2372 XtSetSubvalues(sink->data, sink->resources,
2373 sink->resource_num, args, *num_args);
2375 (*(source->check_data))(source);
2377 ForceBuildLineTable(ctx);
2378 if (realized) {
2379 DisplayAllText(ctx);
2380 _XtTextExecuteUpdate(ctx);
2383 return( FALSE );
2386 /*--------------------------------------------------------------------------+*/
2387 static void GetValuesHook(widget, args, num_args)
2388 /*--------------------------------------------------------------------------+*/
2389 Widget widget;
2390 ArgList args;
2391 Cardinal *num_args;
2393 XwTextSource *source = ((XwTextEditWidget)widget)->text.source;
2394 XwTextSink *sink = ((XwTextEditWidget)widget)->text.sink;
2395 int i = 0;
2397 /* This is ugly, but have to get internal buffer to initial_string storage */
2398 while (i < *num_args) {
2399 if (strcmp(args[i].name, XtNstring) == 0) {
2400 ((StringSourcePtr)(source->data))->initial_string =
2401 XwTextCopyBuffer((XwTextEditWidget)widget);
2402 break;
2404 i++;
2407 XtGetSubvalues(source->data, source->resources, source->resource_num,
2408 args, *num_args);
2409 XtGetSubvalues(sink->data, sink->resources, sink->resource_num,
2410 args, *num_args);
2413 /*--------------------------------------------------------------------------+*/
2414 static void Realize( w, valueMask, attributes )
2415 /*--------------------------------------------------------------------------+*/
2416 Widget w;
2417 Mask *valueMask;
2418 XSetWindowAttributes *attributes;
2420 XwTextEditWidget ctx = (XwTextEditWidget)w;
2422 *valueMask |= CWBitGravity;
2423 attributes->bit_gravity = NorthWestGravity;
2425 XtCreateWindow( w, InputOutput, (Visual *)CopyFromParent,
2426 *valueMask, attributes);
2427 if (XtIsRealized(w)) {
2428 XDefineCursor( w->core.screen->display, w->core.window,
2429 XCreateFontCursor( w->core.screen->display, XC_left_ptr));
2430 ctx->text.update_flag = TRUE;
2432 else {
2433 XtWarning("Unable to realize TextEdit");
2435 _XwRegisterName(w);
2439 /*****************************************************************************
2441 * Text Edit Class Record
2443 *****************************************************************************/
2444 XwTextEditClassRec XwtexteditClassRec = {
2446 /* core fields */
2447 /* superclass */ (WidgetClass) &XwprimitiveClassRec,
2448 /* class_name */ "XwTextEdit",
2449 /* widget_size */ sizeof(XwTextEditRec),
2450 /* class_initialize */ ClassInitialize,
2451 /* class_part_init */ NULL,
2452 /* class_inited */ FALSE,
2453 /* initialize */ (XtInitProc)Initialize,
2454 /* initialize_hook */ InitializeHook,
2455 /* realize */ Realize,
2456 /* actions */ texteditActionsTable,
2457 /* num_actions */ XtNumber(texteditActionsTable),
2458 /* resources */ resources,
2459 /* num_ resource */ XtNumber(resources),
2460 /* xrm_class */ NULLQUARK,
2461 /* compress_motion */ TRUE,
2462 /* compress_exposure*/ FALSE,
2463 /* compress_enterleave*/ TRUE,
2464 /* visible_interest */ FALSE,
2465 /* destroy */ (XtWidgetProc)TextDestroy,
2466 /* resize */ Resize,
2467 /* expose */ (XtExposeProc)ProcessExposeRegion,
2468 /* set_values */ (XtSetValuesFunc)SetValues,
2469 /* set_values_hook */ SetValuesHook,
2470 /* set_values_almost*/ XtInheritSetValuesAlmost,
2471 /* get_values_hook */ GetValuesHook,
2472 /* accept_focus */ NULL,
2473 /* version */ XtVersion,
2474 /* callback_private */ NULL,
2475 /* tm_table */ defaultTextEditTranslations,
2476 /* query_geometry */ NULL,
2477 /* display_accelerator */ XtInheritDisplayAccelerator,
2478 /* extension */ NULL
2481 /* XwPrimitive fields */
2483 (XtWidgetProc) NULL,
2484 (XtWidgetProc) NULL,
2485 (XwEventProc) NULL,
2486 (XwEventProc) NULL,
2487 (XwEventProc) NULL,
2488 (XtTranslations) NULL
2491 /* XwTextEdit fields */
2492 /* copy_substring */ _XwTextCopySubString,
2493 /* copy_selection */ _XwTextCopySelection,
2494 /* unset_selection */ _XwTextUnsetSelection,
2495 /* set_selection */ (XwSetSProc)_XwTextSetSelection,
2496 /* replace_text */ _XwTextReplace,
2497 /* redraw_text */ _XwTextRedraw,
2501 WidgetClass XwtexteditWidgetClass = (WidgetClass)&XwtexteditClassRec;
2502 WidgetClass XwtextEditWidgetClass = (WidgetClass)&XwtexteditClassRec;