Bug Summary

File:TextAction.c
Location:line 1199, column 15
Description:Access to field 'next' results in a dereference of a null pointer (loaded from variable 'tail')

Annotated Source Code

1/*
2
3Copyright 1989, 1994, 1998 The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25*/
26
27#ifdef HAVE_CONFIG_H1
28#include <config.h>
29#endif
30#include <stdio.h>
31#include <stdlib.h>
32#include <unistd.h>
33#include <X11/Xos.h> /* for select() and struct timeval */
34#include <ctype.h>
35#include <X11/IntrinsicP.h>
36#include <X11/StringDefs.h>
37#include <X11/Xatom.h>
38#include <X11/Xfuncs.h>
39#include <X11/Xutil.h>
40#include <X11/Xmu/Atoms.h>
41#include <X11/Xmu/Misc.h>
42#include <X11/Xmu/StdSel.h>
43#include <X11/Xaw/MultiSinkP.h>
44#include <X11/Xaw/MultiSrcP.h>
45#include <X11/Xaw/TextP.h>
46#include <X11/Xaw/TextSrcP.h>
47#include <X11/Xaw/XawImP.h>
48#include "Private.h"
49#include "XawI18n.h"
50
51#ifdef _WIN32
52#include <X11/Xwinsock.h>
53#endif
54
55#define SrcScanXawTextSourceScan XawTextSourceScan
56#define FindDistXawTextSinkFindDistance XawTextSinkFindDistance
57#define FindPosXawTextSinkFindPosition XawTextSinkFindPosition
58#define MULT(w)(w->text.mult == 0 ? 4 : w->text.mult == 32767 ? -4 : w
->text.mult)
(w->text.mult == 0 ? 4 : \
59 w->text.mult == 32767 ? -4 : w->text.mult)
60
61#define KILL_RING_APPEND2 2
62#define KILL_RING_BEGIN3 3
63#define KILL_RING_YANK100 100
64#define KILL_RING_YANK_DONE98 98
65
66#define XawTextActionMaxHexChars100 100
67
68/*
69 * Prototypes
70 */
71static void _DeleteOrKill(TextWidget, XawTextPosition, XawTextPosition, Boolint);
72static void _SelectionReceived(Widget, XtPointer, Atom*, Atom*, XtPointer,
73 unsigned long*, int*);
74static void _LoseSelection(Widget, Atom*, char**, int*);
75static void AutoFill(TextWidget);
76static Boolean ConvertSelection(Widget, Atom*, Atom*, Atom*, XtPointer*,
77 unsigned long*, int*);
78static void DeleteOrKill(TextWidget, XEvent*, XawTextScanDirection,
79 XawTextScanType, Boolint, Boolint);
80static void EndAction(TextWidget);
81#ifndef OLDXAW
82static Boolint BlankLine(Widget, XawTextPosition, int*);
83static int DoFormatText(TextWidget, XawTextPosition, Boolint, int,
84 XawTextBlock*, XawTextPosition*, int, Boolint);
85static int FormatText(TextWidget, XawTextPosition, Boolint,
86 XawTextPosition*, int);
87static Boolint GetBlockBoundaries(TextWidget, XawTextPosition*, XawTextPosition*);
88#endif
89static int FormRegion(TextWidget, XawTextPosition, XawTextPosition,
90 XawTextPosition*, int);
91static void GetSelection(Widget, Time, String*, Cardinal);
92static char *IfHexConvertHexElseReturnParam(char*, int*);
93static void InsertNewCRs(TextWidget, XawTextPosition, XawTextPosition,
94 XawTextPosition*, int);
95static int InsertNewLineAndBackupInternal(TextWidget);
96static int LocalInsertNewLine(TextWidget, XEvent*);
97static void LoseSelection(Widget, Atom*);
98static void ParameterError(Widget, String);
99static Boolint MatchSelection(Atom, XawTextSelection*);
100static void ModifySelection(TextWidget, XEvent*, XawTextSelectionMode,
101 XawTextSelectionAction, String*, Cardinal*);
102static void Move(TextWidget, XEvent*, XawTextScanDirection, XawTextScanType,
103 Boolint);
104static void NotePosition(TextWidget, XEvent*);
105static void StartAction(TextWidget, XEvent*);
106static XawTextPosition StripOutOldCRs(TextWidget, XawTextPosition,
107 XawTextPosition, XawTextPosition*, int);
108#ifndef OLDXAW
109static Boolint StripSpaces(TextWidget, XawTextPosition, XawTextPosition,
110 XawTextPosition*, int, XawTextBlock*);
111static Boolint Tabify(TextWidget, XawTextPosition, XawTextPosition,
112 XawTextPosition*, int, XawTextBlock*);
113static Boolint Untabify(TextWidget, XawTextPosition, XawTextPosition,
114 XawTextPosition*, int, XawTextBlock*);
115#endif
116
117/*
118 * Actions
119 */
120static void CapitalizeWord(Widget, XEvent*, String*, Cardinal*);
121static void DisplayCaret(Widget, XEvent*, String*, Cardinal*);
122static void Delete(Widget, XEvent*, String*, Cardinal*);
123static void DeleteBackwardChar(Widget, XEvent*, String*, Cardinal*);
124static void DeleteBackwardWord(Widget, XEvent*, String*, Cardinal*);
125static void DeleteCurrentSelection(Widget, XEvent*, String*, Cardinal*);
126static void DeleteForwardChar(Widget, XEvent*, String*, Cardinal*);
127static void DeleteForwardWord(Widget, XEvent*, String*, Cardinal*);
128static void DowncaseWord(Widget, XEvent*, String*, Cardinal*);
129static void ExtendAdjust(Widget, XEvent*, String*, Cardinal*);
130static void ExtendEnd(Widget, XEvent*, String*, Cardinal*);
131static void ExtendStart(Widget, XEvent*, String*, Cardinal*);
132static void FormParagraph(Widget, XEvent*, String*, Cardinal*);
133#ifndef OLDXAW
134static void Indent(Widget, XEvent*, String*, Cardinal*);
135#endif
136static void InsertChar(Widget, XEvent*, String*, Cardinal*);
137static void InsertNewLine(Widget, XEvent*, String*, Cardinal*);
138static void InsertNewLineAndBackup(Widget, XEvent*, String*, Cardinal*);
139static void InsertNewLineAndIndent(Widget, XEvent*, String*, Cardinal*);
140static void InsertSelection(Widget, XEvent*, String*, Cardinal*);
141static void InsertString(Widget, XEvent*, String*, Cardinal*);
142#ifndef OLDXAW
143static void KeyboardReset(Widget, XEvent*, String*, Cardinal*);
144#endif
145static void KillBackwardWord(Widget, XEvent*, String*, Cardinal*);
146static void KillCurrentSelection(Widget, XEvent*, String*, Cardinal*);
147static void KillForwardWord(Widget, XEvent*, String*, Cardinal*);
148#ifndef OLDXAW
149static void KillRingYank(Widget, XEvent*, String*, Cardinal*);
150#endif
151static void KillToEndOfLine(Widget, XEvent*, String*, Cardinal*);
152static void KillToEndOfParagraph(Widget, XEvent*, String*, Cardinal*);
153static void MoveBackwardChar(Widget, XEvent*, String*, Cardinal*);
154static void MoveBackwardWord(Widget, XEvent*, String*, Cardinal*);
155static void MoveBackwardParagraph(Widget, XEvent*, String*, Cardinal*);
156static void MoveBeginningOfFile(Widget, XEvent*, String*, Cardinal*);
157static void MoveEndOfFile(Widget, XEvent*, String*, Cardinal*);
158static void MoveForwardChar(Widget, XEvent*, String*, Cardinal*);
159static void MoveForwardWord(Widget, XEvent*, String*, Cardinal*);
160static void MoveForwardParagraph(Widget, XEvent*, String*, Cardinal*);
161static void MoveNextLine(Widget, XEvent*, String*, Cardinal*);
162static void MoveNextPage(Widget, XEvent*, String*, Cardinal*);
163static void MovePage(TextWidget, XEvent*, XawTextScanDirection);
164static void MovePreviousLine(Widget, XEvent*, String*, Cardinal*);
165static void MovePreviousPage(Widget, XEvent*, String*, Cardinal*);
166static void MoveLine(TextWidget, XEvent*, XawTextScanDirection);
167static void MoveToLineEnd(Widget, XEvent*, String*, Cardinal*);
168static void MoveToLineStart(Widget, XEvent*, String*, Cardinal*);
169static void Multiply(Widget, XEvent*, String*, Cardinal*);
170static void NoOp(Widget, XEvent*, String*, Cardinal*);
171#ifndef OLDXAW
172static void Numeric(Widget, XEvent*, String*, Cardinal*);
173#endif
174static void Reconnect(Widget, XEvent*, String*, Cardinal*);
175static void RedrawDisplay(Widget, XEvent*, String*, Cardinal*);
176static void Scroll(TextWidget, XEvent*, XawTextScanDirection);
177static void ScrollOneLineDown(Widget, XEvent*, String*, Cardinal*);
178static void ScrollOneLineUp(Widget, XEvent*, String*, Cardinal*);
179static void SelectAdjust(Widget, XEvent*, String*, Cardinal*);
180static void SelectAll(Widget, XEvent*, String*, Cardinal*);
181static void SelectEnd(Widget, XEvent*, String*, Cardinal*);
182static void SelectSave(Widget, XEvent*, String*, Cardinal*);
183static void SelectStart(Widget, XEvent*, String*, Cardinal*);
184static void SelectWord(Widget, XEvent*, String*, Cardinal*);
185static void SetKeyboardFocus(Widget, XEvent*, String*, Cardinal*);
186static void TextEnterWindow(Widget, XEvent*, String*, Cardinal*);
187static void TextFocusIn(Widget, XEvent*, String*, Cardinal*);
188static void TextFocusOut(Widget, XEvent*, String*, Cardinal*);
189static void TextLeaveWindow(Widget, XEvent*, String*, Cardinal*);
190static void TransposeCharacters(Widget, XEvent*, String*, Cardinal*);
191#ifndef OLDXAW
192static void ToggleOverwrite(Widget, XEvent*, String*, Cardinal*);
193static void Undo(Widget, XEvent*, String*, Cardinal*);
194#endif
195static void UpcaseWord(Widget, XEvent*, String*, Cardinal*);
196static void DestroyFocusCallback(Widget, XtPointer, XtPointer);
197
198/*
199 * External
200 */
201void _XawTextZapSelection(TextWidget, XEvent*, Boolint);
202
203/*
204 * Defined in TextPop.c
205 */
206void _XawTextInsertFileAction(Widget, XEvent*, String*, Cardinal*);
207void _XawTextInsertFile(Widget, XEvent*, String*, Cardinal*);
208void _XawTextSearch(Widget, XEvent*, String*, Cardinal*);
209void _XawTextDoSearchAction(Widget, XEvent*, String*, Cardinal*);
210void _XawTextDoReplaceAction(Widget, XEvent*, String*, Cardinal*);
211void _XawTextSetField(Widget, XEvent*, String*, Cardinal*);
212void _XawTextPopdownSearchAction(Widget, XEvent*, String*, Cardinal*);
213
214/*
215 * These are defined in Text.c
216 */
217void _XawTextAlterSelection(TextWidget, XawTextSelectionMode,
218 XawTextSelectionAction, String*, Cardinal*);
219void _XawTextClearAndCenterDisplay(TextWidget);
220void _XawTextExecuteUpdate(TextWidget);
221char *_XawTextGetText(TextWidget, XawTextPosition, XawTextPosition);
222void _XawTextPrepareToUpdate(TextWidget);
223int _XawTextReplace(TextWidget, XawTextPosition, XawTextPosition,
224 XawTextBlock*);
225Atom *_XawTextSelectionList(TextWidget, String*, Cardinal);
226void _XawTextSetSelection(TextWidget, XawTextPosition, XawTextPosition,
227 String*, Cardinal);
228void _XawTextVScroll(TextWidget, int);
229void XawTextScroll(TextWidget, int, int);
230void _XawTextSetLineAndColumnNumber(TextWidget, Boolint);
231
232#ifndef OLDXAW
233/*
234 * Defined in TextSrc.c
235 */
236Boolint _XawTextSrcUndo(TextSrcObject, XawTextPosition*);
237Boolint _XawTextSrcToggleUndo(TextSrcObject);
238void _XawSourceSetUndoErase(TextSrcObject, int);
239void _XawSourceSetUndoMerge(TextSrcObject, Boolint);
240#endif /* OLDXAW */
241
242/*
243 * Initialization
244 */
245#ifndef OLDXAW
246#define MAX_KILL_RINGS1024 1024
247XawTextKillRing *xaw_text_kill_ring;
248static XawTextKillRing kill_ring_prev, kill_ring_null = { &kill_ring_prev, };
249static unsigned num_kill_rings;
250#endif
251
252/*
253 * Implementation
254 */
255static void
256ParameterError(Widget w, String param)
257{
258 String params[2];
259 Cardinal num_params = 2;
260 params[0] = XtName(w);
261 params[1] = param;
262
263 XtAppWarningMsg(XtWidgetToApplicationContext(w),
264 "parameterError", "textAction", "XawError",
265 "Widget: %s Parameter: %s",
266 params, &num_params);
267 XBell(XtDisplay(w)(((w)->core.screen)->display), 50);
268}
269
270static void
271StartAction(TextWidget ctx, XEvent *event)
272{
273#ifndef OLDXAW
274 Cardinal i;
275 TextSrcObject src = (TextSrcObject)ctx->text.source;
276
277 for (i = 0; i < src->textSrc.num_text; i++)
278 _XawTextPrepareToUpdate((TextWidget)src->textSrc.text[i]);
279 _XawSourceSetUndoMerge(src, False0);
280#else
281 _XawTextPrepareToUpdate(ctx);
282#endif
283
284 if (event != NULL((void*)0)) {
285 switch (event->type) {
286 case ButtonPress4:
287 case ButtonRelease5:
288 ctx->text.time = event->xbutton.time;
289 break;
290 case KeyPress2:
291 case KeyRelease3:
292 ctx->text.time = event->xkey.time;
293 break;
294 case MotionNotify6:
295 ctx->text.time = event->xmotion.time;
296 break;
297 case EnterNotify7:
298 case LeaveNotify8:
299 ctx->text.time = event->xcrossing.time;
300 }
301 }
302}
303
304static void
305NotePosition(TextWidget ctx, XEvent *event)
306{
307 switch (event->type) {
308 case ButtonPress4:
309 case ButtonRelease5:
310 ctx->text.ev_x = event->xbutton.x;
311 ctx->text.ev_y = event->xbutton.y;
312 break;
313 case KeyPress2:
314 case KeyRelease3: {
315 XRectangle cursor;
316 XawTextSinkGetCursorBounds(ctx->text.sink, &cursor);
317 ctx->text.ev_x = cursor.x + cursor.width / 2;
318 ctx->text.ev_y = cursor.y + cursor.height / 2;
319 } break;
320 case MotionNotify6:
321 ctx->text.ev_x = event->xmotion.x;
322 ctx->text.ev_y = event->xmotion.y;
323 break;
324 case EnterNotify7:
325 case LeaveNotify8:
326 ctx->text.ev_x = event->xcrossing.x;
327 ctx->text.ev_y = event->xcrossing.y;
328 }
329}
330
331static void
332EndAction(TextWidget ctx)
333{
334#ifndef OLDXAW
335 Cardinal i;
336 TextSrcObject src = (TextSrcObject)ctx->text.source;
337
338 for (i = 0; i < src->textSrc.num_text; i++)
339 _XawTextExecuteUpdate((TextWidget)src->textSrc.text[i]);
340
341 ctx->text.mult = 1;
342 ctx->text.numeric = False0;
343 if (ctx->text.kill_ring) {
344 if (--ctx->text.kill_ring == KILL_RING_YANK_DONE98) {
345 if (ctx->text.kill_ring_ptr) {
346 --ctx->text.kill_ring_ptr->refcount;
347 ctx->text.kill_ring_ptr = NULL((void*)0);
348 }
349 }
350 }
351#else
352 ctx->text.mult = 1;
353 _XawTextExecuteUpdate(ctx);
354#endif /* OLDXAW */
355}
356
357struct _SelectionList {
358 String* params;
359 Cardinal count;
360 Time time;
361 int asked; /* which selection currently has been asked for:
362 0 = UTF8_STRING, 1 = COMPOUND_TEXT, 2 = STRING */
363 Atom selection; /* selection atom (normally XA_PRIMARY) */
364};
365
366/*ARGSUSED*/
367static void
368_SelectionReceived(Widget w, XtPointer client_data, Atom *selection,
369 Atom *type, XtPointer value, unsigned long *length,
370 int *format)
371{
372 Display *d = XtDisplay(w)(((w)->core.screen)->display);
373 TextWidget ctx = (TextWidget)w;
374 XawTextBlock text;
375
376 if (*type == 0 /*XT_CONVERT_FAIL*/ || *length == 0) {
377 struct _SelectionList* list = (struct _SelectionList*)client_data;
378
379 if (list != NULL((void*)0)) {
380 if (list->asked == 0) {
381 /* If we just asked for XA_UTF8_STRING and got no response,
382 we'll ask again, this time for XA_COMPOUND_TEXT. */
383 list->asked++;
384 XtGetSelectionValue(w, list->selection, XA_COMPOUND_TEXT(d)XmuInternAtom(d, _XA_COMPOUND_TEXT),
385 _SelectionReceived,
386 (XtPointer)list, list->time);
387 } else if (list->asked == 1) {
388 /* If we just asked for XA_COMPOUND_TEXT and got no response,
389 we'll ask again, this time for XA_STRING. */
390 list->asked++;
391 XtGetSelectionValue(w, list->selection, XA_STRING((Atom) 31),
392 _SelectionReceived,
393 (XtPointer)list, list->time);
394 } else {
395 /* We tried all possible text targets in this param.
396 Recurse on the tail of the params list. */
397 GetSelection(w, list->time, list->params, list->count);
398 XtFree(client_data);
399 }
400 }
401 return;
402 }
403
404 StartAction(ctx, NULL((void*)0));
405 if (XawTextFormat(ctx, XawFmtWide)((unsigned long)_XawTextFormat(ctx) == (XawFmtWide))) {
406 XTextProperty textprop;
407 wchar_t **wlist;
408 int count;
409
410 textprop.encoding = *type;
411 textprop.value = (unsigned char *)value;
412 textprop.nitems = strlen(value);
413 textprop.format = 8;
414
415 if (XwcTextPropertyToTextList(d, &textprop, &wlist, &count)
416 != Success0
417 || count < 1) {
418 XwcFreeStringList(wlist);
419
420 /* Notify the user on strerr and in the insertion :) */
421 fprintf(stderr__stderrp, "Xaw Text Widget: An attempt was made to insert "
422 "an illegal selection.\n");
423
424 textprop.value = (unsigned char *)" >> ILLEGAL SELECTION << ";
425 textprop.nitems = strlen((char *) textprop.value);
426 if (XwcTextPropertyToTextList(d, &textprop, &wlist, &count)
427 != Success0
428 || count < 1)
429 return;
430 }
431
432 XFree(value);
433 value = (XPointer)wlist[0];
434
435 *length = wcslen(wlist[0]);
436 XtFree((XtPointer)wlist);
437 text.format = XawFmtWide;
438 }
439 text.ptr = (char*)value;
440 text.firstPos = 0;
441 text.length = *length;
442 if (_XawTextReplace(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) {
443 XBell(XtDisplay(ctx)(((ctx)->core.screen)->display), 0);
444 EndAction(ctx);
445 return;
446 }
447
448 ctx->text.from_left = -1;
449 ctx->text.insertPos = SrcScanXawTextSourceScan(ctx->text.source, ctx->text.old_insert,
450 XawstPositions, XawsdRight, text.length, True1);
451
452 EndAction(ctx);
453 XtFree(client_data);
454 XFree(value); /* the selection value should be freed with XFree */
455}
456
457static void
458GetSelection(Widget w, Time timev, String *params, Cardinal num_params)
459{
460 Display *d = XtDisplay(w)(((w)->core.screen)->display);
461 TextWidget ctx = (TextWidget)w;
462 Atom selection;
463 int buffer;
464
465 selection = XInternAtom(XtDisplay(w)(((w)->core.screen)->display), *params, False0);
466 switch (selection) {
467 case XA_CUT_BUFFER0((Atom) 9): buffer = 0; break;
468 case XA_CUT_BUFFER1((Atom) 10): buffer = 1; break;
469 case XA_CUT_BUFFER2((Atom) 11): buffer = 2; break;
470 case XA_CUT_BUFFER3((Atom) 12): buffer = 3; break;
471 case XA_CUT_BUFFER4((Atom) 13): buffer = 4; break;
472 case XA_CUT_BUFFER5((Atom) 14): buffer = 5; break;
473 case XA_CUT_BUFFER6((Atom) 15): buffer = 6; break;
474 case XA_CUT_BUFFER7((Atom) 16): buffer = 7; break;
475 default: buffer = -1;
476 }
477 if (buffer >= 0) {
478 int nbytes;
479 unsigned long length;
480 int fmt8 = 8;
481 Atom type = XA_STRING((Atom) 31);
482 char *line = XFetchBuffer(XtDisplay(w)(((w)->core.screen)->display), &nbytes, buffer);
483
484 if ((length = nbytes) != 0L)
485 _SelectionReceived(w, NULL((void*)0), &selection, &type, line, &length, &fmt8);
486 else if (num_params > 1)
487 GetSelection(w, timev, params+1, num_params-1);
488 }
489 else {
490 struct _SelectionList* list;
491
492 if (--num_params) {
493 list = XtNew(struct _SelectionList)((struct _SelectionList *) XtMalloc((unsigned) sizeof(struct _SelectionList
)))
;
494 list->params = params + 1;
495 list->count = num_params;
496 list->time = timev;
497 list->asked = 0;
498 list->selection = selection;
499 }
500 else
501 list = NULL((void*)0);
502 XtGetSelectionValue(w, selection, XawTextFormat(ctx, XawFmtWide)((unsigned long)_XawTextFormat(ctx) == (XawFmtWide)) ?
503 XA_UTF8_STRING(d)XmuInternAtom(d, _XA_UTF8_STRING) : XA_TEXT(d)XmuInternAtom(d, _XA_TEXT),
504 _SelectionReceived, (XtPointer)list, timev);
505 }
506}
507
508static void
509InsertSelection(Widget w, XEvent *event, String *params, Cardinal *num_params)
510{
511 StartAction((TextWidget)w, event); /* Get Time. */
512 GetSelection(w, ((TextWidget)w)->text.time, params, *num_params);
513 EndAction((TextWidget)w);
514}
515
516/*
517 * Routines for Moving Around
518 */
519static void
520Move(TextWidget ctx, XEvent *event, XawTextScanDirection dir,
521 XawTextScanType type, Boolint include)
522{
523 XawTextPosition insertPos;
524 short mult = MULT(ctx)(ctx->text.mult == 0 ? 4 : ctx->text.mult == 32767 ? -4
: ctx->text.mult)
;
525
526 if (mult < 0) {
527 mult = -mult;
528 dir = dir == XawsdLeft ? XawsdRight : XawsdLeft;
529 }
530
531 insertPos = SrcScanXawTextSourceScan(ctx->text.source, ctx->text.insertPos,
532 type, dir, mult, include);
533
534 StartAction(ctx, event);
535
536 if (ctx->text.s.left != ctx->text.s.right)
537 XawTextUnsetSelection((Widget)ctx);
538
539#ifndef OLDXAW
540 ctx->text.numeric = False0;
541#endif
542 ctx->text.mult = 1;
543 ctx->text.showposition = True1;
544 ctx->text.from_left = -1;
545 ctx->text.insertPos = insertPos;
546 EndAction(ctx);
547}
548
549/*ARGSUSED*/
550static void
551MoveForwardChar(Widget w, XEvent *event, String *p, Cardinal *n)
552{
553 Move((TextWidget)w, event, XawsdRight, XawstPositions, True1);
554}
555
556/*ARGSUSED*/
557static void
558MoveBackwardChar(Widget w, XEvent *event, String *p, Cardinal *n)
559{
560 Move((TextWidget)w, event, XawsdLeft, XawstPositions, True1);
561}
562
563static void
564MoveForwardWord(Widget w, XEvent *event, String *p, Cardinal *n)
565{
566 if (*n && (p[0][0] == 'A' || p[0][0] == 'a'))
567 Move((TextWidget)w, event, XawsdRight, XawstAlphaNumeric, False0);
568 else
569 Move((TextWidget)w, event, XawsdRight, XawstWhiteSpace, False0);
570}
571
572static void
573MoveBackwardWord(Widget w, XEvent *event, String *p, Cardinal *n)
574{
575 if (*n && (p[0][0] == 'A' || p[0][0] == 'a'))
576 Move((TextWidget)w, event, XawsdLeft, XawstAlphaNumeric, False0);
577 else
578 Move((TextWidget)w, event, XawsdLeft, XawstWhiteSpace, False0);
579}
580
581static void
582MoveForwardParagraph(Widget w, XEvent *event, String *p, Cardinal *n)
583{
584 TextWidget ctx = (TextWidget)w;
585 XawTextPosition position = ctx->text.insertPos;
586 short mult = MULT(ctx)(ctx->text.mult == 0 ? 4 : ctx->text.mult == 32767 ? -4
: ctx->text.mult)
;
587
588 if (mult < 0) {
589 ctx->text.mult = -mult;
590 MoveBackwardParagraph(w, event, p, n);
591 return;
592 }
593
594 while (mult--) {
595 position = SrcScanXawTextSourceScan(ctx->text.source, position,
596 XawstEOL, XawsdRight, 1, False0) - 1;
597
598 while (position == SrcScanXawTextSourceScan(ctx->text.source, position,
599 XawstEOL, XawsdRight, 1, False0))
600 if (++position > ctx->text.lastPos) {
601 mult = 0;
602 break;
603 }
604
605 position = SrcScanXawTextSourceScan(ctx->text.source, position,
606 XawstParagraph, XawsdRight, 1, True1);
607 if (position != ctx->text.lastPos)
608 position = SrcScanXawTextSourceScan(ctx->text.source, position - 1,
609 XawstEOL, XawsdLeft, 1, False0);
610 else
611 break;
612 }
613
614 if (position != ctx->text.insertPos) {
615 XawTextUnsetSelection(w);
616 StartAction(ctx, event);
617 ctx->text.showposition = True1;
618 ctx->text.from_left = -1;
619 ctx->text.insertPos = position;
620 EndAction(ctx);
621 }
622 else
623 ctx->text.mult = 1;
624}
625
626/*ARGSUSED*/
627static void
628MoveBackwardParagraph(Widget w, XEvent *event, String *p, Cardinal *n)
629{
630 TextWidget ctx = (TextWidget)w;
631 XawTextPosition position = ctx->text.insertPos;
632 short mult = MULT(ctx)(ctx->text.mult == 0 ? 4 : ctx->text.mult == 32767 ? -4
: ctx->text.mult)
;
633
634 if (mult < 0) {
635 ctx->text.mult = -mult;
636 MoveForwardParagraph(w, event, p, n);
637 return;
638 }
639
640 while (mult--) {
641 position = SrcScanXawTextSourceScan(ctx->text.source, position,
642 XawstEOL, XawsdLeft, 1, False0) + 1;
643
644 while (position == SrcScanXawTextSourceScan(ctx->text.source, position,
645 XawstEOL, XawsdLeft, 1, False0))
646 if (--position < 0) {
647 mult = 0;
648 break;
649 }
650
651 position = SrcScanXawTextSourceScan(ctx->text.source, position,
652 XawstParagraph, XawsdLeft, 1, True1);
653 if (position > 0 && position < ctx->text.lastPos)
654 ++position;
655 else
656 break;
657 }
658
659 if (position != ctx->text.insertPos) {
660 XawTextUnsetSelection(w);
661 StartAction(ctx, event);
662 ctx->text.showposition = True1;
663 ctx->text.from_left = -1;
664 ctx->text.insertPos = position;
665 EndAction(ctx);
666 }
667 else
668 ctx->text.mult = 1;
669}
670
671/*ARGSUSED*/
672static void
673MoveToLineEnd(Widget w, XEvent *event, String *p, Cardinal *n)
674{
675 Move((TextWidget)w, event, XawsdRight, XawstEOL, False0);
676}
677
678/*ARGSUSED*/
679static void
680MoveToLineStart(Widget w, XEvent *event, String *p, Cardinal *n)
681{
682 Move((TextWidget)w, event, XawsdLeft, XawstEOL, False0);
683}
684
685static void
686MoveLine(TextWidget ctx, XEvent *event, XawTextScanDirection dir)
687{
688 XawTextPosition cnew, next_line, ltemp;
689 int itemp, from_left;
690 short mult = MULT(ctx)(ctx->text.mult == 0 ? 4 : ctx->text.mult == 32767 ? -4
: ctx->text.mult)
;
691
692 StartAction(ctx, event);
693
694 XawTextUnsetSelection((Widget)ctx);
695
696 if (dir == XawsdLeft)
697 mult = mult == 0 ? 5 : mult + 1;
698
699 cnew = SrcScanXawTextSourceScan(ctx->text.source, ctx->text.insertPos,
700 XawstEOL, XawsdLeft, 1, False0);
701
702 if (ctx->text.from_left < 0)
703 FindDistXawTextSinkFindDistance(ctx->text.sink, cnew, ctx->text.left_margin, ctx->text.insertPos,
704 &ctx->text.from_left, &ltemp, &itemp);
705
706 cnew = SrcScanXawTextSourceScan(ctx->text.source, ctx->text.insertPos, XawstEOL, dir,
707 mult, (dir == XawsdRight));
708
709 next_line = SrcScanXawTextSourceScan(ctx->text.source, cnew, XawstEOL, XawsdRight, 1, False0);
710
711 FindPosXawTextSinkFindPosition(ctx->text.sink, cnew, ctx->text.left_margin, ctx->text.from_left,
712 False0, &ctx->text.insertPos, &from_left, &itemp);
713
714 if (from_left < ctx->text.from_left) {
715 XawTextBlock block;
716
717 XawTextSourceRead(ctx->text.source, ctx->text.insertPos, &block, 1);
718 if (block.length) {
719 if (XawTextFormat(ctx, XawFmtWide)((unsigned long)_XawTextFormat(ctx) == (XawFmtWide))) {
720 if (*(wchar_t *)block.ptr == _Xaw_atowc(XawTAB0x09))
721 ++ctx->text.insertPos;
722 }
723 else if (block.ptr[0] == XawTAB0x09)
724 ++ctx->text.insertPos;
725 }
726 }
727
728 if (ctx->text.insertPos > next_line)
729 ctx->text.insertPos = next_line;
730
731 EndAction(ctx);
732}
733
734static void
735MoveNextLine(Widget w, XEvent *event, String *p, Cardinal *n)
736{
737 TextWidget ctx = (TextWidget)w;
738 short mult = MULT(ctx)(ctx->text.mult == 0 ? 4 : ctx->text.mult == 32767 ? -4
: ctx->text.mult)
;
739
740 if (mult < 0) {
741 ctx->text.mult = -mult;
742 MovePreviousLine(w, event, p, n);
743 return;
744 }
745
746 if (ctx->text.insertPos < ctx->text.lastPos)
747 MoveLine(ctx, event, XawsdRight);
748 else
749 ctx->text.mult = 1;
750}
751
752static void
753MovePreviousLine(Widget w, XEvent *event, String *p, Cardinal *n)
754{
755 TextWidget ctx = (TextWidget)w;
756 short mult = MULT(ctx)(ctx->text.mult == 0 ? 4 : ctx->text.mult == 32767 ? -4
: ctx->text.mult)
;
757
758 if (mult < 0) {
759 ctx->text.mult = -mult;
760 MoveNextLine(w, event, p, n);
761 return;
762 }
763
764 if (ctx->text.lt.top != 0 || (ctx->text.lt.lines > 1 &&
765 ctx->text.insertPos >= ctx->text.lt.info[1].position))
766 MoveLine(ctx, event, XawsdLeft);
767 else
768 ctx->text.mult = 1;
769}
770
771/*ARGSUSED*/
772static void
773MoveBeginningOfFile(Widget w, XEvent *event, String *p, Cardinal *n)
774{
775 Move((TextWidget)w, event, XawsdLeft, XawstAll, True1);
776}
777
778/*ARGSUSED*/
779static void
780MoveEndOfFile(Widget w, XEvent *event, String *p, Cardinal *n)
781{
782 Move((TextWidget)w, event, XawsdRight, XawstAll, True1);
783}
784
785static void
786Scroll(TextWidget ctx, XEvent *event, XawTextScanDirection dir)
787{
788 short mult = MULT(ctx)(ctx->text.mult == 0 ? 4 : ctx->text.mult == 32767 ? -4
: ctx->text.mult)
;
789
790 if (mult < 0) {
791 mult = -mult;
792 dir = dir == XawsdLeft ? XawsdRight : XawsdLeft;
793 }
794
795 if (ctx->text.lt.lines > 1
796 && (dir == XawsdRight
797 || ctx->text.lastPos >= ctx->text.lt.info[1].position)) {
798 StartAction(ctx, event);
799
800 if (dir == XawsdLeft)
801 _XawTextVScroll(ctx, mult);
802 else
803 _XawTextVScroll(ctx, -mult);
804
805 EndAction(ctx);
806 }
807 else {
808 ctx->text.mult = 1;
809#ifndef OLDXAW
810 ctx->text.numeric = False0;
811#endif
812 }
813}
814
815/*ARGSUSED*/
816static void
817ScrollOneLineUp(Widget w, XEvent *event, String *p, Cardinal *n)
818{
819 Scroll((TextWidget)w, event, XawsdLeft);
820}
821
822/*ARGSUSED*/
823static void
824ScrollOneLineDown(Widget w, XEvent *event, String *p, Cardinal *n)
825{
826 Scroll((TextWidget)w, event, XawsdRight);
827}
828
829static void
830MovePage(TextWidget ctx, XEvent *event, XawTextScanDirection dir)
831{
832 int scroll_val = 0;
833 XawTextPosition old_pos;
834
835 ctx->text.from_left = -1;
836 switch (dir) {
837 case XawsdLeft:
838 if (ctx->text.lt.top != 0)
839 scroll_val = -Max(1, ctx->text.lt.lines - 1)(((1) > (ctx->text.lt.lines - 1)) ? (1) : (ctx->text
.lt.lines - 1))
;
840 break;
841 case XawsdRight:
842 if (!IsPositionVisible(ctx, Max(0, ctx->text.lastPos))((((0) > (ctx->text.lastPos)) ? (0) : (ctx->text.lastPos
)) >= ctx->text.lt.info[0].position && (((0) >
(ctx->text.lastPos)) ? (0) : (ctx->text.lastPos)) <
ctx->text.lt.info[ctx->text.lt.lines].position)
)
843 scroll_val = Max(1, ctx->text.lt.lines - 1)(((1) > (ctx->text.lt.lines - 1)) ? (1) : (ctx->text
.lt.lines - 1))
;
844 break;
845 }
846
847 if (scroll_val)
848 XawTextScroll(ctx, scroll_val,
849 ctx->text.left_margin - ctx->text.r_margin.left);
850
851 old_pos = ctx->text.insertPos;
852 switch (dir) {
853 case XawsdRight:
854 if (IsPositionVisible(ctx, Max(0, ctx->text.lastPos))((((0) > (ctx->text.lastPos)) ? (0) : (ctx->text.lastPos
)) >= ctx->text.lt.info[0].position && (((0) >
(ctx->text.lastPos)) ? (0) : (ctx->text.lastPos)) <
ctx->text.lt.info[ctx->text.lt.lines].position)
)
855 ctx->text.insertPos = Max(0, ctx->text.lastPos)(((0) > (ctx->text.lastPos)) ? (0) : (ctx->text.lastPos
))
;
856 else
857 ctx->text.insertPos = ctx->text.lt.top;
858 if (ctx->text.insertPos < old_pos)
859 ctx->text.insertPos = SrcScanXawTextSourceScan(ctx->text.source, old_pos,
860 XawstEOL, XawsdLeft, 1, False0);
861 break;
862 case XawsdLeft:
863 if (IsPositionVisible(ctx, 0)(0 >= ctx->text.lt.info[0].position && 0 < ctx
->text.lt.info[ctx->text.lt.lines].position)
)
864 ctx->text.insertPos = 0;
865 else if (ctx->text.lt.lines)
866 ctx->text.insertPos =
867 ctx->text.lt.info[ctx->text.lt.lines - 1].position;
868 else
869 ctx->text.insertPos = ctx->text.lt.top;
870 if (ctx->text.insertPos > old_pos)
871 ctx->text.insertPos = SrcScanXawTextSourceScan(ctx->text.source, old_pos,
872 XawstEOL, XawsdLeft, 1, False0);
873 break;
874 }
875}
876
877static void
878MoveNextPage(Widget w, XEvent *event, String *p, Cardinal *n)
879{
880 TextWidget ctx = (TextWidget)w;
881 short mult = MULT(ctx)(ctx->text.mult == 0 ? 4 : ctx->text.mult == 32767 ? -4
: ctx->text.mult)
;
882
883 if (mult < 0) {
884 ctx->text.mult = -mult;
885 MovePreviousPage(w, event, p, n);
886 return;
887 }
888
889 if (ctx->text.insertPos < ctx->text.lastPos) {
890 XawTextUnsetSelection(w);
891 StartAction(ctx, event);
892 ctx->text.clear_to_eol = True1;
893 while (mult-- && ctx->text.insertPos < ctx->text.lastPos)
894 MovePage(ctx, event, XawsdRight);
895 EndAction(ctx);
896 }
897 else
898 ctx->text.mult = 1;
899}
900
901/*ARGSUSED*/
902static void
903MovePreviousPage(Widget w, XEvent *event, String *p, Cardinal *n)
904{
905 TextWidget ctx = (TextWidget)w;
906 short mult = MULT(ctx)(ctx->text.mult == 0 ? 4 : ctx->text.mult == 32767 ? -4
: ctx->text.mult)
;
907
908 if (mult < 0) {
909 ctx->text.mult = -mult;
910 MoveNextPage(w, event, p, n);
911 return;
912 }
913
914 if (ctx->text.insertPos > 0) {
915 XawTextUnsetSelection(w);
916 StartAction(ctx, event);
917 ctx->text.clear_to_eol = True1;
918 while (mult-- && ctx->text.insertPos > 0)
919 MovePage(ctx, event, XawsdLeft);
920 EndAction(ctx);
921 }
922 else
923 ctx->text.mult = 1;
924}
925
926/*
927 * Delete Routines
928 */
929static Boolint
930MatchSelection(Atom selection, XawTextSelection *s)
931{
932 Atom *match;
933 int count;
934
935 for (count = 0, match = s->selections; count < s->atom_count;
936 match++, count++)
937 if (*match == selection)
938 return (True1);
939
940 return (False0);
941}
942
943#define SrcCvtSelXawTextSourceConvertSelection XawTextSourceConvertSelection
944
945static Boolean
946ConvertSelection(Widget w, Atom *selection, Atom *target, Atom *type,
947 XtPointer *value, unsigned long *length, int *format)
948{
949 Display *d = XtDisplay(w)(((w)->core.screen)->display);
950 TextWidget ctx = (TextWidget)w;
951 Widget src = ctx->text.source;
952 XawTextEditType edit_mode;
953 Arg args[1];
954 XawTextSelectionSalt *salt = NULL((void*)0);
955 XawTextSelection *s;
956
957 if (*target == XA_TARGETS(d)XmuInternAtom(d, _XA_TARGETS)) {
958 Atom *targetP, *std_targets;
959 unsigned long std_length;
960
961 if (SrcCvtSelXawTextSourceConvertSelection(src, selection, target, type, value, length, format))
962 return (True1);
963
964 XtSetArg(args[0], XtNeditType,&edit_mode)((void)( (args[0]).name = (((char*)&XtStrings[185])), (args
[0]).value = (XtArgVal)(&edit_mode) ))
;
965 XtGetValues(src, args, 1);
966
967 XmuConvertStandardSelection(w, ctx->text.time, selection,
968 target, type, (XPointer *)&std_targets,
969 &std_length, format);
970
971 *length = 7 + (edit_mode == XawtextEdit) + std_length;
972 *value = XtMalloc((unsigned)sizeof(Atom)*(*length));
973 targetP = *(Atom**)value;
974 *targetP++ = XA_STRING((Atom) 31);
975 *targetP++ = XA_TEXT(d)XmuInternAtom(d, _XA_TEXT);
976 *targetP++ = XA_UTF8_STRING(d)XmuInternAtom(d, _XA_UTF8_STRING);
977 *targetP++ = XA_COMPOUND_TEXT(d)XmuInternAtom(d, _XA_COMPOUND_TEXT);
978 *targetP++ = XA_LENGTH(d)XmuInternAtom(d, _XA_LENGTH);
979 *targetP++ = XA_LIST_LENGTH(d)XmuInternAtom(d, _XA_LIST_LENGTH);
980 *targetP++ = XA_CHARACTER_POSITION(d)XmuInternAtom(d, _XA_CHARACTER_POSITION);
981 if (edit_mode == XawtextEdit) {
982 *targetP++ = XA_DELETE(d)XmuInternAtom(d, _XA_DELETE);
983 }
984 memcpy((char*)targetP, (char*)std_targets, sizeof(Atom)*std_length)__builtin___memcpy_chk ((char*)targetP, (char*)std_targets, sizeof
(Atom)*std_length, __builtin_object_size ((char*)targetP, 0))
;
985 XtFree((char*)std_targets);
986 *type = XA_ATOM((Atom) 4);
987 *format = 32;
988 return (True1);
989 }
990
991 if (SrcCvtSelXawTextSourceConvertSelection(src, selection, target, type, value, length, format))
992 return (True1);
993
994 for (salt = ctx->text.salt2; salt; salt = salt->next)
995 if (MatchSelection (*selection, &salt->s))
996 break;
997 if (!salt)
998 return (False0);
999 s = &salt->s;
1000 if (*target == XA_STRING((Atom) 31)
1001 || *target == XA_TEXT(d)XmuInternAtom(d, _XA_TEXT)
1002 || *target == XA_UTF8_STRING(d)XmuInternAtom(d, _XA_UTF8_STRING)
1003 || *target == XA_COMPOUND_TEXT(d)XmuInternAtom(d, _XA_COMPOUND_TEXT)) {
1004 if (*target == XA_TEXT(d)XmuInternAtom(d, _XA_TEXT)) {
1005 if (XawTextFormat(ctx, XawFmtWide)((unsigned long)_XawTextFormat(ctx) == (XawFmtWide)))
1006 *type = XA_COMPOUND_TEXT(d)XmuInternAtom(d, _XA_COMPOUND_TEXT);
1007 else
1008 *type = XA_STRING((Atom) 31);
1009 }
1010 else
1011 *type = *target;
1012
1013 /*
1014 * If salt is True, the salt->contents stores CT string,
1015 * its length is measured in bytes.
1016 * Refer to _XawTextSaltAwaySelection()
1017 *
1018 * by Li Yuhong, Mar. 20, 1991.
1019 */
1020 if (!salt) {
1021 *value = (char *)_XawTextGetSTRING(ctx, s->left, s->right);
1022 if (XawTextFormat(ctx, XawFmtWide)((unsigned long)_XawTextFormat(ctx) == (XawFmtWide))) {
1023 XTextProperty textprop;
1024 if (XwcTextListToTextProperty(d, (wchar_t**)value, 1,
1025 XCompoundTextStyle, &textprop)
1026 < Success0) {
1027 XtFree(*value);
1028 return (False0);
1029 }
1030 XtFree(*value);
1031 *value = (XtPointer)textprop.value;
1032 *length = textprop.nitems;
1033 }
1034 else
1035 *length = strlen(*value);
1036 }
1037 else {
1038 *value = XtMalloc((salt->length + 1) * sizeof(unsigned char));
1039 strcpy (*value, salt->contents)__builtin___strcpy_chk (*value, salt->contents, __builtin_object_size
(*value, 2 > 1 ? 1 : 0))
;
1040 *length = salt->length;
1041 }
1042 /* Got *value,*length, now in COMPOUND_TEXT format. */
1043 if (XawTextFormat(ctx, XawFmtWide)((unsigned long)_XawTextFormat(ctx) == (XawFmtWide))) {
1044 if (*type == XA_STRING((Atom) 31)) {
1045 XTextProperty textprop;
1046 wchar_t **wlist;
1047 int count;
1048
1049 textprop.encoding = XA_COMPOUND_TEXT(d)XmuInternAtom(d, _XA_COMPOUND_TEXT);
1050 textprop.value = (unsigned char *)*value;
1051 textprop.nitems = strlen(*value);
1052 textprop.format = 8;
1053 if (XwcTextPropertyToTextList(d, &textprop, &wlist, &count)
1054 < Success0
1055 || count < 1) {
1056 XtFree(*value);
1057 return (False0);
1058 }
1059 XtFree(*value);
1060 if (XwcTextListToTextProperty(d, wlist, 1, XStringStyle, &textprop)
1061 < Success0) {
1062 XwcFreeStringList((wchar_t**)wlist);
1063 return (False0);
1064 }
1065 *value = (XtPointer)textprop.value;
1066 *length = textprop.nitems;
1067 XwcFreeStringList((wchar_t**) wlist);
1068 }
1069 else if (*type == XA_UTF8_STRING(d)XmuInternAtom(d, _XA_UTF8_STRING)) {
1070 XTextProperty textprop;
1071 char **list;
1072 int count;
1073
1074 textprop.encoding = XA_COMPOUND_TEXT(d)XmuInternAtom(d, _XA_COMPOUND_TEXT);
1075 textprop.value = (unsigned char *)*value;
1076 textprop.nitems = strlen(*value);
1077 textprop.format = 8;
1078 if (Xutf8TextPropertyToTextList(d, &textprop, &list, &count)
1079 < Success0
1080 || count < 1) {
1081 XtFree(*value);
1082 return (False0);
1083 }
1084 XtFree(*value);
1085 *value = *list;
1086 *length = strlen(*list);
1087 XFree(list);
1088 }
1089 }
1090 *format = 8;
1091 return (True1);
1092 }
1093
1094 if (*target == XA_LIST_LENGTH(d)XmuInternAtom(d, _XA_LIST_LENGTH) || *target == XA_LENGTH(d)XmuInternAtom(d, _XA_LENGTH)) {
1095 long *temp;
1096
1097 temp = (long *)XtMalloc(sizeof(long));
1098 if (*target == XA_LIST_LENGTH(d)XmuInternAtom(d, _XA_LIST_LENGTH))
1099 *temp = 1L;
1100 else /* *target == XA_LENGTH(d) */
1101 *temp = (long)(s->right - s->left);
1102
1103 *value = (XPointer)temp;
1104 *type = XA_INTEGER((Atom) 19);
1105 *length = 1L;
1106 *format = 32;
1107 return (True1);
1108 }
1109
1110 if (*target == XA_CHARACTER_POSITION(d)XmuInternAtom(d, _XA_CHARACTER_POSITION)) {
1111 long *temp;
1112
1113 temp = (long *) XtMalloc(2 * sizeof(long));
1114 temp[0] = (long)(s->left + 1);
1115 temp[1] = s->right;
1116 *value = (XPointer)temp;
1117 *type = XA_SPAN(d)XmuInternAtom(d, _XA_SPAN);
1118 *length = 2L;
1119 *format = 32;
1120 return (True1);
1121 }
1122
1123 if (*target == XA_DELETE(d)XmuInternAtom(d, _XA_DELETE)) {
1124 if (!salt)
1125 _XawTextZapSelection(ctx, NULL((void*)0), True1);
1126 *value = NULL((void*)0);
1127 *type = XA_NULL(d)XmuInternAtom(d, _XA_NULL);
1128 *length = 0;
1129 *format = 32;
1130 return (True1);
1131 }
1132
1133 if (XmuConvertStandardSelection(w, ctx->text.time, selection, target, type,
1134 (XPointer *)value, length, format))
1135 return (True1);
1136
1137 return (False0);
1138}
1139
1140static void
1141LoseSelection(Widget w, Atom *selection)
1142{
1143 _LoseSelection(w, selection, NULL((void*)0), NULL((void*)0));
14
Calling '_LoseSelection'
1144}
1145
1146static void
1147_LoseSelection(Widget w, Atom *selection, char **contents, int *length)
1148{
1149 TextWidget ctx = (TextWidget)w;
1150 Atom *atomP;
1151 int i;
1152 XawTextSelectionSalt *salt, *prevSalt, *nextSalt;
1153
1154 prevSalt = 0;
1155 for (salt = ctx->text.salt2; salt; salt = nextSalt) {
15
Loop condition is true. Entering loop body
1156 atomP = salt->s.selections;
1157 nextSalt = salt->next;
1158 for (i = 0 ; i < salt->s.atom_count; i++, atomP++)
16
Loop condition is false. Execution continues on line 1162
1159 if (*selection == *atomP)
1160 *atomP = (Atom)0;
1161
1162 while (salt->s.atom_count
1163 && salt->s.selections[salt->s.atom_count-1] == 0)
1164 salt->s.atom_count--;
1165
1166 /*
1167 * Must walk the selection list in opposite order from UnsetSelection.
1168 */
1169 atomP = salt->s.selections;
1170 for (i = 0 ; i < salt->s.atom_count; i++, atomP++)
17
Loop condition is false. Execution continues on line 1178
1171 if (*atomP == (Atom)0) {
1172 *atomP = salt->s.selections[--salt->s.atom_count];
1173
1174 while (salt->s.atom_count
1175 && salt->s.selections[salt->s.atom_count-1] == 0)
1176 salt->s.atom_count--;
1177 }
1178 if (salt->s.atom_count == 0) {
18
Taking true branch
1179#ifndef OLDXAW
1180 if (contents == NULL((void*)0)) {
19
Taking true branch
1181 XawTextKillRing *kill_ring = XtNew(XawTextKillRing)((XawTextKillRing *) XtMalloc((unsigned) sizeof(XawTextKillRing
)))
;
1182
1183 kill_ring->next = xaw_text_kill_ring;
1184 kill_ring->contents = salt->contents;
1185 kill_ring->length = salt->length;
1186 kill_ring->format = XawFmt8Bit;
1187 xaw_text_kill_ring = kill_ring;
1188 kill_ring_prev.next = xaw_text_kill_ring;
1189
1190 if (++num_kill_rings > MAX_KILL_RINGS1024) {
20
Taking true branch
1191 XawTextKillRing *tail = NULL((void*)0);
21
'tail' initialized to a null pointer value
1192
1193 while (kill_ring->next) {
22
Loop condition is false. Execution continues on line 1197
1194 tail = kill_ring;
1195 kill_ring = kill_ring->next;
1196 }
1197 if (kill_ring->refcount == 0) {
23
Taking true branch
1198 --num_kill_rings;
1199 tail->next = NULL((void*)0);
24
Access to field 'next' results in a dereference of a null pointer (loaded from variable 'tail')
1200 XtFree(kill_ring->contents);
1201 XtFree((char*)kill_ring);
1202 }
1203 }
1204 }
1205 else {
1206 *contents = salt->contents;
1207 *length = salt->length;
1208 }
1209#endif
1210 if (prevSalt)
1211 prevSalt->next = nextSalt;
1212 else
1213 ctx->text.salt2 = nextSalt;
1214
1215 XtFree((char *)salt->s.selections);
1216 XtFree((char *)salt);
1217 }
1218 else
1219 prevSalt = salt;
1220 }
1221}
1222
1223static void
1224_DeleteOrKill(TextWidget ctx, XawTextPosition from, XawTextPosition to,
1225 Boolint kill)
1226{
1227 XawTextBlock text;
1228
1229#ifndef OLDXAW
1230 if (ctx->text.kill_ring_ptr) {
9
Taking false branch
1231 --ctx->text.kill_ring_ptr->refcount;
1232 ctx->text.kill_ring_ptr = NULL((void*)0);
1233 }
1234#endif
1235 if (kill && from < to) {
10
Taking true branch
1236#ifndef OLDXAW
1237 Boolint append = False0;
1238 char *ring = NULL((void*)0);
1239 XawTextPosition old_from = from;
1240#endif
1241 char *string;
1242 int size = 0, length;
1243 XawTextSelectionSalt *salt;
1244 Atom selection = XInternAtom(XtDisplay(ctx)(((ctx)->core.screen)->display), "SECONDARY", False0);
1245
1246#ifndef OLDXAW
1247 if (ctx->text.kill_ring == KILL_RING_APPEND2) {
11
Taking false branch
1248 old_from = ctx->text.salt2->s.left;
1249 append = True1;
1250 }
1251 else
1252 ctx->text.kill_ring = KILL_RING_BEGIN3;
1253
1254 if (append)
12
Taking false branch
1255 _LoseSelection((Widget)ctx, &selection, &ring, &size);
1256 else
1257#endif
1258 LoseSelection((Widget)ctx, &selection);
13
Calling 'LoseSelection'
1259
1260 salt = (XawTextSelectionSalt*)XtMalloc(sizeof(XawTextSelectionSalt));
1261 salt->s.selections = (Atom *)XtMalloc(sizeof(Atom));
1262 salt->s.left = from;
1263 salt->s.right = to;
1264
1265 string = (char *)_XawTextGetSTRING(ctx, from, to);
1266
1267 if (XawTextFormat(ctx, XawFmtWide)((unsigned long)_XawTextFormat(ctx) == (XawFmtWide))) {
1268 XTextProperty textprop;
1269
1270 if (XwcTextListToTextProperty(XtDisplay((Widget)ctx)((((Widget)ctx)->core.screen)->display),
1271 (wchar_t**)(&string),
1272 1, XCompoundTextStyle,
1273 &textprop) < Success0) {
1274 XtFree(string);
1275 XtFree((char*)salt->s.selections);
1276 XtFree((char*)salt);
1277 return;
1278 }
1279 XtFree(string);
1280 string = (char *)textprop.value;
1281 length = textprop.nitems;
1282 }
1283 else
1284 length = strlen(string);
1285
1286 salt->length = length + size;
1287
1288#ifndef OLDXAW
1289 if (!append)
1290 salt->contents = string;
1291 else {
1292 salt->contents = XtMalloc(length + size + 1);
1293 if (from >= old_from) {
1294 strncpy(salt->contents, ring, size)__builtin___strncpy_chk (salt->contents, ring, size, __builtin_object_size
(salt->contents, 2 > 1 ? 1 : 0))
;
1295 salt->contents[size] = '\0';
1296 strncat(salt->contents, string, length)__builtin___strncat_chk (salt->contents, string, length, __builtin_object_size
(salt->contents, 2 > 1 ? 1 : 0))
;
1297 }
1298 else {
1299 strncpy(salt->contents, string, length)__builtin___strncpy_chk (salt->contents, string, length, __builtin_object_size
(salt->contents, 2 > 1 ? 1 : 0))
;
1300 salt->contents[length] = '\0';
1301 strncat(salt->contents, ring, size)__builtin___strncat_chk (salt->contents, ring, size, __builtin_object_size
(salt->contents, 2 > 1 ? 1 : 0))
;
1302 }
1303 salt->contents[length + size] = '\0';
1304 XtFree(ring);
1305 XtFree(string);
1306 }
1307
1308 kill_ring_prev.contents = salt->contents;
1309 kill_ring_prev.length = salt->length;
1310 kill_ring_prev.format = XawFmt8Bit;
1311#else
1312 salt->contents = string;
1313#endif
1314
1315 salt->next = ctx->text.salt2;
1316 ctx->text.salt2 = salt;
1317
1318#ifndef OLDXAW
1319 if (append)
1320 ctx->text.kill_ring = KILL_RING_BEGIN3;
1321#endif
1322
1323 salt->s.selections[0] = selection;
1324
1325 XtOwnSelection((Widget)ctx, selection, ctx->text.time,
1326 ConvertSelection, LoseSelection, NULL((void*)0));
1327 salt->s.atom_count = 1;
1328 }
1329 text.length = 0;
1330 text.firstPos = 0;
1331
1332 text.format = _XawTextFormat(ctx);
1333 text.ptr = "";
1334
1335 if (_XawTextReplace(ctx, from, to, &text)) {
1336 XBell(XtDisplay(ctx)(((ctx)->core.screen)->display), 50);
1337 return;
1338 }
1339 ctx->text.from_left = -1;
1340 ctx->text.insertPos = from;
1341 ctx->text.showposition = TRUE1;
1342}
1343
1344static void
1345DeleteOrKill(TextWidget ctx, XEvent *event, XawTextScanDirection dir,
1346 XawTextScanType type, Boolint include, Boolint kill)
1347{
1348 XawTextPosition from, to;
1349 short mult = MULT(ctx)(ctx->text.mult == 0 ? 4 : ctx->text.mult == 32767 ? -4
: ctx->text.mult)
;
1350
1351 if (mult < 0) {
2
Assuming 'mult' is >= 0
3
Taking false branch
1352 mult = -mult;
1353 dir = dir == XawsdLeft ? XawsdRight : XawsdLeft;
1354 }
1355
1356 StartAction(ctx, event);
1357#ifndef OLDXAW
1358 if (mult == 1)
4
Assuming 'mult' is not equal to 1
5
Taking false branch
1359 _XawSourceSetUndoMerge((TextSrcObject)ctx->text.source, True1);
1360#endif
1361 to = SrcScanXawTextSourceScan(ctx->text.source, ctx->text.insertPos,
1362 type, dir, mult, include);
1363
1364 /*
1365 * If no movement actually happened, then bump the count and try again.
1366 * This causes the character position at the very beginning and end of
1367 * a boundary to act correctly
1368 */
1369 if (to == ctx->text.insertPos)
6
Taking false branch
1370 to = SrcScanXawTextSourceScan(ctx->text.source, ctx->text.insertPos,
1371 type, dir, mult + 1, include);
1372
1373 if (dir == XawsdLeft) {
7
Taking false branch
1374 from = to;
1375 to = ctx->text.insertPos;
1376 }
1377 else
1378 from = ctx->text.insertPos;
1379
1380 _DeleteOrKill(ctx, from, to, kill);
8
Calling '_DeleteOrKill'
1381 EndAction(ctx);
1382}
1383
1384static void
1385Delete(Widget w, XEvent *event, String *p, Cardinal *n)
1386{
1387 TextWidget ctx = (TextWidget)w;
1388
1389 if (ctx->text.s.left != ctx->text.s.right)
1390 DeleteCurrentSelection(w, event, p, n);
1391 else
1392 DeleteBackwardChar(w, event, p, n);
1393}
1394
1395static void
1396DeleteChar(Widget w, XEvent *event, XawTextScanDirection dir)
1397{
1398 TextWidget ctx = (TextWidget)w;
1399 short mul = MULT(ctx)(ctx->text.mult == 0 ? 4 : ctx->text.mult == 32767 ? -4
: ctx->text.mult)
;
1400
1401 if (mul < 0) {
1402 ctx->text.mult = mul = -mul;
1403 dir = dir == XawsdLeft ? XawsdRight : XawsdLeft;
1404 }
1405 DeleteOrKill(ctx, event, dir, XawstPositions, True1, False0);
1406#ifndef OLDXAW
1407 if (mul == 1)
1408 _XawSourceSetUndoErase((TextSrcObject)ctx->text.source,
1409 dir == XawsdLeft ? -1 : 1);
1410#endif
1411}
1412
1413/*ARGSUSED*/
1414static void
1415DeleteForwardChar(Widget w, XEvent *event, String *p, Cardinal *n)
1416{
1417 DeleteChar(w, event, XawsdRight);
1418}
1419
1420/*ARGSUSED*/
1421static void
1422DeleteBackwardChar(Widget w, XEvent *event, String *p, Cardinal *n)
1423{
1424 DeleteChar(w, event, XawsdLeft);
1425}
1426
1427static void
1428DeleteForwardWord(Widget w, XEvent *event, String *params, Cardinal *num_params)
1429{
1430 XawTextScanType type;
1431
1432 if (*num_params && (*params[0] == 'A' || *params[0] == 'a'))
1433 type = XawstAlphaNumeric;
1434 else
1435 type = XawstWhiteSpace;
1436
1437 DeleteOrKill((TextWidget)w, event, XawsdRight, type, False0, False0);
1438}
1439
1440static void
1441DeleteBackwardWord(Widget w, XEvent *event, String *params, Cardinal *num_params)
1442{
1443 XawTextScanType type;
1444
1445 if (*num_params && (*params[0] == 'A' || *params[0] == 'a'))
1446 type = XawstAlphaNumeric;
1447 else
1448 type = XawstWhiteSpace;
1449
1450 DeleteOrKill((TextWidget)w, event, XawsdLeft, type, False0, False0);
1451}
1452
1453static void
1454KillForwardWord(Widget w, XEvent *event, String *params, Cardinal *num_params)
1455{
1456 XawTextScanType type;
1457
1458 if (*num_params && (*params[0] == 'A' || *params[0] == 'a'))
1459 type = XawstAlphaNumeric;
1460 else
1461 type = XawstWhiteSpace;
1462
1463 DeleteOrKill((TextWidget)w, event, XawsdRight, type, False0, True1);
1464}
1465
1466static void
1467KillBackwardWord(Widget w, XEvent *event, String *params, Cardinal *num_params)
1468{
1469 XawTextScanType type;
1470
1471 if (*num_params && (*params[0] == 'A' || *params[0] == 'a'))
1472 type = XawstAlphaNumeric;
1473 else
1474 type = XawstWhiteSpace;
1475
1476 DeleteOrKill((TextWidget) w, event, XawsdLeft, type, False0, True1);
1477}
1478
1479/*ARGSUSED*/
1480static void
1481KillToEndOfLine(Widget w, XEvent *event, String *p, Cardinal *n)
1482{
1483 TextWidget ctx = (TextWidget)w;
1484 XawTextPosition end_of_line;
1485 XawTextScanDirection dir = XawsdRight;
1486 short mult = MULT(ctx)(ctx->text.mult == 0 ? 4 : ctx->text.mult == 32767 ? -4
: ctx->text.mult)
;
1487
1488 if (mult < 0) {
1489 dir = XawsdLeft;
1490 mult = -mult;
1491 }
1492
1493 StartAction(ctx, event);
1494 end_of_line = SrcScanXawTextSourceScan(ctx->text.source, ctx->text.insertPos, XawstEOL,
1495 dir, mult, False0);
1496 if (end_of_line == ctx->text.insertPos)
1497 end_of_line = SrcScanXawTextSourceScan(ctx->text.source, ctx->text.insertPos, XawstEOL,
1498 dir, mult, True1);
1499
1500 if (dir == XawsdRight)
1501 _DeleteOrKill(ctx, ctx->text.insertPos, end_of_line, True1);
1502 else
1503 _DeleteOrKill(ctx, end_of_line, ctx->text.insertPos, True1);
1504 EndAction(ctx);
1505}
1506
1507/*ARGSUSED*/
1508static void
1509KillToEndOfParagraph(Widget w, XEvent *event, String *p, Cardinal *n)
1510{
1511 DeleteOrKill((TextWidget)w, event, XawsdRight, XawstParagraph, False0, True1);
1
Calling 'DeleteOrKill'
1512}
1513
1514void
1515_XawTextZapSelection(TextWidget ctx, XEvent *event, Boolint kill)
1516{
1517 StartAction(ctx, event);
1518 _DeleteOrKill(ctx, ctx->text.s.left, ctx->text.s.right, kill);
1519 EndAction(ctx);
1520}
1521
1522/*ARGSUSED*/
1523static void
1524KillCurrentSelection(Widget w, XEvent *event, String *p, Cardinal *n)
1525{
1526 _XawTextZapSelection((TextWidget) w, event, True1);
1527}
1528
1529#ifndef OLDXAW
1530/*ARGSUSED*/
1531static void
1532KillRingYank(Widget w, XEvent *event, String *params, Cardinal *num_params)
1533{
1534 TextWidget ctx = (TextWidget)w;
1535 XawTextPosition insertPos = ctx->text.insertPos;
1536 Boolint first_yank = False0;
1537
1538 if (ctx->text.s.left != ctx->text.s.right)
1539 XawTextUnsetSelection((Widget)ctx);
1540
1541 StartAction(ctx, event);
1542
1543 if (ctx->text.kill_ring_ptr == NULL((void*)0)) {
1544 ctx->text.kill_ring_ptr = &kill_ring_prev;
1545 ++ctx->text.kill_ring_ptr->refcount;
1546 ctx->text.s.left = ctx->text.s.right = insertPos;
1547 first_yank = True1;
1548 }
1549 if (ctx->text.kill_ring_ptr) {
1550 int mul = MULT(ctx)(ctx->text.mult == 0 ? 4 : ctx->text.mult == 32767 ? -4
: ctx->text.mult)
;
1551 XawTextBlock text;
1552
1553 if (!first_yank) {
1554 if (mul < 0)
1555 mul = 1;
1556 --ctx->text.kill_ring_ptr->refcount;
1557 while (mul--) {
1558 if ((ctx->text.kill_ring_ptr = ctx->text.kill_ring_ptr->next) == NULL((void*)0))
1559 ctx->text.kill_ring_ptr = &kill_ring_null;
1560 }
1561 ++ctx->text.kill_ring_ptr->refcount;
1562 }
1563 text.firstPos = 0;
1564 text.length = ctx->text.kill_ring_ptr->length;
1565 text.ptr = ctx->text.kill_ring_ptr->contents;
1566 text.format = ctx->text.kill_ring_ptr->format;
1567
1568 if (_XawTextReplace(ctx, ctx->text.s.left, insertPos, &text) == XawEditDone0) {
1569 ctx->text.kill_ring = KILL_RING_YANK100;
1570 ctx->text.insertPos = ctx->text.s.left + text.length;
1571 }
1572 }
1573 else
1574 XBell(XtDisplay(w)(((w)->core.screen)->display), 0);
1575
1576 EndAction(ctx);
1577}
1578#endif /* OLDXAW */
1579
1580/*ARGSUSED*/
1581static void
1582DeleteCurrentSelection(Widget w, XEvent *event, String *p, Cardinal *n)
1583{
1584 _XawTextZapSelection((TextWidget)w, event, False0);
1585}
1586
1587#ifndef OLDXAW
1588#define CHECK_SAVE() \
1589 if (save && !save->ptr) \
1590 save->ptr = _XawTextGetText(ctx, save->firstPos, \
1591 save->firstPos + save->length)
1592static Boolint
1593StripSpaces(TextWidget ctx, XawTextPosition left, XawTextPosition right,
1594 XawTextPosition *pos, int num_pos, XawTextBlock *save)
1595{
1596 Boolint done, space;
1597 int i, cpos, count = 0;
1598 XawTextBlock block, text;
1599 XawTextPosition ipos, position = left, tmp = left;
1600
1601 text.firstPos = 0;
1602 text.format = XawFmt8Bit;
1603 text.ptr = " ";
1604 text.length = 1;
1605
1606 position = XawTextSourceRead(ctx->text.source, position,
1607 &block, right - left);
1608 done = False0;
1609 space = False0;
1610 /* convert tabs and returns to spaces */
1611 while (!done) {
1612 if (XawTextFormat(ctx, XawFmt8Bit)((unsigned long)_XawTextFormat(ctx) == (XawFmt8Bit))) {
1613 for (i = 0; i < block.length; i++)
1614 if (block.ptr[i] == '\t' || block.ptr[i] == '\n') {
1615 space = True1;
1616 break;
1617 }
1618 }
1619 else {
1620 wchar_t *wptr = (wchar_t*)block.ptr;
1621 for (i = 0; i < block.length; i++)
1622 if (wptr[i] == _Xaw_atowc('\t') || wptr[i] == _Xaw_atowc('\n')) {
1623 space = True1;
1624 break;
1625 }
1626 }
1627 if (space) {
1628 CHECK_SAVE();
1629 if (_XawTextReplace(ctx, tmp + i, tmp + i + 1, &text))
1630 return (False0);
1631 space = False0;
1632 }
1633 tmp += i;
1634 position = XawTextSourceRead(ctx->text.source, tmp,
1635 &block, right - tmp);
1636 if (block.length == 0 || tmp == position || tmp >= right)
1637 done = True1;
1638 }
1639
1640 text.ptr = "";
1641 text.length = 0;
1642 position = tmp = left;
1643 position = XawTextSourceRead(ctx->text.source, position,
1644 &block, right - left);
1645 ipos = ctx->text.insertPos;
1646 done = False0;
1647 while (!done) {
1648 if (XawTextFormat(ctx, XawFmt8Bit)((unsigned long)_XawTextFormat(ctx) == (XawFmt8Bit))) {
1649 for (i = 0; i < block.length; i++)
1650 if (block.ptr[i] == ' ')
1651 ++count;
1652 else if (count == 1)
1653 count = 0;
1654 else if (count)
1655 break;
1656 }
1657 else {
1658 wchar_t *wptr = (wchar_t*)block.ptr;
1659 for (i = 0; i < block.length; i++)
1660 if (wptr[i] == _Xaw_atowc(' '))
1661 ++count;
1662 else if (count == 1)
1663 count = 0;
1664 else if (count)
1665 break;
1666 }
1667 if (--count > 0) {
1668 CHECK_SAVE();
1669 if (_XawTextReplace(ctx, tmp + i - count, tmp + i, &text))
1670 return (False0);
1671 right -= count;
1672 if (num_pos) {
1673 for (cpos = 0; cpos < num_pos; cpos++) {
1674 if (tmp + i - count < pos[cpos]) {
1675 if (tmp + i < pos[cpos])
1676 pos[cpos] -= count;
1677 else
1678 pos[cpos] = tmp + i - count;
1679 }
1680 }
1681 }
1682 else {
1683 if (tmp + i - count < ipos) {
1684 if (tmp + i < ipos)
1685 ipos -= count;
1686 else
1687 ipos = tmp + i - count;
1688 }
1689 }
1690 tmp += i - count;
1691 }
1692 else
1693 tmp += i + 1;
1694 count = 0;
1695 position = XawTextSourceRead(ctx->text.source, tmp,
1696 &block, right - tmp);
1697 if (block.length == 0 || tmp == position || tmp >= right)
1698 done = True1;
1699 }
1700 if (!num_pos)
1701 ctx->text.insertPos = ipos;
1702
1703 return (True1);
1704}
1705
1706static Boolint
1707Tabify(TextWidget ctx, XawTextPosition left, XawTextPosition right,
1708 XawTextPosition *pos, int num_pos, XawTextBlock *save)
1709{
1710 Boolint done, zero;
1711 int i, cpos, count = 0, column = 0, offset = 0;
1712 XawTextBlock text, block;
1713 XawTextPosition ipos, position = left, tmp = left;
1714 TextSinkObject sink = (TextSinkObject)ctx->text.sink;
1715 short *char_tabs = sink->text_sink.char_tabs;
1716 int tab_count = sink->text_sink.tab_count;
1717 int tab_index = 0, tab_column = 0, TAB_SIZE = DEFAULT_TAB_SIZE8;
1718
1719 text.firstPos = 0;
1720 text.ptr = "\t";
1721 text.format = XawFmt8Bit;
1722 text.length = 1;
1723
1724 position = XawTextSourceRead(ctx->text.source, position,
1725 &block, right - left);
1726 ipos = ctx->text.insertPos;
1727 done = zero = False0;
1728 if (tab_count)
1729 TAB_SIZE = *char_tabs;
1730 while (!done) {
1731 if (XawTextFormat(ctx, XawFmt8Bit)((unsigned long)_XawTextFormat(ctx) == (XawFmt8Bit))) {
1732 for (i = 0; i < block.length; i++) {
1733 ++offset;
1734 ++column;
1735 if (tab_count) {
1736 if (column > tab_column + char_tabs[tab_index]) {
1737 TAB_SIZE = tab_index < tab_count - 1 ? char_tabs[tab_index + 1] - char_tabs[tab_index] : *char_tabs;
1738 if (++tab_index >= tab_count) {
1739 tab_column += char_tabs[tab_count - 1];
1740 tab_index = 0;
1741 }
1742 }
1743 }
1744 if (block.ptr[i] == ' ') {
1745 if (++count > TAB_SIZE)
1746 count %= TAB_SIZE;
1747 if ((tab_count && column == tab_column + char_tabs[tab_index]) ||
1748 (!tab_count && column % TAB_SIZE == 0)) {
1749 if (count % (TAB_SIZE + 1) > 1)
1750 break;
1751 else
1752 count = 0;
1753 }
1754 }
1755 else {
1756 if (block.ptr[i] == '\n') {
1757 zero = True1;
1758 break;
1759 }
1760 count = 0;
1761 }
1762 }
1763 }
1764 else {
1765 wchar_t *wptr = (wchar_t*)block.ptr;
1766 for (i = 0; i < block.length; i++) {
1767 ++offset;
1768 ++column;
1769 if (tab_count) {
1770 if (column > tab_column + char_tabs[tab_index]) {
1771 TAB_SIZE = tab_index < tab_count - 1 ? char_tabs[tab_index + 1] - char_tabs[tab_index] : *char_tabs;
1772 if (++tab_index >= tab_count) {
1773 tab_column += char_tabs[tab_count - 1];
1774 tab_index = 0;
1775 }
1776 }
1777 }
1778 if (wptr[i] == _Xaw_atowc(' ')) {
1779 if (++count > TAB_SIZE)
1780 count %= TAB_SIZE;
1781 if ((tab_count && column == tab_column + char_tabs[tab_index]) ||
1782 (!tab_count && column % TAB_SIZE == 0)) {
1783 if (count % (TAB_SIZE + 1) > 1)
1784 break;
1785 else
1786 count = 0;
1787 }
1788 }
1789 else {
1790 if (wptr[i] == _Xaw_atowc('\n')) {
1791 zero = True1;
1792 break;
1793 }
1794 count = 0;
1795 }
1796 }
1797 }
1798 count %= TAB_SIZE + 1;
1799 if (!zero && count > 1 && i < block.length) {
1800 CHECK_SAVE();
1801 if (_XawTextReplace(ctx, tmp + i - count + 1, tmp + i + 1, &text))
1802 return (False0);
1803 right -= count - 1;
1804 offset -= count - 1;
1805 if (num_pos) {
1806 for (cpos = 0; cpos < num_pos; cpos++) {
1807 if (tmp + i - count + 1 < pos[cpos]) {
1808 if (tmp + i + 1 < pos[cpos])
1809 pos[cpos] -= count;
1810 else
1811 pos[cpos] = tmp + i - count + 1;
1812 ++pos[cpos];
1813 }
1814 }
1815 }
1816 else {
1817 if (tmp + i - count + 1 < ipos) {
1818 if (tmp + i + 1 < ipos)
1819 ipos -= count;
1820 else
1821 ipos = tmp + i - count + 1;
1822 ++ipos;
1823 }
1824 }
1825 }
1826 if (count)
1827 --count;
1828 if (zero) {
1829 count = column = 0;
1830 zero = False0;
1831 if (tab_count) {
1832 tab_column = tab_index = 0;
1833 TAB_SIZE = *char_tabs;
1834 }
1835 }
1836 else if (i < block.length)
1837 count = 0;
1838 tmp = left + offset;
1839 position = XawTextSourceRead(ctx->text.source, tmp,
1840 &block, right - tmp);
1841 if (tmp == position || tmp >= right)
1842 done = True1;
1843 }
1844 if (!num_pos)
1845 ctx->text.insertPos = ipos;
1846
1847 return (True1);
1848}
1849
1850static Boolint
1851Untabify(TextWidget ctx, XawTextPosition left, XawTextPosition right,
1852 XawTextPosition *pos, int num_pos, XawTextBlock *save)
1853{
1854 Boolint done, zero;
1855 int i, cpos, count = 0, diff = 0;
1856 XawTextBlock block, text;
1857 XawTextPosition ipos, position = left, tmp = left;
1858 TextSinkObject sink = (TextSinkObject)ctx->text.sink;
1859 short *char_tabs = sink->text_sink.char_tabs;
1860 int tab_count = sink->text_sink.tab_count;
1861 int tab_index = 0, tab_column = 0, tab_base = 0;
1862 static char *tabs = " ";
1863
1864 text.firstPos = 0;
1865 text.format = XawFmt8Bit;
1866 text.ptr = tabs;
1867
1868 position = XawTextSourceRead(ctx->text.source, position,
1869 &block, right - left);
1870 ipos = ctx->text.insertPos;
1871 done = False0;
1872 zero = False0;
1873 while (!done) {
1874 if (XawTextFormat(ctx, XawFmt8Bit)((unsigned long)_XawTextFormat(ctx) == (XawFmt8Bit)))
1875 for (i = 0; i < block.length; i++) {
1876 if (block.ptr[i] != '\t') {
1877 ++count;
1878 if (block.ptr[i] == '\n') {
1879 zero = True1;
1880 break;
1881 }
1882 }
1883 else
1884 break;
1885 }
1886 else {
1887 wchar_t *wptr = (wchar_t*)block.ptr;
1888 for (i = 0; i < block.length; i++)
1889 if (wptr[i] != _Xaw_atowc('\t')) {
1890 ++count;
1891 if (wptr[i] != _Xaw_atowc('\n')) {
1892 zero = True1;
1893 break;
1894 }
1895 }
1896 else
1897 break;
1898 }
1899 if (!zero && i < block.length) {
1900 if (tab_count) {
1901 while (tab_base + tab_column <= count) {
1902 for (; tab_index < tab_count; ++tab_index)
1903 if (tab_base + char_tabs[tab_index] > count) {
1904 tab_column = char_tabs[tab_index];
1905 break;
1906 }
1907 if (tab_index >= tab_count) {
1908 tab_base += char_tabs[tab_count - 1];
1909 tab_column = tab_index = 0;
1910 }
1911 }
1912 text.length = (tab_base + tab_column) - count;
1913 if (text.length > 8) {
1914 int j;
1915
1916 text.ptr = XtMalloc(text.length);
1917 for (j = 0; j < text.length; j++)
1918 text.ptr[j] = ' ';
1919 }
1920 else
1921 text.ptr = tabs;
1922 }
1923 else
1924 text.length = DEFAULT_TAB_SIZE8 - (count % DEFAULT_TAB_SIZE8);
1925 CHECK_SAVE();
1926 if (_XawTextReplace(ctx, tmp + i, tmp + i + 1, &text)) {
1927 if (tab_count && text.length > 8)
1928 XtFree(text.ptr);
1929 return (False0);
1930 }
1931 if (tab_count && text.length > 8)
1932 XtFree(text.ptr);
1933 count += text.length;
1934 right += text.length - 1;
1935 if (num_pos) {
1936 for (cpos = 0; cpos < num_pos; cpos++) {
1937 if (tmp + i < pos[cpos]) {
1938 if (tmp + i + 1 < pos[cpos])
1939 --pos[cpos];
1940 else
1941 pos[cpos] = tmp + i;
1942 pos[cpos] += text.length;
1943 }
1944 }
1945 }
1946 else {
1947 if (tmp + i < ipos) {
1948 if (tmp + i + 1 < ipos)
1949 --ipos;
1950 else
1951 ipos = tmp + i;
1952 ipos += text.length;
1953 }
1954 }
1955 }
1956 tmp = left + count + diff;
1957 if (zero) {
1958 diff += count;
1959 count = 0;
1960 zero = False0;
1961 if (tab_count)
1962 tab_base = tab_column = tab_index = 0;
1963 }
1964 position = XawTextSourceRead(ctx->text.source, tmp,
1965 &block, right - tmp);
1966 if (tmp == position || tmp >= right)
1967 done = True1;
1968 }
1969 if (!num_pos)
1970 ctx->text.insertPos = ipos;
1971
1972 return (True1);
1973}
1974
1975static int
1976FormatText(TextWidget ctx, XawTextPosition left, Boolint force,
1977 XawTextPosition *pos, int num_pos)
1978{
1979 char *ptr = NULL((void*)0);
1980 Boolint freepos = False0, undo, paragraph = pos != NULL((void*)0);
1981 int i, result;
1982 XawTextBlock block, *text;
1983 XawTextPosition end = ctx->text.lastPos, buf[32];
1984 TextSrcObject src = (TextSrcObject)ctx->text.source;
1985 XawTextPosition right = SrcScanXawTextSourceScan(ctx->text.source, left, XawstEOL,
1986 XawsdRight, 1, False0);
1987
1988 undo = src->textSrc.enable_undo && src->textSrc.undo_state == False0;
1989 if (undo) {
1990 if (!pos) {
1991 num_pos = src->textSrc.num_text;
1992 pos = XawStackAlloc(sizeof(XawTextPosition) * num_pos, buf)((sizeof(XawTextPosition) * num_pos) <= sizeof(buf) ? (XtPointer
)(buf) : XtMalloc((unsigned)(sizeof(XawTextPosition) * num_pos
)))
;
1993 for (i = 0; i < num_pos; i++)
1994 pos[i] = ((TextWidget)src->textSrc.text[i])->text.insertPos;
1995 freepos = True1;
1996 }
1997 else
1998 freepos = False0;
1999 src->textSrc.undo_state = True1;
2000 block.ptr = NULL((void*)0);
2001 block.firstPos = left;
2002 block.length = right - left;
2003 text = &block;
2004 }
2005 else
2006 text = NULL((void*)0);
2007
2008 result = DoFormatText(ctx, left, force, 1, text, pos, num_pos, paragraph);
2009 if (undo && result == XawEditDone0 && block.ptr) {
2010 char *lbuf, *rbuf;
2011 unsigned llen, rlen, size;
2012
2013 ptr = lbuf = block.ptr;
2014 llen = block.length;
2015 rlen = llen + (ctx->text.lastPos - end);
2016
2017 block.firstPos = 0;
2018 block.format = _XawTextFormat(ctx);
2019
2020 rbuf = _XawTextGetText(ctx, left, left + rlen);
2021
2022 size = XawTextFormat(ctx, XawFmtWide)((unsigned long)_XawTextFormat(ctx) == (XawFmtWide)) ? sizeof(wchar_t) : sizeof(char);
2023 if (llen != rlen || memcmp(lbuf, rbuf, llen * size)) {
2024 block.ptr = lbuf;
2025 block.length = llen;
2026 _XawTextReplace(ctx, left, left + rlen, &block);
2027
2028 src->textSrc.undo_state = False0;
2029 block.ptr = rbuf;
2030 block.length = rlen;
2031 _XawTextReplace(ctx, left, left + llen, &block);
2032 }
2033 else
2034 src->textSrc.undo_state = False0;
2035 XtFree(rbuf);
2036 }
2037 if (undo) {
2038 src->textSrc.undo_state = False0;
2039 if (freepos) {
2040 for (i = 0; i < num_pos; i++) {
2041 TextWidget tw = (TextWidget)src->textSrc.text[i];
2042 tw->text.insertPos = XawMin(XawMax(0, pos[i]), tw->text.lastPos)((((0) > (pos[i]) ? (0) : (pos[i]))) < (tw->text.lastPos
) ? (((0) > (pos[i]) ? (0) : (pos[i]))) : (tw->text.lastPos
))
;
2043 }
2044 XawStackFree(pos, buf)do { if ((pos) != (XtPointer)(buf)) XtFree((char *)pos); } while
(0)
;
2045 }
2046 if (ptr)
2047 XtFree(ptr);
2048 }
2049
2050 return (result);
2051}
2052
2053static int
2054DoFormatText(TextWidget ctx, XawTextPosition left, Boolint force, int level,
2055 XawTextBlock *save, XawTextPosition *pos, int num_pos,
2056 Boolint paragraph)
2057{
2058 XawTextPosition right = SrcScanXawTextSourceScan(ctx->text.source, left, XawstEOL,
2059 XawsdRight, 1, False0);
2060 XawTextPosition position, tmp, ipos;
2061 XawTextBlock block, text;
2062 char buf[128];
2063 wchar_t *wptr;
2064 int i, count, cpos;
2065 Boolint done, force2 = force, recurse = False0;
2066
2067 position = XawTextSourceRead(ctx->text.source, left, &block, right - left);
2068 if (block.length == 0 || left >= right ||
2069 (level == 1 && ((XawTextFormat(ctx, XawFmt8Bit)((unsigned long)_XawTextFormat(ctx) == (XawFmt8Bit)) &&
2070 block.ptr[0] != ' ' &&
2071 block.ptr[0] != '\t' &&
2072 !isalnum(*(unsigned char*)block.ptr)) ||
2073 (XawTextFormat(ctx, XawFmtWide)((unsigned long)_XawTextFormat(ctx) == (XawFmtWide)) &&
2074 _Xaw_atowc(XawSP0x20) != *(wchar_t*)block.ptr &&
2075 _Xaw_atowc(XawTAB0x09) != *(wchar_t*)block.ptr &&
2076 !iswalnum(*(wchar_t*)block.ptr)))))
2077 return (XawEditDone0);
2078
2079 if (level == 1 && !paragraph) {
2080 tmp = ctx->text.lastPos;
2081 if (Untabify(ctx, left, right, pos, num_pos, save) == False0)
2082 return (XawEditError1);
2083 right += ctx->text.lastPos - tmp;
2084 position = XawTextSourceRead(ctx->text.source, left, &block,
2085 right - left);
2086 }
2087
2088 text.firstPos = 0;
2089 text.format = XawFmt8Bit;
2090
2091 ipos = ctx->text.insertPos;
2092 count = 0;
2093 done = False0;
2094 while (!done) {
2095 if (XawTextFormat(ctx, XawFmt8Bit)((unsigned long)_XawTextFormat(ctx) == (XawFmt8Bit))) {
2096 for (i = 0; i < block.length; i++)
2097 if (block.ptr[i] == ' ')
2098 ++count;
2099 else {
2100 done = True1;
2101 break;
2102 }
2103 }
2104 else {
2105 wptr = (wchar_t*)block.ptr;
2106 for (i = 0; i < block.length; i++)
2107 if (wptr[i] == _Xaw_atowc(' '))
2108 ++count;
2109 else {
2110 done = True1;
2111 break;
2112 }
2113 }
2114 tmp = position;
2115 position = XawTextSourceRead(ctx->text.source, position,
2116 &block, right - position);
2117 if (tmp == position)
2118 done = True1;
2119 }
2120 position = left + count;
2121 if (count < ctx->text.left_column) {
2122 int bytes = ctx->text.left_column - count;
2123
2124 text.ptr = XawStackAlloc(bytes, buf)((bytes) <= sizeof(buf) ? (XtPointer)(buf) : XtMalloc((unsigned
)(bytes)))
;
2125 text.length = bytes;
2126 for (i = 0; i < bytes; i++)
2127 text.ptr[i] = ' ';
2128 CHECK_SAVE();
2129 if (_XawTextReplace(ctx, left, left, &text)) {
2130 XawStackFree(text.ptr, buf)do { if ((text.ptr) != (XtPointer)(buf)) XtFree((char *)text.
ptr); } while (0)
;
2131 return (XawEditError1);
2132 }
2133 XawStackFree(text.ptr, buf)do { if ((text.ptr) != (XtPointer)(buf)) XtFree((char *)text.
ptr); } while (0)
;
2134 right += bytes;
2135 if (num_pos) {
2136 for (cpos = 0; cpos < num_pos; cpos++)
2137 if (pos[cpos] >= left)
2138 pos[cpos] += bytes;
2139 }
2140 if (ipos >= left)
2141 ipos += bytes;
2142 count += bytes;
2143 }
2144
2145 done = False0;
2146 if (!paragraph && level == 1
2147 && ipos <= right && ipos - left > ctx->text.right_column) {
2148 XawTextPosition len = ctx->text.lastPos;
2149 int skip = ctx->text.justify == XawjustifyRight
2150 || ctx->text.justify == XawjustifyCenter ?
2151 ctx->text.left_column : count;
2152
2153 if (pos)
2154 for (i = 0; i < num_pos; i++)
2155 if (pos[i] == ipos)
2156 break;
2157
2158 StripSpaces(ctx, left + skip, right, pos, num_pos, save);
2159 right += ctx->text.lastPos - len;
2160 if (pos && i < num_pos)
2161 ipos = pos[i];
2162 else
2163 ipos = ctx->text.insertPos;
2164 done = ipos - left > ctx->text.right_column;
2165 count = skip + (count == skip + 1);
2166 }
2167 if ((paragraph || done) && right - left > ctx->text.right_column) {
2168 position = tmp = right;
2169 XawTextSourceRead(ctx->text.source, position - 1, &block, 1);
2170 if (block.length &&
2171 ((XawTextFormat(ctx, XawFmt8Bit)((unsigned long)_XawTextFormat(ctx) == (XawFmt8Bit)) &&
2172 block.ptr[0] == ' ') ||
2173 (XawTextFormat(ctx, XawFmtWide)((unsigned long)_XawTextFormat(ctx) == (XawFmtWide)) &&
2174 _Xaw_atowc(XawSP0x20) == *(wchar_t*)block.ptr)))
2175 --position;
2176 while (position - left > ctx->text.right_column) {
2177 tmp = position;
2178 position = SrcScanXawTextSourceScan(ctx->text.source, position,
2179 XawstWhiteSpace, XawsdLeft, 1, True1);
2180 }
2181 if (position <= left + ctx->text.left_column)
2182 position = tmp;
2183 if (position > left && position - left > ctx->text.left_column
2184 && position != right) {
2185 text.ptr = "\n";
2186 text.length = 1;
2187 CHECK_SAVE();
2188 if (_XawTextReplace(ctx, position, position + 1, &text))
2189 return (XawEditError1);
2190 right = position;
2191 recurse = True1;
2192 force = True1;
2193 }
2194 }
2195
2196 if (force) {
2197 if (ctx->text.justify == XawjustifyCenter)
2198 count = ctx->text.right_column - (count - ctx->text.left_column);
2199 else
2200 count = ctx->text.right_column;
2201 if (count > right - left)
2202 count -= right - left;
2203 else
2204 count = 0;
2205 }
2206 else
2207 count = 0;
2208 if (count > 0) {
2209 switch (ctx->text.justify) {
2210 case XawjustifyLeft:
2211 break;
2212 case XawjustifyRight:
2213 case XawjustifyCenter:
2214 if (ctx->text.justify == XawjustifyCenter) {
2215 int alnum = 0;
2216
2217 if (!(count & 1)) {
2218 XawTextSourceRead(ctx->text.source, right, &block, 1);
2219 if ((XawTextFormat(ctx, XawFmt8Bit)((unsigned long)_XawTextFormat(ctx) == (XawFmt8Bit))
2220 && isalnum(*(unsigned char*)block.ptr)) ||
2221 (XawTextFormat(ctx, XawFmtWide)((unsigned long)_XawTextFormat(ctx) == (XawFmtWide))
2222 && iswalnum(*(wchar_t*)block.ptr)))
2223 alnum = 1;
2224 }
2225 count = (count + alnum) >> 1;
2226 }
2227 text.ptr = XawStackAlloc(count, buf)((count) <= sizeof(buf) ? (XtPointer)(buf) : XtMalloc((unsigned
)(count)))
;
2228 text.length = count;
2229 for (i = 0; i < count; i++)
2230 text.ptr[i] = ' ';
2231 CHECK_SAVE();
2232 if (_XawTextReplace(ctx, left, left, &text)) {
2233 XawStackFree(text.ptr, buf)do { if ((text.ptr) != (XtPointer)(buf)) XtFree((char *)text.
ptr); } while (0)
;
2234 return (XawEditError1);
2235 }
2236 XawStackFree(text.ptr, buf)do { if ((text.ptr) != (XtPointer)(buf)) XtFree((char *)text.
ptr); } while (0)
;
2237 position += count;
2238 right += count;
2239 if (num_pos) {
2240 for (cpos = 0; cpos < num_pos; cpos++)
2241 if (pos[cpos] > left)
2242 pos[cpos] += count;
2243 }
2244 else if (ipos > left)
2245 ipos += count;
2246 break;
2247 case XawjustifyFull:
2248 i = 0;
2249 tmp = left;
2250 /*CONSTCOND*/
2251 while (True1) {
2252 tmp = SrcScanXawTextSourceScan(ctx->text.source, tmp, XawstWhiteSpace,
2253 XawsdRight, 1, True1);
2254 if (tmp < right)
2255 ++i;
2256 else
2257 break;
2258 }
2259 if (i) {
2260 double inc, ii;
2261 int bytes, steps;
2262
2263 bytes = count;
2264 inc = ii = (count + .5) / (double)i;
2265
2266 steps = count;
2267 text.ptr = XawStackAlloc(steps, buf)((steps) <= sizeof(buf) ? (XtPointer)(buf) : XtMalloc((unsigned
)(steps)))
;
2268 for (i = 0; i < steps; i++)
2269 text.ptr[i] = ' ';
2270 tmp = left;
2271 CHECK_SAVE();
2272 while (bytes) {
2273 steps = 1;
2274 while (inc + ii < 1) {
2275 ++steps;
2276 inc += ii;
2277 }
2278 tmp = SrcScanXawTextSourceScan(ctx->text.source, tmp, XawstWhiteSpace,
2279 XawsdRight, steps, True1);
2280 if (bytes > inc)
2281 text.length = (int)inc;
2282 else
2283 text.length = bytes;
2284 bytes -= text.length;
2285 if (_XawTextReplace(ctx, tmp, tmp, &text)) {
2286 XawStackFree(text.ptr, buf)do { if ((text.ptr) != (XtPointer)(buf)) XtFree((char *)text.
ptr); } while (0)
;
2287 return (XawEditError1);
2288 }
2289 if (num_pos) {
2290 for (cpos = 0; cpos < num_pos; cpos++)
2291 if (tmp <= pos[cpos])
2292 pos[cpos] += text.length;
2293 }
2294 else if (tmp <= ipos)
2295 ipos += text.length;
2296 inc -= (int)inc;
2297 inc += ii;
2298 }
2299 position += count;
2300 right += count;
2301 XawStackFree(text.ptr, buf)do { if ((text.ptr) != (XtPointer)(buf)) XtFree((char *)text.
ptr); } while (0)
;
2302 }
2303 break;
2304 }
2305 }
2306
2307 if (!num_pos)
2308 ctx->text.insertPos = XawMin(ipos, ctx->text.lastPos)((ipos) < (ctx->text.lastPos) ? (ipos) : (ctx->text.
lastPos))
;
2309
2310 return (recurse ? DoFormatText(ctx, position + 1,
2311 ctx->text.justify != XawjustifyFull
2312 && (force2 || paragraph),
2313 ++level, save, pos, num_pos, paragraph)
2314 : XawEditDone0);
2315}
2316#undef CHECK_SAVE
2317
2318/*ARGSUSED*/
2319static void
2320Indent(Widget w, XEvent *event, String *params, Cardinal *num_params)
2321{
2322 TextWidget ctx = (TextWidget)w;
2323 TextSrcObject src = (TextSrcObject)ctx->text.source;
2324 XawTextPosition from, to, tmp, end = 0, *pos, *posbuf[32];
2325 char buf[32];
2326 XawTextBlock text;
2327 int i, spaces = MULT(ctx)(ctx->text.mult == 0 ? 4 : ctx->text.mult == 32767 ? -4
: ctx->text.mult)
;
2328 char *lbuf = NULL((void*)0), *rbuf;
2329 unsigned llen = 0, rlen, size;
2330 Boolint undo = src->textSrc.enable_undo && src->textSrc.undo_state == False0;
2331 Boolint format = ctx->text.auto_fill
2332 && ctx->text.left_column < ctx->text.right_column;
2333
2334 text.firstPos = 0;
2335 text.format = XawFmt8Bit;
2336 text.ptr = "";
2337
2338 StartAction(ctx, event);
2339
2340 pos = XawStackAlloc(sizeof(XawTextPosition) * src->textSrc.num_text, posbuf)((sizeof(XawTextPosition) * src->textSrc.num_text) <= sizeof
(posbuf) ? (XtPointer)(posbuf) : XtMalloc((unsigned)(sizeof(XawTextPosition
) * src->textSrc.num_text)))
;
2341 for (i = 0; i < src->textSrc.num_text; i++)
2342 pos[i] = ((TextWidget)src->textSrc.text[i])->text.insertPos;
2343
2344 if (!GetBlockBoundaries(ctx, &from, &to)) {
2345 EndAction(ctx);
2346 XawStackFree(pos, posbuf)do { if ((pos) != (XtPointer)(posbuf)) XtFree((char *)pos); }
while (0)
;
2347 return;
2348 }
2349
2350 if (undo) {
2351 llen = to - from;
2352 end = ctx->text.lastPos;
2353 lbuf = _XawTextGetText(ctx, from, to);
2354 src->textSrc.undo_state = True1;
2355 }
2356
2357 tmp = ctx->text.lastPos;
2358 if (!Untabify(ctx, from, to, pos, src->textSrc.num_text, NULL((void*)0))) {
2359 XBell(XtDisplay(ctx)(((ctx)->core.screen)->display), 0);
2360 EndAction(ctx);
2361 XawStackFree(pos, posbuf)do { if ((pos) != (XtPointer)(posbuf)) XtFree((char *)pos); }
while (0)
;
2362 if (undo) {
2363 src->textSrc.undo_state = True1;
2364 XtFree(lbuf);
2365 }
2366 return;
2367 }
2368 to += ctx->text.lastPos - tmp;
2369
2370 tmp = from;
2371
2372 if (spaces > 0) {
2373 text.ptr = XawStackAlloc(spaces, buf)((spaces) <= sizeof(buf) ? (XtPointer)(buf) : XtMalloc((unsigned
)(spaces)))
;
2374 for (i = 0; i < spaces; i++)
2375 text.ptr[i] = ' ';
2376
2377 text.length = spaces;
2378 while (tmp < to) {
2379 _XawTextReplace(ctx, tmp, tmp, &text);
2380
2381 for (i = 0; i < src->textSrc.num_text; i++)
2382 if (tmp < pos[i])
2383 pos[i] += spaces;
2384
2385 to += spaces;
2386 tmp = SrcScanXawTextSourceScan(ctx->text.source, tmp, XawstEOL, XawsdRight, 1, True1);
2387 }
2388 XawStackFree(text.ptr, buf)do { if ((text.ptr) != (XtPointer)(buf)) XtFree((char *)text.
ptr); } while (0)
;
2389 }
2390 else {
2391 int min = 32767;
2392
2393 text.length = 0;
2394 tmp = from;
2395
2396 /* find the amount of spaces to cut */
2397 while (tmp < to) {
2398 (void)BlankLine(w, tmp, &i);
2399 if (i < min)
2400 min = i;
2401 tmp = SrcScanXawTextSourceScan(ctx->text.source, tmp, XawstEOL, XawsdRight, 1, True1);
2402 }
2403 spaces = XawMin(-spaces, min)((-spaces) < (min) ? (-spaces) : (min));
2404
2405 /* cut the spaces */
2406 tmp = from;
2407 while (tmp < to) {
2408 _XawTextReplace(ctx, tmp, tmp + spaces, &text);
2409
2410 for (i = 0; i < src->textSrc.num_text; i++)
2411 if (tmp < pos[i]) {
2412 if (tmp + spaces < pos[i])
2413 pos[i] -= spaces;
2414 else
2415 pos[i] = tmp;
2416 }
2417
2418 to -= spaces;
2419 tmp = SrcScanXawTextSourceScan(ctx->text.source, tmp, XawstEOL, XawsdRight, 1, True1);
2420 }
2421 }
2422
2423 if (!format)
2424 Tabify(ctx, from, to, pos, src->textSrc.num_text, NULL((void*)0));
2425
2426 if (undo) {
2427 rlen = llen + (ctx->text.lastPos - end);
2428 rbuf = _XawTextGetText(ctx, from, from + rlen);
2429
2430 text.format = _XawTextFormat(ctx);
2431 size = XawTextFormat(ctx, XawFmtWide)((unsigned long)_XawTextFormat(ctx) == (XawFmtWide)) ? sizeof(wchar_t) : sizeof(char);
2432 if (llen != rlen || memcmp(lbuf, rbuf, llen * size)) {
2433 text.ptr = lbuf;
2434 text.length = llen;
2435 _XawTextReplace(ctx, from, from + rlen, &text);
2436
2437 src->textSrc.undo_state = False0;
2438 text.ptr = rbuf;
2439 text.length = rlen;
2440 _XawTextReplace(ctx, from, from + llen, &text);
2441 }
2442 else
2443 src->textSrc.undo_state = False0;
2444 XtFree(lbuf);
2445 XtFree(rbuf);
2446 }
2447
2448 for (i = 0; i < src->textSrc.num_text; i++) {
2449 TextWidget tw = (TextWidget)src->textSrc.text[i];
2450
2451 tw->text.insertPos = XawMin(XawMax(0, pos[i]), tw->text.lastPos)((((0) > (pos[i]) ? (0) : (pos[i]))) < (tw->text.lastPos
) ? (((0) > (pos[i]) ? (0) : (pos[i]))) : (tw->text.lastPos
))
;
2452 }
2453 XawStackFree(pos, posbuf)do { if ((pos) != (XtPointer)(posbuf)) XtFree((char *)pos); }
while (0)
;
2454 ctx->text.showposition = True1;
2455
2456 EndAction(ctx);
2457}
2458
2459/*ARGSUSED*/
2460static void
2461ToggleOverwrite(Widget w, XEvent *event, String *params, Cardinal *num_params)
2462{
2463 TextWidget ctx = (TextWidget)w;
2464
2465 ctx->text.overwrite = !ctx->text.overwrite;
2466
2467 /* call information callback */
2468 _XawTextSetLineAndColumnNumber(ctx, True1);
2469}
2470#endif /* OLDXAW */
2471
2472/*
2473 * Insertion Routines
2474 */
2475static int
2476InsertNewLineAndBackupInternal(TextWidget ctx)
2477{
2478 int count, error = XawEditDone0, mult = MULT(ctx)(ctx->text.mult == 0 ? 4 : ctx->text.mult == 32767 ? -4
: ctx->text.mult)
;
2479#ifndef OLDXAW
2480 XawTextPosition position;
2481#endif
2482 XawTextBlock text;
2483 char buf[32];
2484
2485 if (mult < 0) {
2486 ctx->text.mult = 1;
2487 return (XawEditError1);
2488 }
2489
2490 text.format = _XawTextFormat(ctx);
2491 text.length = mult;
2492 text.firstPos = 0;
2493
2494 if (text.format == XawFmtWide) {
2495 wchar_t *wptr;
2496
2497 text.ptr = XawStackAlloc(sizeof(wchar_t) * mult, buf)((sizeof(wchar_t) * mult) <= sizeof(buf) ? (XtPointer)(buf
) : XtMalloc((unsigned)(sizeof(wchar_t) * mult)))
;
2498 wptr = (wchar_t *)text.ptr;
2499 for (count = 0; count < mult; count++)
2500 wptr[count] = _Xaw_atowc(XawLF0x0a);
2501 }
2502 else {
2503 text.ptr = XawStackAlloc(sizeof(char) * mult, buf)((sizeof(char) * mult) <= sizeof(buf) ? (XtPointer)(buf) :
XtMalloc((unsigned)(sizeof(char) * mult)))
;
2504 for (count = 0; count < mult; count++)
2505 text.ptr[count] = XawLF0x0a;
2506 }
2507
2508#ifndef OLDXAW
2509 position = SrcScanXawTextSourceScan(ctx->text.source, ctx->text.insertPos,
2510 XawstEOL, XawsdLeft, 1, False0);
2511#endif
2512 if (_XawTextReplace(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) {
2513 XBell( XtDisplay(ctx)(((ctx)->core.screen)->display), 50);
2514 error = XawEditError1;
2515 }
2516 else {
2517 ctx->text.showposition = TRUE1;
2518 ctx->text.insertPos += text.length;
2519 }
2520
2521 XawStackFree(text.ptr, buf)do { if ((text.ptr) != (XtPointer)(buf)) XtFree((char *)text.
ptr); } while (0)
;
2522
2523#ifndef OLDXAW
2524 if (ctx->text.auto_fill && error == XawEditDone0)
2525 (void)FormatText(ctx, position, ctx->text.justify != XawjustifyFull,
2526 NULL((void*)0), 0);
2527#endif
2528
2529 return (error);
2530}
2531
2532/*ARGSUSED*/
2533static void
2534InsertNewLineAndBackup(Widget w, XEvent *event, String *p, Cardinal *n)
2535{
2536 TextWidget ctx = (TextWidget)w;
2537 XawTextPosition insertPos = ctx->text.insertPos;
2538
2539 StartAction((TextWidget)w, event);
2540 (void)InsertNewLineAndBackupInternal(ctx);
2541 ctx->text.insertPos = SrcScanXawTextSourceScan(ctx->text.source, insertPos, XawstEOL,
2542 XawsdRight, 1, False0);
2543 EndAction((TextWidget)w);
2544}
2545
2546static int
2547LocalInsertNewLine(TextWidget ctx, XEvent *event)
2548{
2549 int error;
2550
2551 StartAction(ctx, event);
2552 error = InsertNewLineAndBackupInternal(ctx);
2553 ctx->text.from_left = -1;
2554 EndAction(ctx);
2555
2556 return (error);
2557}
2558
2559/*ARGSUSED*/
2560static void
2561InsertNewLine(Widget w, XEvent *event, String *p, Cardinal *n)
2562{
2563 (void)LocalInsertNewLine((TextWidget)w, event);
2564}
2565
2566/*ARGSUSED*/
2567static void
2568InsertNewLineAndIndent(Widget w, XEvent *event, String *p, Cardinal *n)
2569{
2570 XawTextBlock text;
2571 XawTextPosition pos1;
2572 int length;
2573 TextWidget ctx = (TextWidget)w;
2574 String line_to_ip;
2575
2576 StartAction(ctx, event);
2577 pos1 = SrcScanXawTextSourceScan(ctx->text.source, ctx->text.insertPos,
2578 XawstEOL, XawsdLeft, 1, False0);
2579
2580 line_to_ip = _XawTextGetText(ctx, pos1, ctx->text.insertPos);
2581
2582 text.format = _XawTextFormat(ctx);
2583 text.firstPos = 0;
2584
2585 if (text.format == XawFmtWide) {
2586 wchar_t *ptr;
2587
2588 text.ptr = XtMalloc((2 + wcslen((wchar_t*)line_to_ip))
2589 * sizeof(wchar_t));
2590 ptr = (wchar_t*)text.ptr;
2591 ptr[0] = _Xaw_atowc(XawLF0x0a);
2592 wcscpy((wchar_t*)++ptr, (wchar_t*)line_to_ip);
2593
2594 length = wcslen((wchar_t*)text.ptr);
2595 while (length && (iswspace(*ptr)(isascii(*ptr) && isspace(toascii(*ptr))) || *ptr == _Xaw_atowc(XawTAB0x09)))
2596 ptr++, length--;
2597 *ptr = (wchar_t)0;
2598 text.length = wcslen((wchar_t*)text.ptr);
2599 }
2600 else {
2601 char *ptr;
2602
2603 length = strlen(line_to_ip);
2604 text.ptr = XtMalloc((2 + length) * sizeof(char));
2605 ptr = text.ptr;
2606 ptr[0] = XawLF0x0a;
2607 strcpy(++ptr, line_to_ip)__builtin___strcpy_chk (++ptr, line_to_ip, __builtin_object_size
(++ptr, 2 > 1 ? 1 : 0))
;
2608
2609 length++;
2610 while (length && (isspace(*ptr) || (*ptr == XawTAB0x09)))
2611 ptr++, length--;
2612 *ptr = '\0';
2613 text.length = strlen(text.ptr);
2614 }
2615 XtFree(line_to_ip);
2616
2617 if (_XawTextReplace(ctx,ctx->text.insertPos, ctx->text.insertPos, &text)) {
2618 XBell(XtDisplay(ctx)(((ctx)->core.screen)->display), 50);
2619 XtFree(text.ptr);
2620 EndAction(ctx);
2621 return;
2622 }
2623
2624 XtFree(text.ptr);
2625 ctx->text.from_left = -1;
2626 ctx->text.insertPos = SrcScanXawTextSourceScan(ctx->text.source, ctx->text.old_insert,
2627 XawstPositions, XawsdRight, text.length, True1);
2628 EndAction(ctx);
2629}
2630
2631/*
2632 * Selection Routines
2633 */
2634static void
2635SelectWord(Widget w, XEvent *event, String *params, Cardinal *num_params)
2636{
2637 TextWidget ctx = (TextWidget)w;
2638 XawTextPosition l, r;
2639
2640 StartAction(ctx, event);
2641 l = SrcScanXawTextSourceScan(ctx->text.source, ctx->text.insertPos,
2642 XawstWhiteSpace, XawsdLeft, 1, False0);
2643 r = SrcScanXawTextSourceScan(ctx->text.source, l, XawstWhiteSpace, XawsdRight, 1, False0);
2644 _XawTextSetSelection(ctx, l, r, params, *num_params);
2645 EndAction(ctx);
2646}
2647
2648static void
2649SelectAll(Widget w, XEvent *event, String *params, Cardinal *num_params)
2650{
2651 TextWidget ctx = (TextWidget)w;
2652
2653 StartAction(ctx, event);
2654 _XawTextSetSelection(ctx,zeroPosition((XawTextPosition)0),ctx->text.lastPos,params,*num_params);
2655 EndAction(ctx);
2656}
2657
2658static void
2659ModifySelection(TextWidget ctx, XEvent *event,
2660 XawTextSelectionMode mode,
2661 XawTextSelectionAction action,
2662 String *params, Cardinal *num_params)
2663{
2664#ifndef OLDXAW
2665 int old_y = ctx->text.ev_y;
2666#endif
2667
2668 StartAction(ctx, event);
2669 NotePosition(ctx, event);
2670
2671#ifndef OLDXAW
2672 if (event->type == MotionNotify6) {
2673 if (ctx->text.ev_y <= ctx->text.margin.top) {
2674 if (old_y >= ctx->text.ev_y)
2675 XawTextScroll(ctx, -1, 0);
2676 }
2677 else if (ctx->text.ev_y >= XtHeight(ctx)(((RectObj)ctx)->rectangle.height) - ctx->text.margin.bottom) {
2678 if (old_y <= ctx->text.ev_y
2679 && !IsPositionVisible(ctx, ctx->text.lastPos)(ctx->text.lastPos >= ctx->text.lt.info[0].position &&
ctx->text.lastPos < ctx->text.lt.info[ctx->text.
lt.lines].position)
)
2680 XawTextScroll(ctx, 1, 0);
2681 }
2682 }
2683#endif
2684 ctx->text.from_left = -1;
2685 _XawTextAlterSelection(ctx, mode, action, params, num_params);
2686
2687 EndAction(ctx);
2688}
2689
2690static void
2691SelectStart(Widget w, XEvent *event, String *params, Cardinal *num_params)
2692{
2693 TextWidget ctx = (TextWidget)w;
2694
2695#ifndef OLDXAW
2696 if (!ctx->text.selection_state) {
2697 ctx->text.selection_state = True1;
2698#endif
2699 ModifySelection(ctx, event,
2700 XawsmTextSelect, XawactionStart, params, num_params);
2701#ifndef OLDXAW
2702 }
2703#endif
2704}
2705
2706static void
2707SelectAdjust(Widget w, XEvent *event, String *params, Cardinal *num_params)
2708{
2709 TextWidget ctx = (TextWidget)w;
2710
2711#ifndef OLDXAW
2712 if (ctx->text.selection_state)
2713#endif
2714 ModifySelection(ctx, event,
2715 XawsmTextSelect, XawactionAdjust, params, num_params);
2716}
2717
2718static void
2719SelectEnd(Widget w, XEvent *event, String *params, Cardinal *num_params)
2720{
2721 TextWidget ctx = (TextWidget)w;
2722
2723#ifndef OLDXAW
2724 if (ctx->text.selection_state) {
2725 ctx->text.selection_state = False0;
2726#endif
2727 ModifySelection(ctx, event,
2728 XawsmTextSelect, XawactionEnd, params, num_params);
2729#ifndef OLDXAW
2730 }
2731#endif
2732}
2733
2734static void
2735ExtendStart(Widget w, XEvent *event, String *params, Cardinal *num_params)
2736{
2737 TextWidget ctx = (TextWidget)w;
2738
2739#ifndef OLDXAW
2740 if (!ctx->text.selection_state) {
2741 ctx->text.selection_state = True1;
2742#endif
2743 ModifySelection(ctx, event,
2744 XawsmTextExtend, XawactionStart, params, num_params);
2745#ifndef OLDXAW
2746 }
2747#endif
2748}
2749
2750static void
2751ExtendAdjust(Widget w, XEvent *event, String *params, Cardinal *num_params)
2752{
2753 TextWidget ctx = (TextWidget)w;
2754
2755#ifndef OLDXAW
2756 if (ctx->text.selection_state)
2757#endif
2758 ModifySelection(ctx, event,
2759 XawsmTextExtend, XawactionAdjust, params, num_params);
2760}
2761
2762static void
2763ExtendEnd(Widget w, XEvent *event, String *params, Cardinal *num_params)
2764{
2765 TextWidget ctx = (TextWidget)w;
2766
2767#ifndef OLDXAW
2768 if (ctx->text.selection_state) {
2769 ctx->text.selection_state = False0;
2770#endif
2771 ModifySelection(ctx, event,
2772 XawsmTextExtend, XawactionEnd, params, num_params);
2773#ifndef OLDXAW
2774 }
2775#endif
2776}
2777
2778static void
2779SelectSave(Widget w, XEvent *event, String *params, Cardinal *num_params)
2780{
2781 int num_atoms;
2782 Atom *sel;
2783 Display *dpy = XtDisplay(w)(((w)->core.screen)->display);
2784 Atom selections[256];
2785
2786 StartAction((TextWidget)w, event);
2787 num_atoms = *num_params;
2788 if (num_atoms > 256)
2789 num_atoms = 256;
2790 for (sel=selections; --num_atoms >= 0; sel++, params++)
2791 *sel = XInternAtom(dpy, *params, False0);
2792 num_atoms = *num_params;
2793 _XawTextSaltAwaySelection((TextWidget)w, selections, num_atoms);
2794 EndAction((TextWidget)w);
2795}
2796
2797/*
2798 * Misc. Routines
2799 */
2800/*ARGSUSED*/
2801static void
2802SetKeyboardFocus(Widget w, XEvent *event, String *params, Cardinal *num_params)
2803{
2804 Widget shell, parent;
2805
2806 shell = parent = w;
2807 while (parent) {
2808 if (XtIsShell(shell = parent)(((Object)(shell = parent))->object.widget_class->core_class
.class_inited & 0x20)
)
2809 break;
2810 parent = XtParent(parent)((parent)->core.parent);
2811 }
2812 XtSetKeyboardFocus(shell, w);
2813}
2814
2815/*ARGSUSED*/
2816static void
2817RedrawDisplay(Widget w, XEvent *event, String *p, Cardinal *n)
2818{
2819 StartAction((TextWidget)w, event);
2820 _XawTextClearAndCenterDisplay((TextWidget)w);
2821 EndAction((TextWidget)w);
2822}
2823
2824/* This is kind of a hack, but, only one text widget can have focus at
2825 * a time on one display. There is a problem in the implementation of the
2826 * text widget, the scrollbars can not be adressed via editres, since they
2827 * are not children of a subclass of composite.
2828 * The focus variable is required to make sure only one text window will
2829 * show a block cursor at one time.
2830 */
2831struct _focus { Display *display; Widget widget; };
2832static struct _focus *focus;
2833static Cardinal num_focus;
2834
2835/*ARGSUSED*/
2836static void
2837DestroyFocusCallback(Widget w, XtPointer user_data, XtPointer call_data)
2838{
2839 struct _focus *f = (struct _focus*)(user_data);
2840
2841 if (f->widget == w)
2842 f->widget = NULL((void*)0);
2843}
2844
2845/*ARGSUSED*/
2846static void
2847TextFocusIn(Widget w, XEvent *event, String *p, Cardinal *n)
2848{
2849 TextWidget ctx = (TextWidget)w;
2850 Boolint display_caret = ctx->text.display_caret;
2851 int i;
2852
2853 if (event->xfocus.detail == NotifyPointer5)
2854 return;
2855
2856 if (event->xfocus.send_event) {
2857 Window root, child;
2858 int rootx, rooty, x, y;
2859 unsigned int mask;
2860
2861 if (ctx->text.hasfocus)
2862 return;
2863
2864 if (XQueryPointer(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window), &root, &child,
2865 &rootx, &rooty, &x, &y, &mask)) {
2866 if (child)
2867 return;
2868 }
2869 }
2870
2871 /* Let the input method know focus has arrived. */
2872 _XawImSetFocusValues(w, NULL((void*)0), 0);
2873
2874 if (display_caret)
2875 StartAction(ctx, event);
2876 ctx->text.hasfocus = TRUE1;
2877 if (display_caret)
2878 EndAction(ctx);
2879
2880 for (i = 0; i < num_focus; i++)
2881 if (focus[i].display == XtDisplay(w)(((w)->core.screen)->display))
2882 break;
2883 if (i >= num_focus) {
2884 focus = (struct _focus*)
2885 XtRealloc((XtPointer)focus, sizeof(struct _focus) * (num_focus + 1));
2886 i = num_focus;
2887 focus[i].widget = NULL((void*)0);
2888 focus[i].display = XtDisplay(w)(((w)->core.screen)->display);
2889 num_focus++;
2890 }
2891 if (focus[i].widget != w) {
2892 Widget old = focus[i].widget;
2893
2894 focus[i].widget = w;
2895 if (old != NULL((void*)0)) {
2896 TextFocusOut(old, event, p, n);
2897 /* TextFocusOut may set it to NULL */
2898 focus[i].widget = w;
2899 }
2900 XtAddCallback(w, XtNdestroyCallback((char*)&XtStrings[169]),
2901 DestroyFocusCallback, (XtPointer)&focus[i]);
2902 }
2903}
2904
2905/*ARGSUSED*/
2906static void
2907TextFocusOut(Widget w, XEvent *event, String *p, Cardinal *n)
2908{
2909 TextWidget ctx = (TextWidget)w;
2910 Boolint display_caret = ctx->text.display_caret;
2911 Widget shell;
2912 Window window;
2913 int i, revert;
2914
2915 shell = w;
2916 while (shell) {
2917 if (XtIsShell(shell)(((Object)(shell))->object.widget_class->core_class.class_inited
& 0x20)
)
2918 break;
2919 shell = XtParent(shell)((shell)->core.parent);
2920 }
2921
2922 for (i = 0; i < num_focus; i++)
2923 if (focus[i].display == XtDisplay(w)(((w)->core.screen)->display))
2924 break;
2925 XGetInputFocus(XtDisplay(w)(((w)->core.screen)->display), &window, &revert);
2926 if ((XtWindow(shell)((shell)->core.window) == window &&
2927 (i < num_focus && focus[i].widget == w))
2928 || event->xfocus.detail == NotifyPointer5)
2929 return;
2930
2931 if (i < num_focus && focus[i].widget) {
2932 XtRemoveCallback(focus[i].widget, XtNdestroyCallback((char*)&XtStrings[169]),
2933 DestroyFocusCallback, (XtPointer)&focus[i]);
2934 focus[i].widget = NULL((void*)0);
2935 }
2936
2937 /* Let the input method know focus has left.*/
2938 _XawImUnsetFocus(w);
2939
2940 if (display_caret)
2941 StartAction(ctx, event);
2942 ctx->text.hasfocus = FALSE0;
2943 if (display_caret)
2944 EndAction(ctx);
2945}
2946
2947/*ARGSUSED*/
2948static void
2949TextEnterWindow(Widget w, XEvent *event, String *params, Cardinal *num_params)
2950{
2951 TextWidget ctx = (TextWidget)w;
2952
2953 if ((event->xcrossing.detail != NotifyInferior2) && event->xcrossing.focus
2954 && !ctx->text.hasfocus)
2955 _XawImSetFocusValues(w, NULL((void*)0), 0);
2956}
2957
2958/*ARGSUSED*/
2959static void
2960TextLeaveWindow(Widget w, XEvent *event, String *params, Cardinal *num_params)
2961{
2962 TextWidget ctx = (TextWidget)w;
2963
2964 if ((event->xcrossing.detail != NotifyInferior2) && event->xcrossing.focus
2965 && !ctx->text.hasfocus)
2966 _XawImUnsetFocus(w);
2967}
2968
2969/*
2970 * Function:
2971 * AutoFill
2972 * Arguments: ctx - The text widget.
2973 *
2974 * Description:
2975 * Breaks the line at the previous word boundry when
2976 * called inside InsertChar.
2977 */
2978static void
2979AutoFill(TextWidget ctx)
2980{
2981 int width, height, x, line_num, max_width;
2982 XawTextPosition ret_pos;
2983 XawTextBlock text;
2984 XRectangle cursor;
2985 wchar_t wc_buf[2];
2986
2987 for (line_num = 0; line_num < ctx->text.lt.lines ; line_num++)
2988 if (ctx->text.lt.info[line_num].position >= ctx->text.insertPos)
2989 break;
2990 if (line_num)
2991 line_num--; /* backup a line. */
2992
2993 XawTextSinkGetCursorBounds(ctx->text.sink, &cursor);
2994 max_width = Max(0, (int)XtWidth(ctx) - RHMargins(ctx) - cursor.width)(((0) > ((int)(((RectObj)ctx)->rectangle.width) - ((ctx
)->text.r_margin.left + (ctx)->text.r_margin.right) - cursor
.width)) ? (0) : ((int)(((RectObj)ctx)->rectangle.width) -
((ctx)->text.r_margin.left + (ctx)->text.r_margin.right
) - cursor.width))
;
2995
2996 x = ctx->text.r_margin.left;
2997 XawTextSinkFindPosition(ctx->text.sink, ctx->text.lt.info[line_num].position,
2998 x, max_width, True1, &ret_pos,
2999 &width, &height);
3000
3001 if (ret_pos <= ctx->text.lt.info[line_num].position
3002 || ret_pos >= ctx->text.insertPos || ret_pos < 1)
3003 return;
3004
3005 XawTextSourceRead(ctx->text.source, ret_pos - 1, &text, 1);
3006
3007 if (XawTextFormat(ctx, XawFmtWide)((unsigned long)_XawTextFormat(ctx) == (XawFmtWide))) {
3008 wc_buf[0] = *(wchar_t *)text.ptr;
3009 if (wc_buf[0] != _Xaw_atowc(XawSP0x20) && wc_buf[0] != _Xaw_atowc(XawTAB0x09))
3010 /* Only eats white spaces */
3011 return;
3012
3013 text.format = XawFmtWide;
3014 text.ptr = (char *)wc_buf;
3015 wc_buf[0] = _Xaw_atowc(XawLF0x0a);
3016 wc_buf[1] = 0;
3017 }
3018 else {
3019 if (text.ptr[0] != XawSP0x20 && text.ptr[0] != XawTAB0x09)
3020 /* Only eats white spaces */
3021 return;
3022
3023 text.format = XawFmt8Bit;
3024 text.ptr = "\n";
3025 }
3026 text.length = 1;
3027 text.firstPos = 0;
3028
3029 if (_XawTextReplace(ctx, ret_pos - 1, ret_pos, &text))
3030 XBell(XtDisplay((Widget)ctx)((((Widget)ctx)->core.screen)->display), 0);
3031
3032 if (++ctx->text.insertPos > ctx->text.lastPos)
3033 ctx->text.insertPos = ctx->text.lastPos;
3034}
3035
3036/*ARGSUSED*/
3037static void
3038InsertChar(Widget w, XEvent *event, String *p, Cardinal *n)
3039{
3040 TextWidget ctx = (TextWidget)w;
3041 char *ptr, strbuf[128], ptrbuf[512];
3042 int count, error, mult = MULT(ctx)(ctx->text.mult == 0 ? 4 : ctx->text.mult == 32767 ? -4
: ctx->text.mult)
;
3043 KeySym keysym;
3044 XawTextBlock text;
3045#ifndef OLDXAW
3046 Boolint format = False0;
3047#endif
3048 XawTextPosition from, to;
3049
3050 if (XtIsSubclass (ctx->text.source, (WidgetClass) multiSrcObjectClass))
3051 text.length = _XawImWcLookupString(w, &event->xkey, (wchar_t*)strbuf,
3052 sizeof(strbuf), &keysym);
3053 else
3054 text.length = _XawLookupString(w, (XKeyEvent*)event, strbuf,
3055 sizeof(strbuf), &keysym);
3056
3057 if (text.length == 0)
3058 return;
3059
3060 if (mult < 0) {
3061 ctx->text.mult = 1;
3062 return;
3063 }
3064
3065 text.format = _XawTextFormat(ctx);
3066 if (text.format == XawFmtWide) {
3067 text.ptr = ptr = XawStackAlloc(sizeof(wchar_t) * text.length((sizeof(wchar_t) * text.length * mult) <= sizeof(ptrbuf) ?
(XtPointer)(ptrbuf) : XtMalloc((unsigned)(sizeof(wchar_t) * text
.length * mult)))
3068 * mult, ptrbuf)((sizeof(wchar_t) * text.length * mult) <= sizeof(ptrbuf) ?
(XtPointer)(ptrbuf) : XtMalloc((unsigned)(sizeof(wchar_t) * text
.length * mult)))
;
3069 for (count = 0; count < mult; count++) {
3070 memcpy((char*)ptr, (char *)strbuf, sizeof(wchar_t) * text.length)__builtin___memcpy_chk ((char*)ptr, (char *)strbuf, sizeof(wchar_t
) * text.length, __builtin_object_size ((char*)ptr, 0))
;
3071 ptr += sizeof(wchar_t) * text.length;
3072 }
3073#ifndef OLDXAW
3074 if (mult == 1)
3075 format = ctx->text.left_column < ctx->text.right_column;
3076#endif
3077 }
3078 else { /* == XawFmt8Bit */
3079 text.ptr = ptr = XawStackAlloc(text.length * mult, ptrbuf)((text.length * mult) <= sizeof(ptrbuf) ? (XtPointer)(ptrbuf
) : XtMalloc((unsigned)(text.length * mult)))
;
3080 for (count = 0; count < mult; count++) {
3081 strncpy(ptr, strbuf, text.length)__builtin___strncpy_chk (ptr, strbuf, text.length, __builtin_object_size
(ptr, 2 > 1 ? 1 : 0))
;
3082 ptr += text.length;
3083 }
3084#ifndef OLDXAW
3085 if (mult == 1)
3086 format = ctx->text.left_column < ctx->text.right_column;
3087#endif
3088 }
3089
3090 text.length = text.length * mult;
3091 text.firstPos = 0;
3092
3093 StartAction(ctx, event);
3094#ifndef OLDXAW
3095 if (mult == 1)
3096 _XawSourceSetUndoMerge((TextSrcObject)ctx->text.source, True1);
3097#endif
3098
3099 from = ctx->text.insertPos;
3100#ifndef OLDXAW
3101 if (ctx->text.overwrite) {
3102 XawTextPosition tmp;
3103
3104 to = from + mult;
3105 tmp = SrcScanXawTextSourceScan(ctx->text.source, from, XawstEOL, XawsdRight, 1, False0);
3106 if (to > tmp)
3107 to = tmp;
3108 }
3109 else
3110#endif
3111 to = from;
3112
3113 error = _XawTextReplace(ctx, from , to, &text);
3114
3115 if (error == XawEditDone0) {
3116 ctx->text.from_left = -1;
3117 ctx->text.insertPos = SrcScanXawTextSourceScan(ctx->text.source, ctx->text.old_insert,
3118 XawstPositions, XawsdRight,
3119 text.length, True1);
3120 if (ctx->text.auto_fill) {
3121#ifndef OLDXAW
3122 if (format)
3123 (void)FormatText(ctx, SrcScanXawTextSourceScan(ctx->text.source,
3124 ctx->text.insertPos, XawstEOL,
3125 XawsdLeft, 1, False0), False0,
3126 NULL((void*)0), 0);
3127 else
3128#endif
3129 AutoFill(ctx);
3130 }
3131 }
3132 else
3133 XBell(XtDisplay(ctx)(((ctx)->core.screen)->display), 50);
3134
3135 XawStackFree(text.ptr, ptrbuf)do { if ((text.ptr) != (XtPointer)(ptrbuf)) XtFree((char *)text
.ptr); } while (0)
;
3136 EndAction(ctx);
3137
3138 if (error == XawEditDone0 && text.format == XawFmt8Bit && text.length == 1
3139 && (text.ptr[0] == ')' || text.ptr[0] == ']' || text.ptr[0] == '}')
3140 && ctx->text.display_caret) {
3141 static struct timeval tmval = {0, 500000};
3142 fd_set fds;
3143 Widget source = ctx->text.source;
3144 XawTextPosition insertPos = ctx->text.insertPos, pos, tmp, last;
3145 char left, right = text.ptr[0];
3146 int level = 0;
3147 XtAppContext app_context = XtWidgetToApplicationContext(w);
3148
3149 left = right == ')' ? '(' : right == ']' ? '[' : '{';
3150
3151 last = insertPos - 1;
3152 do {
3153 text.ptr[0] = left;
3154 pos = XawTextSourceSearch(source, last, XawsdLeft, &text);
3155 if (pos == XawTextSearchError(-12345L) || !IsPositionVisible(ctx, pos)(pos >= ctx->text.lt.info[0].position && pos <
ctx->text.lt.info[ctx->text.lt.lines].position)
)
3156 return;
3157 text.ptr[0] = right;
3158 tmp = pos;
3159 do {
3160 tmp = XawTextSourceSearch(source, tmp, XawsdRight, &text);
3161 if (tmp == XawTextSearchError(-12345L))
3162 return;
3163 if (tmp <= last)
3164 ++level;
3165 } while (++tmp <= last);
3166 --level;
3167 last = pos;
3168 } while (level);
3169
3170 StartAction(ctx, NULL((void*)0));
3171#ifndef OLDXAW
3172 _XawSourceSetUndoMerge((TextSrcObject)ctx->text.source, True1);
3173#endif
3174 ctx->text.insertPos = pos;
3175 EndAction(ctx);
3176
3177 XSync(XtDisplay(w)(((w)->core.screen)->display), False0);
3178 while (XtAppPending(app_context) & XtIMXEvent1) {
3179 XEvent ev;
3180 if (! XtAppPeekEvent(app_context, &ev))
3181 break;
3182 if (ev.type == KeyPress2 || ev.type == ButtonPress4)
3183 break;
3184 XtAppProcessEvent(app_context, XtIMXEvent1);
3185 }
3186 FD_ZERO(&fds)__builtin_bzero(&fds, sizeof(*(&fds)));
3187 FD_SET(ConnectionNumber(XtDisplay(w)), &fds)do { int __fd = ((((_XPrivDisplay)((((w)->core.screen)->
display)))->fd)); ((&fds)->fds_bits[(unsigned long)
__fd/(sizeof(__int32_t) * 8)] |= ((__int32_t)(1<<((unsigned
long)__fd % (sizeof(__int32_t) * 8))))); } while(0)
;
3188 (void)select(FD_SETSIZE1024, &fds, NULL((void*)0), NULL((void*)0), &tmval);
3189 if (tmval.tv_usec != 500000)
3190 usleep(40000);
3191
3192 StartAction(ctx, NULL((void*)0));
3193#ifndef OLDXAW
3194 _XawSourceSetUndoMerge((TextSrcObject)ctx->text.source, True1);
3195#endif
3196 ctx->text.insertPos = insertPos;
3197 EndAction(ctx);
3198 }
3199}
3200
3201/* IfHexConvertHexElseReturnParam() - called by InsertString
3202 *
3203 * i18n requires the ability to specify multiple characters in a hexa-
3204 * decimal string at once. Since Insert was already too long, I made
3205 * this a seperate routine.
3206 *
3207 * A legal hex string in MBNF: '0' 'x' ( HEX-DIGIT HEX-DIGIT )+ '\0'
3208 *
3209 * WHEN: the passed param is a legal hex string
3210 * RETURNS: a pointer to that converted, null terminated hex string;
3211 * len_return holds the character count of conversion result
3212 *
3213 * WHEN: the passed param is not a legal hex string:
3214 * RETURNS: the parameter passed;
3215 * len_return holds the char count of param.
3216 *
3217 * NOTE: In neither case will there be strings to free. */
3218static char *
3219IfHexConvertHexElseReturnParam(char *param, int *len_return)
3220{
3221 char *p; /* steps through param char by char */
3222 char c; /* holds the character pointed to by p */
3223 int ind; /* steps through hexval buffer char by char */
3224 static char hexval[XawTextActionMaxHexChars100];
3225 Boolean first_digit;
3226
3227 /* reject if it doesn't begin with 0x and at least one more character. */
3228 if ((param[0] != '0') || (param[1] != 'x') || (param[2] == '\0')) {
3229 *len_return = strlen(param);
3230 return(param);
3231 }
3232
3233 /* Skip the 0x; go character by character shifting and adding. */
3234 first_digit = True1;
3235 ind = 0;
3236 hexval[ind] = '\0';
3237
3238 for (p = param+2; (c = *p) != '\0'; p++) {
3239 hexval[ind] *= 16;
3240 if (c >= '0' && c <= '9')
3241 hexval[ind] += c - '0';
3242 else if (c >= 'a' && c <= 'f')
3243 hexval[ind] += c - 'a' + 10;
3244 else if (c >= 'A' && c <= 'F')
3245 hexval[ind] += c - 'A' + 10;
3246 else
3247 break;
3248
3249 /* If we didn't break in preceding line, it was a good hex char. */
3250 if (first_digit)
3251 first_digit = False0;
3252 else {
3253 first_digit = True1;
3254 if (++ind < XawTextActionMaxHexChars100)
3255 hexval[ind] = '\0';
3256 else {
3257 *len_return = strlen(param);
3258 return(param);
3259 }
3260 }
3261 }
3262
3263 /* We quit the above loop becasue we hit a non hex. If that char is \0... */
3264 if ((c == '\0') && first_digit) {
3265 *len_return = strlen(hexval);
3266 return (hexval); /* ...it was a legal hex string, so return it */
3267 }
3268
3269 /* Else, there were non-hex chars or odd digit count, so... */
3270
3271 *len_return = strlen(param);
3272 return (param); /* ...return the verbatim string. */
3273}
3274
3275/* InsertString() - action
3276 *
3277 * Mostly rewritten for R6 i18n.
3278 *
3279 * Each parameter, in turn, will be insert at the inputPos
3280 * and the inputPos advances to the insertion's end.
3281 *
3282 * The exception is that parameters composed of the two
3283 * characters 0x, followed only by an even number of
3284 * hexadecimal digits will be converted to characters */
3285/*ARGSUSED*/
3286static void
3287InsertString(Widget w, XEvent *event, String *params, Cardinal *num_params)
3288{
3289 TextWidget ctx = (TextWidget)w;
3290 XtAppContext app_con = XtWidgetToApplicationContext(w);
3291 XawTextBlock text;
3292 int i;
3293
3294 text.firstPos = 0;
3295 text.format = _XawTextFormat(ctx);
3296
3297 StartAction(ctx, event);
3298 for (i = *num_params; i; i--, params++) { /* DO FOR EACH PARAMETER */
3299 text.ptr = IfHexConvertHexElseReturnParam(*params, &text.length);
3300
3301 if (text.length == 0)
3302 continue;
3303
3304 if (XawTextFormat(ctx, XawFmtWide)((unsigned long)_XawTextFormat(ctx) == (XawFmtWide))) { /* convert to WC */
3305 int temp_len;
3306
3307 text.ptr = (char*)_XawTextMBToWC(XtDisplay(w)(((w)->core.screen)->display), text.ptr,
3308 &text.length);
3309
3310 if (text.ptr == NULL((void*)0)) { /* conversion error */
3311 XtAppWarningMsg(app_con,
3312 "insertString", "textAction", "XawError",
3313 "insert-string()'s parameter contents "
3314 "not legal in this locale.",
3315 NULL((void*)0), NULL((void*)0));
3316 ParameterError(w, *params);
3317 continue;
3318 }
3319
3320 /* Double check that the new input is legal: try to convert to MB. */
3321
3322 temp_len = text.length; /* _XawTextWCToMB's 3rd arg is in_out */
3323 if (_XawTextWCToMB(XtDisplay(w)(((w)->core.screen)->display), (wchar_t*)text.ptr, &temp_len)
3324 == NULL((void*)0)) {
3325 XtAppWarningMsg( app_con,
3326 "insertString", "textAction", "XawError",
3327 "insert-string()'s parameter contents "
3328 "not legal in this locale.",
3329 NULL((void*)0), NULL((void*)0));
3330 ParameterError(w, *params);
3331 continue;
3332 }
3333 } /* convert to WC */
3334
3335 if (_XawTextReplace(ctx, ctx->text.insertPos,
3336 ctx->text.insertPos, &text)) {
3337 XBell(XtDisplay(ctx)(((ctx)->core.screen)->display), 50);
3338 EndAction(ctx);
3339 return;
3340 }
3341
3342 ctx->text.from_left = -1;
3343 /* Advance insertPos to the end of the string we just inserted. */
3344 ctx->text.insertPos = SrcScanXawTextSourceScan(ctx->text.source, ctx->text.old_insert,
3345 XawstPositions, XawsdRight, text.length,
3346 True1);
3347
3348 } /* DO FOR EACH PARAMETER */
3349
3350 EndAction(ctx);
3351}
3352
3353/* DisplayCaret() - action
3354 *
3355 * The parameter list should contain one boolean value. If the
3356 * argument is true, the cursor will be displayed. If false, not.
3357 *
3358 * The exception is that EnterNotify and LeaveNotify events may
3359 * have a second argument, "always". If they do not, the cursor
3360 * is only affected if the focus member of the event is true. */
3361static void
3362DisplayCaret(Widget w, XEvent *event, String *params, Cardinal *num_params)
3363{
3364 TextWidget ctx = (TextWidget)w;
3365 Boolint display_caret = True1;
3366
3367 if ((event->type == EnterNotify7 || event->type == LeaveNotify8)
3368 && ((*num_params >= 2) && (strcmp(params[1], "always") == 0))
3369 && (!event->xcrossing.focus))
3370 return;
3371
3372 if (*num_params > 0) { /* default arg is "True" */
3373 XrmValue from, to;
3374 from.size = strlen(from.addr = params[0]);
3375 XtConvert(w, XtRString((char*)&XtStrings[1797]), &from, XtRBoolean((char*)&XtStrings[1561]), &to);
3376
3377 if (to.addr != NULL((void*)0))
3378 display_caret = *(Boolean*)to.addr;
3379 if (ctx->text.display_caret == display_caret)
3380 return;
3381 }
3382 StartAction(ctx, event);
3383 ctx->text.display_caret = display_caret;
3384 EndAction(ctx);
3385}
3386
3387#ifndef OLDXAW
3388static void
3389Numeric(Widget w, XEvent *event, String *params, Cardinal *num_params)
3390{
3391 TextWidget ctx = (TextWidget)w;
3392
3393 if (ctx->text.numeric) {
3394 long mult = ctx->text.mult;
3395
3396 if (*num_params != 1 || strlen(params[0]) != 1
3397 || (!isdigit(params[0][0])
3398 && (params[0][0] != '-' || mult != 0))) {
3399 char err_buf[256];
3400
3401 if (event && (event->type == KeyPress2 || event->type == KeyRelease3)
3402 && params[0][0] == '-') {
3403 InsertChar(w, event, params, num_params);
3404 return;
3405 }
3406 snprintf(err_buf, sizeof(err_buf),__builtin___snprintf_chk (err_buf, sizeof(err_buf), 0, __builtin_object_size
(err_buf, 2 > 1 ? 1 : 0), "numeric: Invalid argument%s'%s'"
, *num_params ? ", " : "", *num_params ? params[0] : "")
3407 "numeric: Invalid argument%s'%s'",__builtin___snprintf_chk (err_buf, sizeof(err_buf), 0, __builtin_object_size
(err_buf, 2 > 1 ? 1 : 0), "numeric: Invalid argument%s'%s'"
, *num_params ? ", " : "", *num_params ? params[0] : "")
3408 *num_params ? ", " : "",__builtin___snprintf_chk (err_buf, sizeof(err_buf), 0, __builtin_object_size
(err_buf, 2 > 1 ? 1 : 0), "numeric: Invalid argument%s'%s'"
, *num_params ? ", " : "", *num_params ? params[0] : "")
3409 *num_params ? params[0] : "")__builtin___snprintf_chk (err_buf, sizeof(err_buf), 0, __builtin_object_size
(err_buf, 2 > 1 ? 1 : 0), "numeric: Invalid argument%s'%s'"
, *num_params ? ", " : "", *num_params ? params[0] : "")
;
3410 XtAppWarning(XtWidgetToApplicationContext(w), err_buf);
3411 ctx->text.numeric = False0;
3412 ctx->text.mult = 1;
3413 return;
3414 }
3415 if (params[0][0] == '-') {
3416 ctx->text.mult = 32767;
3417 return;
3418 }
3419 else if (mult == 32767) {
3420 mult = ctx->text.mult = - (params[0][0] - '0');
3421 return;
3422 }
3423 else {
3424 mult = mult * 10 + (params[0][0] - '0') * (mult < 0 ? -1 : 1);
3425 ctx->text.mult = ctx->text.mult * 10 + (params[0][0] - '0') *
3426 (mult < 0 ? -1 : 1);
3427 }
3428 if (mult != ctx->text.mult || mult >= 32767) { /* checks for overflow */
3429 XBell(XtDisplay(w)(((w)->core.screen)->display), 0);
3430 ctx->text.mult = 1;
3431 ctx->text.numeric = False0;
3432 return;
3433 }
3434 }
3435 else
3436 InsertChar(w, event, params, num_params);
3437}
3438
3439/*ARGSUSED*/
3440static void
3441KeyboardReset(Widget w, XEvent *event, String *params, Cardinal *num_params)
3442{
3443 TextWidget ctx = (TextWidget)w;
3444
3445 ctx->text.numeric = False0;
3446 ctx->text.mult = 1;
3447
3448 (void)_XawTextSrcToggleUndo((TextSrcObject)ctx->text.source);
3449
3450 if (ctx->text.kill_ring_ptr) {
3451 --ctx->text.kill_ring_ptr->refcount;
3452 ctx->text.kill_ring_ptr = NULL((void*)0);
3453 }
3454 ctx->text.kill_ring = 0;
3455
3456 XBell(XtDisplay(w)(((w)->core.screen)->display), 0);
3457}
3458#endif /* OLDXAW */
3459
3460/* Multiply() - action
3461 *
3462 * The parameter list may contain either a number or the string 'Reset'.
3463 *
3464 * A number will multiply the current multiplication factor by that number.
3465 * Many of the text widget actions will will perform n actions, where n is
3466 * the multiplication factor.
3467 *
3468 * The string reset will reset the mutiplication factor to 1. */
3469/*ARGSUSED*/
3470static void
3471Multiply(Widget w, XEvent *event, String *params, Cardinal *num_params)
3472{
3473 TextWidget ctx = (TextWidget)w;
3474 int mult;
3475
3476 if (*num_params != 1) {
3477 XtAppError(XtWidgetToApplicationContext(w),
3478 "Xaw Text Widget: multiply() takes exactly one argument.");
3479 XBell(XtDisplay(w)(((w)->core.screen)->display), 0);
3480 return;
3481 }
3482
3483 if ((params[0][0] == 'r') || (params[0][0] == 'R')) {
3484 XBell(XtDisplay(w)(((w)->core.screen)->display), 0);
3485#ifndef OLDXAW
3486 ctx->text.numeric = False0;
3487#endif
3488 ctx->text.mult = 1;
3489 return;
3490 }
3491
3492#ifndef OLDXAW
3493 if (params[0][0] == 's' || params[0][0] == 'S') {
3494 ctx->text.numeric = True1;
3495 ctx->text.mult = 0;
3496 return;
3497 }
3498 else
3499#endif
3500 if ((mult = atoi(params[0])) == 0) {
3501 char buf[BUFSIZ1024];
3502
3503 snprintf(buf, sizeof(buf),__builtin___snprintf_chk (buf, sizeof(buf), 0, __builtin_object_size
(buf, 2 > 1 ? 1 : 0), "Xaw Text Widget: multiply() argument "
"must be a number greater than zero, or 'Reset'.")
3504 "Xaw Text Widget: multiply() argument "__builtin___snprintf_chk (buf, sizeof(buf), 0, __builtin_object_size
(buf, 2 > 1 ? 1 : 0), "Xaw Text Widget: multiply() argument "
"must be a number greater than zero, or 'Reset'.")
3505 "must be a number greater than zero, or 'Reset'.")__builtin___snprintf_chk (buf, sizeof(buf), 0, __builtin_object_size
(buf, 2 > 1 ? 1 : 0), "Xaw Text Widget: multiply() argument "
"must be a number greater than zero, or 'Reset'.")
;
3506 XtAppError(XtWidgetToApplicationContext(w), buf);
3507 XBell(XtDisplay(w)(((w)->core.screen)->display), 50);
3508 return;
3509 }
3510
3511 ctx->text.mult *= mult;
3512}
3513
3514/* StripOutOldCRs() - called from FormRegion
3515 *
3516 * removes CRs in widget ctx, from from to to.
3517 *
3518 * RETURNS: the new ending location (we may add some characters),
3519 * or XawReplaceError if the widget can't be written to. */
3520static XawTextPosition
3521StripOutOldCRs(TextWidget ctx, XawTextPosition from, XawTextPosition to,
3522 XawTextPosition *pos, int num_pos)
3523{
3524 XawTextPosition startPos, endPos, eop_begin, eop_end, temp;
3525 Widget src = ctx->text.source;
3526 XawTextBlock text;
3527 char *buf;
3528 static wchar_t wc_two_spaces[3];
3529 int idx;
3530
3531 /* Initialize our TextBlock with two spaces. */
3532 text.firstPos = 0;
3533 text.format = _XawTextFormat(ctx);
3534 if (text.format == XawFmt8Bit)
3535 text.ptr= " ";
3536 else {
3537 wc_two_spaces[0] = _Xaw_atowc(XawSP0x20);
3538 wc_two_spaces[1] = _Xaw_atowc(XawSP0x20);
3539 wc_two_spaces[2] = 0;
3540 text.ptr = (char*)wc_two_spaces;
3541 }
3542
3543 /* Strip out CR's. */
3544 eop_begin = eop_end = startPos = endPos = from;
3545
3546 /* CONSTCOND */
3547 while (TRUE1) {
3548 endPos=SrcScanXawTextSourceScan(src, startPos, XawstEOL, XawsdRight, 1, False0);
3549
3550 temp = SrcScanXawTextSourceScan(src, endPos, XawstWhiteSpace, XawsdLeft, 1, False0);
3551 temp = SrcScanXawTextSourceScan(src, temp, XawstWhiteSpace, XawsdRight,1, False0);
3552
3553 if (temp > startPos)
3554 endPos = temp;
3555
3556 if (endPos >= to)
3557 break;
3558
3559 if (endPos >= eop_begin) {
3560 startPos = eop_end;
3561 eop_begin=SrcScanXawTextSourceScan(src, startPos, XawstParagraph,
3562 XawsdRight, 1,False0);
3563 eop_end = SrcScanXawTextSourceScan(src, startPos, XawstParagraph,
3564 XawsdRight, 1, True1);
3565 }
3566 else {
3567 XawTextPosition periodPos, next_word;
3568 int i, len;
3569
3570 periodPos = SrcScanXawTextSourceScan(src, endPos, XawstPositions,
3571 XawsdLeft, 1, True1);
3572 next_word = SrcScanXawTextSourceScan(src, endPos, XawstWhiteSpace,
3573 XawsdRight, 1, False0);
3574
3575 len = next_word - periodPos;
3576
3577 text.length = 1;
3578 buf = _XawTextGetText(ctx, periodPos, next_word);
3579 if (text.format == XawFmtWide) {
3580 if (periodPos < endPos && ((wchar_t*)buf)[0] == _Xaw_atowc('.'))
3581 text.length++;
3582 }
3583 else
3584 if (periodPos < endPos && buf[0] == '.')
3585 text.length++; /* Put in two spaces. */
3586
3587 /*
3588 * Remove all extra spaces.
3589 */
3590 for (i = 1 ; i < len; i++)
3591 if (text.format == XawFmtWide) {
3592 if (!iswspace(((wchar_t*)buf)[i])(isascii(((wchar_t*)buf)[i]) && isspace(toascii(((wchar_t
*)buf)[i])))
|| ((periodPos + i) >= to))
3593 break;
3594 }
3595 else if (!isspace(buf[i]) || (periodPos + i) >= to)
3596 break;
3597
3598 XtFree(buf);
3599
3600 to -= (i - text.length - 1);
3601 startPos = SrcScanXawTextSourceScan(src, periodPos, XawstPositions,
3602 XawsdRight, i, True1);
3603 if (_XawTextReplace(ctx, endPos, startPos, &text) != XawEditDone0)
3604 return (XawReplaceError-1);
3605
3606 for (idx = 0; idx < num_pos; idx++) {
3607 if (endPos < pos[idx]) {
3608 if (startPos < pos[idx])
3609 pos[idx] -= startPos - endPos;
3610 else
3611 pos[idx] = endPos;
3612 pos[idx] += text.length;
3613 }
3614 }
3615
3616 startPos -= i - text.length;
3617 }
3618 }
3619
3620 return (to);
3621}
3622
3623/* InsertNewCRs() - called from FormRegion
3624 *
3625 * inserts new CRs for FormRegion, thus for FormParagraph action */
3626static void
3627InsertNewCRs(TextWidget ctx, XawTextPosition from, XawTextPosition to,
3628 XawTextPosition *pos, int num_pos)
3629{
3630 XawTextPosition startPos, endPos, space, eol;
3631 XawTextBlock text;
3632 int i, width, height, len, wwidth, idx;
3633 char *buf;
3634 static wchar_t wide_CR[2];
3635
3636 text.firstPos = 0;
3637 text.length = 1;
3638 text.format = _XawTextFormat(ctx);
3639
3640 if (text.format == XawFmt8Bit)
3641 text.ptr = "\n";
3642 else {
3643 wide_CR[0] = _Xaw_atowc(XawLF0x0a);
3644 wide_CR[1] = 0;
3645 text.ptr = (char*)wide_CR;
3646 }
3647
3648 startPos = from;
3649
3650 wwidth = (int)XtWidth(ctx)(((RectObj)ctx)->rectangle.width) - (int)HMargins(ctx)((ctx)->text.left_margin + (ctx)->text.margin.right);
3651 if (ctx->text.wrap != XawtextWrapNever) {
3652 XRectangle cursor;
3653
3654 XawTextSinkGetCursorBounds(ctx->text.sink, &cursor);
3655 wwidth -= (int)cursor.width;
3656 }
3657 wwidth = XawMax(0, wwidth)((0) > (wwidth) ? (0) : (wwidth));
3658
3659 /* CONSTCOND */
3660 while (TRUE1) {
3661 XawTextSinkFindPosition(ctx->text.sink, startPos,
3662 (int)ctx->text.r_margin.left, wwidth,
3663 True1, &eol, &width, &height);
3664 if (eol == startPos)
3665 ++eol;
3666 if (eol >= to)
3667 break;
3668
3669 eol = SrcScanXawTextSourceScan(ctx->text.source, eol, XawstPositions,
3670 XawsdLeft, 1, True1);
3671 space = SrcScanXawTextSourceScan(ctx->text.source, eol, XawstWhiteSpace,
3672 XawsdRight,1, True1);
3673
3674 startPos = endPos = eol;
3675 if (eol == space)
3676 return;
3677
3678 len = (int)(space - eol);
3679 buf = _XawTextGetText(ctx, eol, space);
3680 for (i = 0 ; i < len ; i++)
3681 if (text.format == XawFmtWide) {
3682 if (!iswspace(((wchar_t*)buf)[i])(isascii(((wchar_t*)buf)[i]) && isspace(toascii(((wchar_t
*)buf)[i])))
)
3683 break;
3684 }
3685 else if (!isspace(buf[i]))
3686 break;
3687
3688 to -= (i - 1);
3689 endPos = SrcScanXawTextSourceScan(ctx->text.source, endPos,
3690 XawstPositions, XawsdRight, i, True1);
3691 XtFree(buf);
3692
3693 if (_XawTextReplace(ctx, startPos, endPos, &text))
3694 return;
3695
3696 for (idx = 0; idx < num_pos; idx++) {
3697 if (startPos < pos[idx]) {
3698 if (endPos < pos[idx])
3699 pos[idx] -= endPos - startPos;
3700 else
3701 pos[idx] = startPos;
3702 pos[idx] += text.length;
3703 }
3704 }
3705
3706 startPos = SrcScanXawTextSourceScan(ctx->text.source, startPos,
3707 XawstPositions, XawsdRight, 1, True1);
3708 }
3709}
3710
3711/* FormRegion() - called by FormParagraph
3712 *
3713 * oversees the work of paragraph-forming a region
3714 *
3715 * Return:
3716 * XawEditDone if successful, or XawReplaceError
3717 */
3718static int
3719FormRegion(TextWidget ctx, XawTextPosition from, XawTextPosition to,
3720 XawTextPosition *pos, int num_pos)
3721{
3722#ifndef OLDXAW
3723 Boolint format = ctx->text.auto_fill
3724 && ctx->text.left_column < ctx->text.right_column;
3725#endif
3726
3727 if (from >= to)
3728 return (XawEditDone0);
3729
3730#ifndef OLDXAW
3731 if (format) {
3732 XawTextPosition len = ctx->text.lastPos;
3733 int inc = 0;
3734
3735 if (ctx->text.justify == XawjustifyLeft ||
3736 ctx->text.justify == XawjustifyFull) {
3737 Untabify(ctx, from, to, pos, num_pos, NULL((void*)0));
3738 to += ctx->text.lastPos - len;
3739 len = ctx->text.insertPos;
3740 (void)BlankLine((Widget)ctx, from, &inc);
3741 if (from + inc >= to)
3742 return (XawEditDone0);
3743 }
3744 if (!StripSpaces(ctx, from + inc, to, pos, num_pos, NULL((void*)0)))
3745 return (XawReplaceError-1);
3746 to += ctx->text.lastPos - len;
3747
3748 FormatText(ctx, from, ctx->text.justify != XawjustifyFull, pos, num_pos);
3749 }
3750 else {
3751#endif
3752 if ((to = StripOutOldCRs(ctx, from, to, pos, num_pos)) == XawReplaceError-1)
3753 return (XawReplaceError-1);
3754 InsertNewCRs(ctx, from, to, pos, num_pos);
3755#ifndef OLDXAW
3756 }
3757#endif
3758 ctx->text.from_left = -1;
3759
3760 return (XawEditDone0);
3761}
3762
3763#ifndef OLDXAW
3764static Boolint
3765BlankLine(Widget w, XawTextPosition pos, int *blanks_return)
3766{
3767 int i, blanks = 0;
3768 XawTextBlock block;
3769 Widget src = XawTextGetSource(w);
3770 XawTextPosition l = SrcScanXawTextSourceScan(src, pos, XawstEOL, XawsdLeft, 1, False0);
3771 XawTextPosition r = SrcScanXawTextSourceScan(src, pos, XawstEOL, XawsdRight, 1, False0);
3772
3773 while (l < r) {
3774 l = XawTextSourceRead(src, l, &block, r - l);
3775 if (block.length == 0) {
3776 if (blanks_return)
3777 *blanks_return = blanks;
3778 return (True1);
3779 }
3780 if (XawTextFormat((TextWidget)w, XawFmt8Bit)((unsigned long)_XawTextFormat((TextWidget)w) == (XawFmt8Bit)
)
) {
3781 for (i = 0; i < block.length; i++, blanks++)
3782 if (block.ptr[i] != ' ' &&
3783 block.ptr[i] != '\t') {
3784 if (blanks_return)
3785 *blanks_return = blanks;
3786 return (block.ptr[i] == '\n');
3787 }
3788 }
3789 else if (XawTextFormat((TextWidget)w, XawFmtWide)((unsigned long)_XawTextFormat((TextWidget)w) == (XawFmtWide)
)
) {
3790 for (i = 0; i < block.length; i++, blanks++)
3791 if (_Xaw_atowc(XawSP0x20) != ((wchar_t*)block.ptr)[i] &&
3792 _Xaw_atowc(XawTAB0x09) != ((wchar_t*)block.ptr)[i]) {
3793 if (blanks_return)
3794 *blanks_return = blanks;
3795 return (_Xaw_atowc(XawLF0x0a) == ((wchar_t*)block.ptr)[i]);
3796 }
3797 }
3798 }
3799
3800 return (True1);
3801}
3802
3803static Boolint
3804GetBlockBoundaries(TextWidget ctx,
3805 XawTextPosition *from_return, XawTextPosition *to_return)
3806{
3807 XawTextPosition from, to;
3808
3809 if (ctx->text.auto_fill && ctx->text.left_column < ctx->text.right_column) {
3810 if (ctx->text.s.left != ctx->text.s.right) {
3811 from = SrcScanXawTextSourceScan(ctx->text.source,
3812 XawMin(ctx->text.s.left, ctx->text.s.right)((ctx->text.s.left) < (ctx->text.s.right) ? (ctx->
text.s.left) : (ctx->text.s.right))
,
3813 XawstEOL, XawsdLeft, 1, False0);
3814 to = SrcScanXawTextSourceScan(ctx->text.source,
3815 XawMax(ctx->text.s.right, ctx->text.s.right)((ctx->text.s.right) > (ctx->text.s.right) ? (ctx->
text.s.right) : (ctx->text.s.right))
,
3816 XawstEOL, XawsdRight, 1, False0);
3817 }
3818 else {
3819 XawTextBlock block;
3820 XawTextPosition tmp;
3821 Boolint first;
3822
3823 from = to = ctx->text.insertPos;
3824
3825 /* find from position */
3826 first = True1;
3827 while (1) {
3828 tmp = from;
3829 from = SrcScanXawTextSourceScan(ctx->text.source, from, XawstEOL, XawsdLeft,
3830 1 + !first, False0);
3831 XawTextSourceRead(ctx->text.source, from, &block, 1);
3832 if (block.length == 0 ||
3833 (XawTextFormat(ctx, XawFmt8Bit)((unsigned long)_XawTextFormat(ctx) == (XawFmt8Bit)) &&
3834 block.ptr[0] != ' ' &&
3835 block.ptr[0] != '\t' &&
3836 !isalnum(*(unsigned char*)block.ptr)) ||
3837 (XawTextFormat(ctx, XawFmtWide)((unsigned long)_XawTextFormat(ctx) == (XawFmtWide)) &&
3838 _Xaw_atowc(XawSP0x20) != *(wchar_t*)block.ptr &&
3839 _Xaw_atowc(XawTAB0x09) != *(wchar_t*)block.ptr &&
3840 !iswalnum(*(wchar_t*)block.ptr)) ||
3841 BlankLine((Widget)ctx, from, NULL((void*)0))) {
3842 from = tmp;
3843 break;
3844 }
3845 if (from == tmp && !first)
3846 break;
3847 first = False0;
3848 }
3849 if (first)
3850 return (False0);
3851
3852 /* find to position */
3853 first = True1;
3854 while (1) {
3855 tmp = to;
3856 to = SrcScanXawTextSourceScan(ctx->text.source, to, XawstEOL, XawsdRight,
3857 1 + !first, False0);
3858 XawTextSourceRead(ctx->text.source, to + (to < ctx->text.lastPos),
3859 &block, 1);
3860 if (block.length == 0 ||
3861 (XawTextFormat(ctx, XawFmt8Bit)((unsigned long)_XawTextFormat(ctx) == (XawFmt8Bit)) &&
3862 block.ptr[0] != ' ' &&
3863 block.ptr[0] != '\t' &&
3864 !isalnum(*(unsigned char*)block.ptr)) ||
3865 (XawTextFormat(ctx, XawFmtWide)((unsigned long)_XawTextFormat(ctx) == (XawFmtWide)) &&
3866 _Xaw_atowc(XawSP0x20) != *(wchar_t*)block.ptr &&
3867 _Xaw_atowc(XawTAB0x09) != *(wchar_t*)block.ptr &&
3868 !iswalnum(*(wchar_t*)block.ptr)) ||
3869 BlankLine((Widget)ctx, to, NULL((void*)0)))
3870 break;
3871 if (to == tmp && !first)
3872 break;
3873 first = False0;
3874 }
3875 }
3876 }
3877 else {
3878 from = SrcScanXawTextSourceScan(ctx->text.source, ctx->text.insertPos, XawstEOL,
3879 XawsdLeft, 1, False0);
3880 if (BlankLine((Widget)ctx, from, NULL((void*)0)))
3881 return (False0);
3882 from = SrcScanXawTextSourceScan(ctx->text.source, from, XawstParagraph,
3883 XawsdLeft, 1, False0);
3884 if (BlankLine((Widget)ctx, from, NULL((void*)0)))
3885 from = SrcScanXawTextSourceScan(ctx->text.source, from, XawstEOL,
3886 XawsdRight, 1, True1);
3887 to = SrcScanXawTextSourceScan(ctx->text.source, from, XawstParagraph,
3888 XawsdRight, 1, False0);
3889 }
3890
3891 if (from < to) {
3892 *from_return = from;
3893 *to_return = to;
3894 return (True1);
3895 }
3896
3897 return (False0);
3898}
3899#endif /* OLDXAW */
3900
3901/* FormParagraph() - action
3902 *
3903 * removes and reinserts CRs to maximize line length without clipping */
3904/*ARGSUSED*/
3905static void
3906FormParagraph(Widget w, XEvent *event, String *params, Cardinal *num_params)
3907{
3908 TextWidget ctx = (TextWidget)w;
3909 XawTextPosition from, to, buf[32], *pos;
3910#ifndef OLDXAW
3911 XawTextPosition endPos = 0;
3912 char *lbuf = NULL((void*)0), *rbuf;
3913 TextSrcObject src = (TextSrcObject)ctx->text.source;
3914 Cardinal i;
3915 Boolint undo = src->textSrc.enable_undo && src->textSrc.undo_state == False0;
3916#endif
3917
3918 StartAction(ctx, event);
3919
3920#ifndef OLDXAW
3921 pos = XawStackAlloc(sizeof(XawTextPosition) * src->textSrc.num_text, buf)((sizeof(XawTextPosition) * src->textSrc.num_text) <= sizeof
(buf) ? (XtPointer)(buf) : XtMalloc((unsigned)(sizeof(XawTextPosition
) * src->textSrc.num_text)))
;
3922 for (i = 0; i < src->textSrc.num_text; i++)
3923 pos[i] = ((TextWidget)src->textSrc.text[i])->text.old_insert;
3924#else
3925 pos = buf;
3926 *pos = ctx->text.old_insert;
3927#endif
3928
3929#ifndef OLDXAW
3930 if (!GetBlockBoundaries(ctx, &from, &to)) {
3931 EndAction(ctx);
3932 XawStackFree(pos, buf)do { if ((pos) != (XtPointer)(buf)) XtFree((char *)pos); } while
(0)
;
3933 return;
3934 }
3935
3936 if (undo) {
3937 src->textSrc.undo_state = True1;
3938 lbuf = _XawTextGetText(ctx, from, to);
3939 endPos = ctx->text.lastPos;
3940 }
3941
3942 if (FormRegion(ctx, from, to, pos, src->textSrc.num_text) == XawReplaceError-1) {
3943 XawStackFree(pos, buf)do { if ((pos) != (XtPointer)(buf)) XtFree((char *)pos); } while
(0)
;
3944 pos = buf;
3945#else
3946 from = SrcScanXawTextSourceScan(ctx->text.source, ctx->text.insertPos,
3947 XawstParagraph, XawsdLeft, 1, False0);
3948 to = SrcScanXawTextSourceScan(ctx->text.source, from,
3949 XawstParagraph, XawsdRight, 1, False0);
3950
3951 if (FormRegion(ctx, from, to, pos, 1) == XawReplaceError-1) {
3952#endif
3953 XBell(XtDisplay(w)(((w)->core.screen)->display), 0);
3954#ifndef OLDXAW
3955 if (undo) {
3956 src->textSrc.undo_state = False0;
3957 XtFree(lbuf);
3958 }
3959#endif
3960 }
3961#ifndef OLDXAW
3962 else if (undo) {
3963 /* makes the form-paragraph only one undo/redo step */
3964 unsigned llen, rlen, size;
3965 XawTextBlock block;
3966
3967 llen = to - from;
3968 rlen = llen + (ctx->text.lastPos - endPos);
3969
3970 block.firstPos = 0;
3971 block.format = _XawTextFormat(ctx);
3972
3973 rbuf = _XawTextGetText(ctx, from, from + rlen);
3974
3975 size = XawTextFormat(ctx, XawFmtWide)((unsigned long)_XawTextFormat(ctx) == (XawFmtWide)) ? sizeof(wchar_t) : sizeof(char);
3976 if (llen != rlen || memcmp(lbuf, rbuf, llen * size)) {
3977 block.ptr = lbuf;
3978 block.length = llen;
3979 _XawTextReplace(ctx, from, from + rlen, &block);
3980
3981 src->textSrc.undo_state = False0;
3982 block.ptr = rbuf;
3983 block.length = rlen;
3984 _XawTextReplace(ctx, from, from + llen, &block);
3985 }
3986 else
3987 src->textSrc.undo_state = False0;
3988 XtFree(lbuf);
3989 XtFree(rbuf);
3990 }
3991
3992 for (i = 0; i < src->textSrc.num_text; i++) {
3993 TextWidget tw = (TextWidget)src->textSrc.text[i];
3994
3995 tw->text.old_insert = tw->text.insertPos = pos[i];
3996 _XawTextBuildLineTable(tw, SrcScanXawTextSourceScan((Widget)src, tw->text.lt.top, XawstEOL,
3997 XawsdLeft, 1, False0), False0);
3998 tw->text.clear_to_eol = True1;
3999 }
4000 XawStackFree(pos, buf)do { if ((pos) != (XtPointer)(buf)) XtFree((char *)pos); } while
(0)
;
4001#else
4002 ctx->text.old_insert = ctx->text.insertPos = *pos;
4003 _XawTextBuildLineTable(ctx, SrcScanXawTextSourceScan(ctx->text.source, ctx->text.lt.top,
4004 XawstEOL, XawsdLeft, 1, False0), False0);
4005 ctx->text.clear_to_eol = True1;
4006#endif
4007 ctx->text.showposition = True1;
4008
4009 EndAction(ctx);
4010}
4011
4012/* TransposeCharacters() - action
4013 *
4014 * Swaps the character to the left of the mark
4015 * with the character to the right of the mark */
4016/*ARGSUSED*/
4017static void
4018TransposeCharacters(Widget w, XEvent *event,
4019 String *params, Cardinal *num_params)
4020{
4021 TextWidget ctx = (TextWidget)w;
4022 XawTextPosition start, end;
4023 XawTextBlock text;
4024 char *buf;
4025 int i, mult = MULT(ctx)(ctx->text.mult == 0 ? 4 : ctx->text.mult == 32767 ? -4
: ctx->text.mult)
;
4026
4027 if (mult < 0) {
4028 ctx->text.mult = 1;
4029 return;
4030 }
4031
4032 StartAction(ctx, event);
4033
4034 /* Get bounds. */
4035
4036 start = SrcScanXawTextSourceScan(ctx->text.source, ctx->text.insertPos, XawstPositions,
4037 XawsdLeft, 1, True1);
4038 end = SrcScanXawTextSourceScan(ctx->text.source, ctx->text.insertPos, XawstPositions,
4039 XawsdRight, mult, True1);
4040
4041 /* Make sure we aren't at the very beginning or end of the buffer. */
4042
4043 if (start == ctx->text.insertPos || end == ctx->text.insertPos) {
4044 XBell(XtDisplay(w)(((w)->core.screen)->display), 0); /* complain. */
4045 EndAction(ctx);
4046 return;
4047 }
4048
4049 ctx->text.from_left = -1;
4050 ctx->text.insertPos = end;
4051
4052 text.firstPos = 0;
4053 text.format = _XawTextFormat(ctx);
4054
4055 /* Retrieve text and swap the characters. */
4056 if (text.format == XawFmtWide) {
4057 wchar_t wc;
4058 wchar_t *wbuf;
4059
4060 wbuf = (wchar_t*)_XawTextGetText(ctx, start, end);
4061 text.length = wcslen(wbuf);
4062 wc = wbuf[0];
4063 for (i = 1; i < text.length; i++)
4064 wbuf[i - 1] = wbuf[i];
4065 wbuf[i - 1] = wc;
4066 buf = (char*)wbuf; /* so that it gets assigned and freed */
4067 }
4068 else { /* thus text.format == XawFmt8Bit */
4069 char c;
4070
4071 buf = _XawTextGetText(ctx, start, end);
4072 text.length = strlen(buf);
4073 c = buf[0];
4074 for (i = 1; i < text.length; i++)
4075 buf[i - 1] = buf[i];
4076 buf[i - 1] = c;
4077 }
4078
4079 text.ptr = buf;
4080
4081 /* Store new text in source. */
4082
4083 if (_XawTextReplace (ctx, start, end, &text))
4084 XBell(XtDisplay(w)(((w)->core.screen)->display), 0);
4085 XtFree((char *)buf);
4086 EndAction(ctx);
4087}
4088
4089#ifndef OLDXAW
4090/*ARGSUSED*/
4091static void
4092Undo(Widget w, XEvent *event, String *params, Cardinal *num_params)
4093{
4094 TextWidget ctx = (TextWidget)w;
4095 int mul = MULT(ctx)(ctx->text.mult == 0 ? 4 : ctx->text.mult == 32767 ? -4
: ctx->text.mult)
;
4096 Boolint toggle = False0;
4097
4098 if (mul < 0) {
4099 toggle = True1;
4100 _XawTextSrcToggleUndo((TextSrcObject)ctx->text.source);
4101 ctx->text.mult = mul = -mul;
4102 }
4103
4104 StartAction(ctx, event);
4105 for (; mul; --mul)
4106 if (!_XawTextSrcUndo((TextSrcObject)ctx->text.source, &ctx->text.insertPos))
4107 break;
4108 ctx->text.showposition = True1;
4109
4110 if (toggle)
4111 _XawTextSrcToggleUndo((TextSrcObject)ctx->text.source);
4112 EndAction(ctx);
4113}
4114#endif
4115
4116/* NoOp() - action
4117 * This action performs no action, and allows the user or
4118 * application programmer to unbind a translation.
4119 *
4120 * Note: If the parameter list contains the string "RingBell" then
4121 * this action will ring the bell.
4122 */
4123/*ARGSUSED*/
4124static void
4125NoOp(Widget w, XEvent *event, String *params, Cardinal *num_params)
4126{
4127 if (*num_params != 1)
4128 return;
4129
4130 switch(params[0][0]) {
4131 case 'R':
4132 case 'r':
4133 XBell(XtDisplay(w)(((w)->core.screen)->display), 0);
4134 /*FALLTROUGH*/
4135 default:
4136 break;
4137 }
4138}
4139
4140/* Reconnect() - action
4141 * This reconnects to the input method. The user will typically call
4142 * this action if/when connection has been severed, or when the app
4143 * was started up before an IM was started up
4144 */
4145/*ARGSUSED*/
4146static void
4147Reconnect(Widget w, XEvent *event, String *params, Cardinal *num_params)
4148{
4149 _XawImReconnect(w);
4150}
4151
4152#define CAPITALIZE 1
4153#define DOWNCASE 2
4154#define UPCASE 3
4155
4156#ifdef NO_LIBC_I18N
4157static int
4158ToLowertolower(int ch)
4159{
4160 char buf[2];
4161
4162 *buf = ch;
4163 XmuNCopyISOLatin1Lowered(buf, buf, sizeof(buf));
4164
4165 return (*buf);
4166}
4167
4168static int
4169ToUppertoupper(int ch)
4170{
4171 char buf[2];
4172
4173 *buf = ch;
4174 XmuNCopyISOLatin1Uppered(buf, buf, sizeof(buf));
4175
4176 return (*buf);
4177}
4178
4179static int
4180IsAlnumisalnum(int ch)
4181{
4182 return ((ch >= '0' && ch <= '9') || ToUppertoupper(ch) != ch || ToLowertolower(ch) != ch);
4183}
4184
4185static int
4186IsLowerislower(int ch)
4187{
4188 char upbuf[2];
4189 char lobuf[2];
4190
4191 *upbuf = *lobuf = ch;
4192 XmuNCopyISOLatin1Lowered(lobuf, lobuf, sizeof(lobuf));
4193 XmuNCopyISOLatin1Uppered(upbuf, upbuf, sizeof(upbuf));
4194
4195 return (*lobuf != *upbuf && ch == *lobuf);
4196}
4197
4198static int
4199IsUpperisupper(int ch)
4200{
4201 char upbuf[2];
4202 char lobuf[2];
4203
4204 *upbuf = *lobuf = ch;
4205 XmuNCopyISOLatin1Lowered(lobuf, lobuf, sizeof(lobuf));
4206 XmuNCopyISOLatin1Uppered(upbuf, upbuf, sizeof(upbuf));
4207
4208 return (*lobuf != *upbuf && ch == *upbuf);
4209}
4210#else
4211#define ToLowertolower tolower
4212#define ToUppertoupper toupper
4213#define IsAlnumisalnum isalnum
4214#define IsLowerislower islower
4215#define IsUpperisupper isupper
4216#endif
4217
4218static void
4219CaseProc(Widget w, XEvent *event, int cmd)
4220{
4221 TextWidget ctx = (TextWidget)w;
4222 short mul = MULT(ctx)(ctx->text.mult == 0 ? 4 : ctx->text.mult == 32767 ? -4
: ctx->text.mult)
;
4223 XawTextPosition left, right;
4224 XawTextBlock block;
4225 Boolint changed = False0;
4226 unsigned char ch, mb[sizeof(wchar_t)];
4227 int i, count;
4228
4229 if (mul > 0)
4230 right = SrcScanXawTextSourceScan(ctx->text.source, left = ctx->text.insertPos,
4231 XawstAlphaNumeric, XawsdRight, mul, False0);
4232 else
4233 left = SrcScanXawTextSourceScan(ctx->text.source, right = ctx->text.insertPos,
4234 XawstAlphaNumeric, XawsdLeft, 1 + -mul, False0);
4235 block.firstPos = 0;
4236 block.format = _XawTextFormat(ctx);
4237 block.length = right - left;
4238 block.ptr = _XawTextGetText(ctx, left, right);
4239
4240 count = 0;
4241 if (block.format == XawFmt8Bit)
4242 for (i = 0; i < block.length; i++) {
4243 if (!IsAlnumisalnum(*mb = (unsigned char)block.ptr[i]))
4244 count = 0;
4245 else if (++count == 1 || cmd != CAPITALIZE) {
4246 ch = cmd == DOWNCASE ? ToLowertolower(*mb) : ToUppertoupper(*mb);
4247 if (ch != *mb) {
4248 changed = True1;
4249 block.ptr[i] = ch;
4250 }
4251 }
4252 else if (cmd == CAPITALIZE) {
4253 if ((ch = ToLowertolower(*mb)) != *mb) {
4254 changed = True1;
4255 block.ptr[i] = ch;
4256 }
4257 }
4258 }
4259 else
4260 for (i = 0; i < block.length; i++) {
4261 wctomb((char*)mb, ((wchar_t*)block.ptr)[i]);
4262 if (!IsAlnumisalnum(*mb))
4263 count = 0;
4264 else if (++count == 1 || cmd != CAPITALIZE) {
4265 ch = cmd == DOWNCASE ? ToLowertolower(*mb) : ToUppertoupper(*mb);
4266 if (ch != *mb) {
4267 changed = True1;
4268 ((wchar_t*)block.ptr)[i] = _Xaw_atowc(ch);
4269 }
4270 }
4271 else if (cmd == CAPITALIZE) {
4272 if ((ch = ToLowertolower(*mb)) != *mb) {
4273 changed = True1;
4274 ((wchar_t*)block.ptr)[i] = _Xaw_atowc(ch);
4275 }
4276 }
4277 }
4278
4279 StartAction(ctx, event);
4280 if (changed && _XawTextReplace(ctx, left, right, &block) != XawEditDone0)
4281 XBell(XtDisplay(ctx)(((ctx)->core.screen)->display), 0);
4282 ctx->text.insertPos = right;
4283 EndAction(ctx);
4284
4285 XtFree(block.ptr);
4286}
4287
4288/*ARGSUSED*/
4289static void
4290CapitalizeWord(Widget w, XEvent *event, String *params, Cardinal *num_params)
4291{
4292 CaseProc(w, event, CAPITALIZE);
4293}
4294
4295/*ARGSUSED*/
4296static void
4297DowncaseWord(Widget w, XEvent *event, String *params, Cardinal *num_params)
4298{
4299 CaseProc(w, event, DOWNCASE);
4300}
4301
4302/*ARGSUSED*/
4303static void
4304UpcaseWord(Widget w, XEvent *event, String *params, Cardinal *num_params)
4305{
4306 CaseProc(w, event, UPCASE);
4307}
4308#undef CAPITALIZE
4309#undef DOWNCASE
4310#undef UPCASE
4311
4312XtActionsRec _XawTextActionsTable[] = {
4313 /* motion */
4314 {"forward-character", MoveForwardChar},
4315 {"backward-character", MoveBackwardChar},
4316 {"forward-word", MoveForwardWord},
4317 {"backward-word", MoveBackwardWord},
4318 {"forward-paragraph", MoveForwardParagraph},
4319 {"backward-paragraph", MoveBackwardParagraph},
4320 {"beginning-of-line", MoveToLineStart},
4321 {"end-of-line", MoveToLineEnd},
4322 {"next-line", MoveNextLine},
4323 {"previous-line", MovePreviousLine},
4324 {"next-page", MoveNextPage},
4325 {"previous-page", MovePreviousPage},
4326 {"beginning-of-file", MoveBeginningOfFile},
4327 {"end-of-file", MoveEndOfFile},
4328 {"scroll-one-line-up", ScrollOneLineUp},
4329 {"scroll-one-line-down", ScrollOneLineDown},
4330
4331 /* delete */
4332 {"delete-next-character", DeleteForwardChar},
4333 {"delete-previous-character", DeleteBackwardChar},
4334 {"delete-next-word", DeleteForwardWord},
4335 {"delete-previous-word", DeleteBackwardWord},
4336 {"delete-selection", DeleteCurrentSelection},
4337 {"delete", Delete},
4338
4339 /* kill */
4340 {"kill-word", KillForwardWord},
4341 {"backward-kill-word", KillBackwardWord},
4342 {"kill-selection", KillCurrentSelection},
4343 {"kill-to-end-of-line", KillToEndOfLine},
4344 {"kill-to-end-of-paragraph", KillToEndOfParagraph},
4345
4346 /* new line */
4347 {"newline-and-indent", InsertNewLineAndIndent},
4348 {"newline-and-backup", InsertNewLineAndBackup},
4349 {"newline", InsertNewLine},
4350
4351 /* selection */
4352 {"select-word", SelectWord},
4353 {"select-all", SelectAll},
4354 {"select-start", SelectStart},
4355 {"select-adjust", SelectAdjust},
4356 {"select-end", SelectEnd},
4357 {"select-save", SelectSave},
4358 {"extend-start", ExtendStart},
4359 {"extend-adjust", ExtendAdjust},
4360 {"extend-end", ExtendEnd},
4361 {"insert-selection", InsertSelection},
4362
4363 /* miscellaneous */
4364 {"redraw-display", RedrawDisplay},
4365 {"insert-file", _XawTextInsertFile},
4366 {"search", _XawTextSearch},
4367 {"insert-char", InsertChar},
4368 {"insert-string", InsertString},
4369 {"focus-in", TextFocusIn},
4370 {"focus-out", TextFocusOut},
4371 {"enter-window", TextEnterWindow},
4372 {"leave-window", TextLeaveWindow},
4373 {"display-caret", DisplayCaret},
4374 {"multiply", Multiply},
4375 {"form-paragraph", FormParagraph},
4376 {"transpose-characters", TransposeCharacters},
4377 {"set-keyboard-focus", SetKeyboardFocus},
4378#ifndef OLDXAW
4379 {"numeric", Numeric},
4380 {"undo", Undo},
4381 {"keyboard-reset", KeyboardReset},
4382 {"kill-ring-yank", KillRingYank},
4383 {"toggle-overwrite", ToggleOverwrite},
4384 {"indent", Indent},
4385#endif
4386 {"no-op", NoOp},
4387
4388 /* case transformations */
4389 {"capitalize-word", CapitalizeWord},
4390 {"downcase-word", DowncaseWord},
4391 {"upcase-word", UpcaseWord},
4392
4393 /* action to bind translations for text dialogs */
4394 {"InsertFileAction", _XawTextInsertFileAction},
4395 {"DoSearchAction", _XawTextDoSearchAction},
4396 {"DoReplaceAction", _XawTextDoReplaceAction},
4397 {"SetField", _XawTextSetField},
4398 {"PopdownSearchAction", _XawTextPopdownSearchAction},
4399
4400 /* reconnect to Input Method */
4401 {"reconnect-im", Reconnect} /* Li Yuhong, Omron KK, 1991 */
4402};
4403
4404Cardinal _XawTextActionsTableCount = XtNumber(_XawTextActionsTable)((Cardinal) (sizeof(_XawTextActionsTable) / sizeof(_XawTextActionsTable
[0])))
;