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