home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / lib / Xaw / TextAction.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-23  |  37.1 KB  |  1,580 lines

  1. /* $XConsortium: TextAction.c,v 1.43 91/07/23 12:23:54 rws Exp $ */
  2.  
  3. /***********************************************************
  4. Copyright 1989 by the Massachusetts Institute of Technology,
  5. Cambridge, Massachusetts.
  6.  
  7.                         All Rights Reserved
  8.  
  9. Permission to use, copy, modify, and distribute this software and its 
  10. documentation for any purpose and without fee is hereby granted, 
  11. provided that the above copyright notice appear in all copies and that
  12. both that copyright notice and this permission notice appear in 
  13. supporting documentation, and that the names of Digital or MIT not be
  14. used in advertising or publicity pertaining to distribution of the
  15. software without specific, written prior permission.  
  16.  
  17. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  18. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  19. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  20. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  22. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  23. SOFTWARE.
  24.  
  25. ******************************************************************/
  26.  
  27. /*
  28.  * NOTE:  There are some ASCII Dependancies on '\n' and '\0' that I
  29.  *        am not too thrilled with.  There is also the implicit assumption
  30.  *        that the individual characters will fit inside a "char".
  31.  *        It would be nice if we could generalize this a but more.  If
  32.  *        anyone out there comes up with an implementation of this stuff
  33.  *        that has no dependency on ASCII, please send the code back to us.
  34.  *
  35.  *                        Chris D. Peterson     
  36.  *                        MIT X Consortium 
  37.  */
  38.  
  39. #include <X11/IntrinsicP.h>
  40. #include <X11/StringDefs.h>
  41. #include <X11/Xatom.h>
  42. #include <X11/Xmu/Misc.h>
  43. #include <X11/Xaw/TextP.h>
  44. #include <stdio.h>
  45. #include <ctype.h>
  46.  
  47. #define SrcScan                XawTextSourceScan
  48. #define FindDist               XawTextSinkFindDistance
  49. #define FindPos                XawTextSinkFindPosition
  50.  
  51. /*
  52.  * These are defined in TextPop.c
  53.  */
  54.  
  55. void _XawTextInsertFileAction(), _XawTextInsertFile(), _XawTextSearch();
  56. void _XawTextSearch(), _XawTextDoSearchAction(), _XawTextDoReplaceAction();
  57. void _XawTextSetField(), _XawTextPopdownSearchAction();
  58.  
  59. /*
  60.  * These are defined in Text.c
  61.  */
  62.  
  63. char * _XawTextGetText();
  64. void _XawTextBuildLineTable(), _XawTextAlterSelection(), _XawTextVScroll();
  65. void _XawTextSetSelection(), _XawTextCheckResize(), _XawTextExecuteUpdate();
  66. void _XawTextSetScrollBars(), _XawTextClearAndCenterDisplay();
  67. Atom * _XawTextSelectionList();
  68.  
  69. static void
  70. StartAction(ctx, event)
  71. TextWidget ctx;
  72. XEvent *event;
  73. {
  74.   _XawTextPrepareToUpdate(ctx);
  75.   if (event != NULL) {
  76.     switch (event->type) {
  77.     case ButtonPress:
  78.     case ButtonRelease:
  79.       ctx->text.time = event->xbutton.time;
  80.       ctx->text.ev_x = event->xbutton.x;
  81.       ctx->text.ev_y = event->xbutton.y;
  82.       break;
  83.     case KeyPress:
  84.     case KeyRelease:
  85.       ctx->text.time = event->xkey.time;
  86.       ctx->text.ev_x = event->xkey.x;
  87.       ctx->text.ev_y = event->xkey.y;
  88.       break;
  89.     case MotionNotify:
  90.       ctx->text.time = event->xmotion.time;
  91.       ctx->text.ev_x = event->xmotion.x;
  92.       ctx->text.ev_y = event->xmotion.y;
  93.       break;
  94.     case EnterNotify:
  95.     case LeaveNotify:
  96.       ctx->text.time = event->xcrossing.time;
  97.       ctx->text.ev_x = event->xcrossing.x;
  98.       ctx->text.ev_y = event->xcrossing.y;
  99.     }
  100.   }
  101. }
  102.  
  103. static void
  104. EndAction(ctx)
  105. TextWidget ctx;
  106. {
  107.   _XawTextCheckResize(ctx);
  108.   _XawTextExecuteUpdate(ctx);
  109.   ctx->text.mult = 1;
  110. }
  111.  
  112.  
  113. struct _SelectionList {
  114.     String *params;
  115.     Cardinal count;
  116.     Time time;
  117. };
  118.  
  119. static void GetSelection();
  120.  
  121. /* ARGSUSED */
  122. static void 
  123. _SelectionReceived(w, client_data, selection, type, value, length, format)
  124. Widget w;
  125. XtPointer client_data;
  126. Atom *selection, *type;
  127. XtPointer value;
  128. unsigned long *length;
  129. int *format;
  130. {
  131.   TextWidget ctx = (TextWidget)w;
  132.   XawTextBlock text;
  133.   
  134.   if (*type == 0 /*XT_CONVERT_FAIL*/ || *length == 0) {
  135.     struct _SelectionList* list = (struct _SelectionList*)client_data;
  136.     if (list != NULL) {
  137.       GetSelection(w, list->time, list->params, list->count);
  138.       XtFree(client_data);
  139.     }
  140.     return;
  141.   }
  142.   
  143.   StartAction(ctx, NULL);
  144.   text.ptr = (char*)value;
  145.   text.firstPos = 0;
  146.   text.length = *length;
  147.   text.format = FMT8BIT;
  148.   if (_XawTextReplace(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) {
  149.     XBell(XtDisplay(ctx), 0);
  150.     return;
  151.   }
  152.   ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos, 
  153.                 XawstPositions, XawsdRight, text.length, TRUE);
  154.  
  155.   EndAction(ctx);
  156.   _XawTextSetScrollBars(ctx);
  157.   XtFree(client_data);
  158.   XFree(value);        /* the selection value should be freed with XFree */
  159. }
  160.  
  161. static void 
  162. GetSelection(w, time, params, num_params)
  163. Widget w;
  164. Time time;
  165. String *params;            /* selections in precedence order */
  166. Cardinal num_params;
  167. {
  168.     Atom selection;
  169.     int buffer;
  170.  
  171.     selection = XInternAtom(XtDisplay(w), *params, False);
  172.     switch (selection) {
  173.       case XA_CUT_BUFFER0: buffer = 0; break;
  174.       case XA_CUT_BUFFER1: buffer = 1; break;
  175.       case XA_CUT_BUFFER2: buffer = 2; break;
  176.       case XA_CUT_BUFFER3: buffer = 3; break;
  177.       case XA_CUT_BUFFER4: buffer = 4; break;
  178.       case XA_CUT_BUFFER5: buffer = 5; break;
  179.       case XA_CUT_BUFFER6: buffer = 6; break;
  180.       case XA_CUT_BUFFER7: buffer = 7; break;
  181.       default:           buffer = -1;
  182.     }
  183.     if (buffer >= 0) {
  184.     int nbytes;
  185.     unsigned long length;
  186.     int fmt8 = 8;
  187.     Atom type = XA_STRING;
  188.     char *line = XFetchBuffer(XtDisplay(w), &nbytes, buffer);
  189.     if (length = nbytes)
  190.         _SelectionReceived(w, NULL, &selection, &type, (caddr_t)line,
  191.                    &length, &fmt8);
  192.     else if (num_params > 1)
  193.         GetSelection(w, time, params+1, num_params-1);
  194.     } else {
  195.     struct _SelectionList* list;
  196.     if (--num_params) {
  197.         list = XtNew(struct _SelectionList);
  198.         list->params = params + 1;
  199.         list->count = num_params;
  200.         list->time = time;
  201.     } else list = NULL;
  202.     XtGetSelectionValue(w, selection, XA_STRING, _SelectionReceived,
  203.                 (XtPointer)list, time);
  204.     }
  205. }
  206.  
  207. static void 
  208. InsertSelection(w, event, params, num_params)
  209. Widget w;
  210. XEvent *event;
  211. String *params;        /* precedence list of selections to try */
  212. Cardinal *num_params;
  213. {
  214.   StartAction((TextWidget)w, event); /* Get Time. */
  215.   GetSelection(w, ((TextWidget)w)->text.time, params, *num_params);
  216.   EndAction((TextWidget)w);
  217. }
  218.  
  219. /************************************************************
  220.  *
  221.  * Routines for Moving Around.
  222.  *
  223.  ************************************************************/
  224.  
  225. static void
  226. Move(ctx, event, dir, type, include)
  227. TextWidget ctx;
  228. XEvent *event;
  229. XawTextScanDirection dir;
  230. XawTextScanType type;
  231. Boolean include;
  232. {
  233.   StartAction(ctx, event);
  234.   ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos,
  235.                 type, dir, ctx->text.mult, include);
  236.   EndAction(ctx);
  237. }
  238.  
  239. /*ARGSUSED*/
  240. static void 
  241. MoveForwardChar(w, event, p, n)
  242. Widget w;
  243. XEvent *event;
  244. String *p;
  245. Cardinal *n;
  246. {
  247.    Move((TextWidget) w, event, XawsdRight, XawstPositions, TRUE);
  248. }
  249.  
  250. /*ARGSUSED*/
  251. static void 
  252. MoveBackwardChar(w, event, p, n)
  253. Widget w;
  254. XEvent *event;
  255. String *p;
  256. Cardinal *n;
  257. {
  258.   Move((TextWidget) w, event, XawsdLeft, XawstPositions, TRUE);
  259. }
  260.  
  261. /*ARGSUSED*/
  262. static void 
  263. MoveForwardWord(w, event, p, n)
  264. Widget w;
  265. XEvent *event;
  266. String *p;
  267. Cardinal *n;
  268. {
  269.   Move((TextWidget) w, event, XawsdRight, XawstWhiteSpace, FALSE);
  270. }
  271.  
  272. /*ARGSUSED*/
  273. static void 
  274. MoveBackwardWord(w, event, p, n)
  275. Widget w;
  276. XEvent *event;
  277. String *p;
  278. Cardinal *n;
  279. {
  280.   Move((TextWidget) w, event, XawsdLeft, XawstWhiteSpace, FALSE);
  281. }
  282.  
  283. /*ARGSUSED*/
  284. static void MoveForwardParagraph(w, event, p, n)
  285. Widget w;
  286. XEvent *event;
  287. String *p;
  288. Cardinal *n;
  289. {
  290.   Move((TextWidget) w, event, XawsdRight, XawstParagraph, FALSE);
  291. }
  292.  
  293. /*ARGSUSED*/
  294. static void MoveBackwardParagraph(w, event, p, n)
  295. Widget w;
  296. XEvent *event;
  297. String *p;
  298. Cardinal *n;
  299. {
  300.   Move((TextWidget) w, event, XawsdLeft, XawstParagraph, FALSE);
  301. }
  302.  
  303. /*ARGSUSED*/
  304. static void 
  305. MoveToLineEnd(w, event, p, n)
  306. Widget w;
  307. XEvent *event;
  308. String *p;
  309. Cardinal *n;
  310. {
  311.   Move((TextWidget) w, event, XawsdRight, XawstEOL, FALSE);
  312. }
  313.  
  314. /*ARGSUSED*/
  315. static void 
  316. MoveToLineStart(w, event, p, n)
  317. Widget w;
  318. XEvent *event;
  319. String *p;
  320. Cardinal *n;
  321. {
  322.   Move((TextWidget) w, event, XawsdLeft, XawstEOL, FALSE);
  323. }
  324.  
  325.  
  326. static void
  327. MoveLine(ctx, event, dir)
  328. TextWidget ctx;
  329. XEvent *event;
  330. XawTextScanDirection dir;
  331. {
  332.   XawTextPosition new, next_line, junk;
  333.   int from_left, garbage;
  334.  
  335.   StartAction(ctx, event);
  336.  
  337.   if (dir == XawsdLeft)
  338.     ctx->text.mult++;
  339.  
  340.   new = SrcScan(ctx->text.source, ctx->text.insertPos,
  341.         XawstEOL, XawsdLeft, 1, FALSE);
  342.  
  343.   FindDist(ctx->text.sink, new, ctx->text.margin.left, ctx->text.insertPos,
  344.        &from_left, &junk, &garbage);
  345.  
  346.   new = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, dir,
  347.         ctx->text.mult, (dir == XawsdRight));
  348.  
  349.   next_line = SrcScan(ctx->text.source, new, XawstEOL, XawsdRight, 1, FALSE);
  350.  
  351.   FindPos(ctx->text.sink, new, ctx->text.margin.left, from_left, FALSE,
  352.       &(ctx->text.insertPos), &garbage, &garbage);
  353.   
  354.   if (ctx->text.insertPos > next_line)
  355.     ctx->text.insertPos = next_line;
  356.  
  357.   EndAction(ctx);
  358. }
  359.  
  360. /*ARGSUSED*/
  361. static void 
  362. MoveNextLine(w, event, p, n)
  363. Widget w;
  364. XEvent *event;
  365. String *p;
  366. Cardinal *n;
  367. {
  368.   MoveLine( (TextWidget) w, event, XawsdRight);
  369. }
  370.  
  371. /*ARGSUSED*/
  372. static void 
  373. MovePreviousLine(w, event, p, n)
  374. Widget w;
  375. XEvent *event;
  376. String *p;
  377. Cardinal *n;
  378. {
  379.   MoveLine( (TextWidget) w, event, XawsdLeft);
  380. }
  381.  
  382. /*ARGSUSED*/
  383. static void
  384. MoveBeginningOfFile(w, event, p, n)
  385. Widget w;
  386. XEvent *event;
  387. String *p;
  388. Cardinal *n;
  389. {
  390.   Move((TextWidget) w, event, XawsdLeft, XawstAll, TRUE);
  391. }
  392.  
  393. /*ARGSUSED*/
  394. static void 
  395. MoveEndOfFile(w, event, p, n)
  396. Widget w;
  397. XEvent *event;
  398. String *p;
  399. Cardinal *n;
  400. {
  401.   Move((TextWidget) w, event, XawsdRight, XawstAll, TRUE);
  402. }
  403.  
  404. static void 
  405. Scroll(ctx, event, dir)
  406. TextWidget ctx;
  407. XEvent *event;
  408. XawTextScanDirection dir;
  409. {
  410.   StartAction(ctx, event);
  411.  
  412.   if (dir == XawsdLeft)
  413.     _XawTextVScroll(ctx, ctx->text.mult);
  414.   else
  415.     _XawTextVScroll(ctx, -ctx->text.mult);
  416.  
  417.   EndAction(ctx);
  418. }
  419.  
  420. /*ARGSUSED*/
  421. static void 
  422. ScrollOneLineUp(w, event, p, n)
  423. Widget w;
  424. XEvent *event;
  425. String *p;
  426. Cardinal *n;
  427. {
  428.   Scroll( (TextWidget) w, event, XawsdLeft);
  429. }
  430.  
  431. /*ARGSUSED*/
  432. static void 
  433. ScrollOneLineDown(w, event, p, n)
  434. Widget w;
  435. XEvent *event;
  436. String *p;
  437. Cardinal *n;
  438. {
  439.   Scroll( (TextWidget) w, event, XawsdRight);
  440. }
  441.  
  442. static void 
  443. MovePage(ctx, event, dir)
  444. TextWidget ctx;
  445. XEvent *event;
  446. XawTextScanDirection dir;
  447. {
  448.   int scroll_val = Max(1, ctx->text.lt.lines - 2);
  449.  
  450.   if (dir == XawsdLeft)
  451.     scroll_val = -scroll_val;
  452.  
  453.   StartAction(ctx, event);
  454.   _XawTextVScroll(ctx, scroll_val);
  455.   ctx->text.insertPos = ctx->text.lt.top;
  456.   EndAction(ctx);
  457. }
  458.  
  459. /*ARGSUSED*/
  460. static void 
  461. MoveNextPage(w, event, p, n)
  462. Widget w;
  463. XEvent *event;
  464. String *p;
  465. Cardinal *n;
  466. {
  467.   MovePage((TextWidget) w, event, XawsdRight);
  468. }
  469.  
  470. /*ARGSUSED*/
  471. static void 
  472. MovePreviousPage(w, event, p, n)
  473. Widget w;
  474. XEvent *event;
  475. String *p;
  476. Cardinal *n;
  477. {
  478.   MovePage((TextWidget) w, event, XawsdLeft);
  479. }
  480.  
  481. /************************************************************
  482.  *
  483.  * Delete Routines.
  484.  *
  485.  ************************************************************/
  486.  
  487. static void 
  488. _DeleteOrKill(ctx, from, to, kill)
  489. TextWidget ctx;
  490. XawTextPosition from, to;
  491. Boolean    kill;
  492. {
  493.   XawTextBlock text;
  494.   char *ptr;
  495.   
  496.   if (kill && from < to) {
  497.     ptr = _XawTextGetText(ctx, from, to);
  498.     XStoreBuffer(XtDisplay(ctx), ptr, strlen(ptr), 1);
  499.     XtFree(ptr);
  500.   }
  501.   text.length = 0;
  502.   text.firstPos = 0;
  503.   if (_XawTextReplace(ctx, from, to, &text)) {
  504.     XBell(XtDisplay(ctx), 50);
  505.     return;
  506.   }
  507.   ctx->text.insertPos = from;
  508.   ctx->text.showposition = TRUE; 
  509. }
  510.  
  511. static void
  512. DeleteOrKill(ctx, event, dir, type, include, kill)
  513. TextWidget       ctx;
  514. XEvent *event;
  515. XawTextScanDirection dir;
  516. XawTextScanType type;
  517. Boolean       include, kill;
  518. {
  519.   XawTextPosition from, to;
  520.   
  521.   StartAction(ctx, event);
  522.   to = SrcScan(ctx->text.source, ctx->text.insertPos,
  523.            type, dir, ctx->text.mult, include);
  524.  
  525. /*
  526.  * If no movement actually happened, then bump the count and try again. 
  527.  * This causes the character position at the very beginning and end of 
  528.  * a boundry to act correctly. 
  529.  */
  530.  
  531.   if (to == ctx->text.insertPos)
  532.       to = SrcScan(ctx->text.source, ctx->text.insertPos,
  533.            type, dir, ctx->text.mult + 1, include);
  534.  
  535.   if (dir == XawsdLeft) {
  536.     from = to;
  537.     to = ctx->text.insertPos;
  538.   }
  539.   else 
  540.     from = ctx->text.insertPos;
  541.  
  542.   _DeleteOrKill(ctx, from, to, kill);
  543.   _XawTextSetScrollBars(ctx);
  544.   EndAction(ctx);
  545. }
  546.  
  547. /*ARGSUSED*/
  548. static void 
  549. DeleteForwardChar(w, event, p, n)
  550. Widget w;
  551. XEvent *event;
  552. String *p;
  553. Cardinal *n;
  554. {
  555.   DeleteOrKill((TextWidget) w, event, XawsdRight, XawstPositions, TRUE, FALSE);
  556. }
  557.  
  558. /*ARGSUSED*/
  559. static void
  560. DeleteBackwardChar(w, event, p, n)
  561. Widget w;
  562. XEvent *event;
  563. String *p;
  564. Cardinal *n;
  565. {
  566.   DeleteOrKill((TextWidget) w, event, XawsdLeft, XawstPositions, TRUE, FALSE);
  567. }
  568.  
  569. /*ARGSUSED*/
  570. static void 
  571. DeleteForwardWord(w, event, p, n)
  572. Widget w;
  573. XEvent *event;
  574. String *p;
  575. Cardinal *n;
  576. {
  577.   DeleteOrKill((TextWidget) w, event,
  578.            XawsdRight, XawstWhiteSpace, FALSE, FALSE);
  579. }
  580.  
  581. /*ARGSUSED*/
  582. static void 
  583. DeleteBackwardWord(w, event, p, n)
  584. Widget w;
  585. XEvent *event;
  586. String *p;
  587. Cardinal *n;
  588. {
  589.   DeleteOrKill((TextWidget) w, event,
  590.            XawsdLeft, XawstWhiteSpace, FALSE, FALSE);
  591. }
  592.  
  593. /*ARGSUSED*/
  594. static void 
  595. KillForwardWord(w, event, p, n)
  596. Widget w;
  597. XEvent *event;
  598. String *p;
  599. Cardinal *n;
  600. {
  601.   DeleteOrKill((TextWidget) w, event, 
  602.            XawsdRight, XawstWhiteSpace, FALSE, TRUE);
  603. }
  604.  
  605. /*ARGSUSED*/
  606. static void 
  607. KillBackwardWord(w, event, p, n)
  608. Widget w;
  609. XEvent *event;
  610. String *p;
  611. Cardinal *n;
  612. {
  613.   DeleteOrKill((TextWidget) w, event,
  614.            XawsdLeft, XawstWhiteSpace, FALSE, TRUE);
  615. }
  616.  
  617. /*ARGSUSED*/
  618. static void
  619. KillToEndOfLine(w, event, p, n)
  620. Widget w;
  621. XEvent *event;
  622. String *p;
  623. Cardinal *n;
  624. {
  625.   TextWidget ctx = (TextWidget) w;
  626.   XawTextPosition end_of_line;
  627.  
  628.   StartAction(ctx, event);
  629.   end_of_line = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, 
  630.             XawsdRight, ctx->text.mult, FALSE);
  631.   if (end_of_line == ctx->text.insertPos)
  632.     end_of_line = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, 
  633.               XawsdRight, ctx->text.mult, TRUE);
  634.  
  635.   _DeleteOrKill(ctx, ctx->text.insertPos, end_of_line, TRUE);
  636.   EndAction(ctx);
  637.   _XawTextSetScrollBars(ctx);
  638. }
  639.  
  640. /*ARGSUSED*/
  641. static void 
  642. KillToEndOfParagraph(w, event, p, n)
  643. Widget w;
  644. XEvent *event;
  645. String *p;
  646. Cardinal *n;
  647. {
  648.   DeleteOrKill((TextWidget) w, event, XawsdRight, XawstParagraph, FALSE, TRUE);
  649. }
  650.  
  651. void 
  652. _XawTextZapSelection(ctx, event, kill)
  653. TextWidget ctx;
  654. XEvent *event;
  655. Boolean kill;
  656. {
  657.    StartAction(ctx, event);
  658.    _DeleteOrKill(ctx, ctx->text.s.left, ctx->text.s.right, kill);
  659.    EndAction(ctx);
  660.   _XawTextSetScrollBars(ctx);
  661. }
  662.  
  663. /*ARGSUSED*/
  664. static void 
  665. KillCurrentSelection(w, event, p, n)
  666. Widget w;
  667. XEvent *event;
  668. String *p;
  669. Cardinal *n;
  670. {
  671.   _XawTextZapSelection( (TextWidget) w, event, TRUE);
  672. }
  673.  
  674. /*ARGSUSED*/
  675. static void 
  676. DeleteCurrentSelection(w, event, p, n)
  677. Widget w;
  678. XEvent *event;
  679. String *p;
  680. Cardinal *n;
  681. {
  682.   _XawTextZapSelection( (TextWidget) w, event, FALSE);
  683. }
  684.  
  685. /************************************************************
  686.  *
  687.  * Insertion Routines.
  688.  *
  689.  ************************************************************/
  690.  
  691. static int 
  692. InsertNewLineAndBackupInternal(ctx)
  693. TextWidget ctx;
  694. {
  695.   int count, error = XawEditDone;
  696.   XawTextBlock text;
  697.   char *buf, *ptr;
  698.  
  699.   ptr = buf = XtMalloc(sizeof(char) * ctx->text.mult);
  700.   for (count = 0; count < ctx->text.mult; count++, ptr++)
  701.     ptr[0] = '\n';
  702.  
  703.   text.length = ctx->text.mult;
  704.   text.ptr = buf;
  705.   text.firstPos = 0;
  706.   text.format = FMT8BIT;
  707.  
  708.   if (_XawTextReplace(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) {
  709.     XBell( XtDisplay(ctx), 50);
  710.     error = XawEditError;
  711.   }
  712.   else 
  713.     ctx->text.showposition = TRUE;
  714.  
  715.   XtFree(buf);
  716.   return(error);
  717. }
  718.  
  719. /*ARGSUSED*/
  720. static void 
  721. InsertNewLineAndBackup(w, event, p, n)
  722. Widget w;
  723. XEvent *event;
  724. String *p;
  725. Cardinal *n;
  726. {
  727.   StartAction( (TextWidget) w, event );
  728.   (void) InsertNewLineAndBackupInternal( (TextWidget) w );
  729.   EndAction( (TextWidget) w );
  730.   _XawTextSetScrollBars( (TextWidget) w);
  731. }
  732.  
  733. static int
  734. LocalInsertNewLine(ctx, event)
  735. TextWidget ctx;
  736. XEvent *event;
  737. {
  738.   StartAction(ctx, event);
  739.   if (InsertNewLineAndBackupInternal(ctx) == XawEditError)
  740.     return(XawEditError);
  741.   ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos, 
  742.                  XawstPositions, XawsdRight, ctx->text.mult, TRUE);
  743.   EndAction(ctx);
  744.   _XawTextSetScrollBars(ctx);
  745.   return(XawEditDone);
  746. }
  747.  
  748. /*ARGSUSED*/
  749. static void
  750. InsertNewLine(w, event, p, n)
  751. Widget w;
  752. XEvent *event;
  753. String *p;
  754. Cardinal *n;
  755. {
  756.   (void) LocalInsertNewLine( (TextWidget) w, event);
  757. }
  758.  
  759. /*ARGSUSED*/
  760. static void 
  761. InsertNewLineAndIndent(w, event, p, n)
  762. Widget w;
  763. XEvent *event;
  764. String *p;
  765. Cardinal *n;
  766. {
  767.   XawTextBlock text;
  768.   XawTextPosition pos1;
  769.   register char *ptr;
  770.   register int length;
  771.   TextWidget ctx = (TextWidget) w;
  772.  
  773.   StartAction(ctx, event);
  774.   pos1 = SrcScan(ctx->text.source, ctx->text.insertPos, 
  775.          XawstEOL, XawsdLeft, 1, FALSE);
  776.  
  777.   /* Hacked because Ascii Source Object Scan method is permanently broken. */
  778.   text.ptr = _XawTextGetText(ctx, pos1, ctx->text.insertPos);
  779.   length = strlen(text.ptr);
  780.   for (ptr=text.ptr; length && isspace(*ptr); ptr++, length--)
  781.       ;
  782.   *ptr = '\0';
  783.  
  784.   text.length = strlen(text.ptr);
  785.   if (LocalInsertNewLine(ctx, event)) {
  786.       XtFree(text.ptr);
  787.       return;
  788.   }
  789.   text.firstPos = 0;
  790.   if (_XawTextReplace(ctx,ctx->text.insertPos, ctx->text.insertPos, &text)) {
  791.     XBell(XtDisplay(ctx), 50);
  792.     XtFree(text.ptr);
  793.     EndAction(ctx);
  794.     return;
  795.   }
  796.   ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos,
  797.                 XawstPositions, XawsdRight, text.length, TRUE);
  798.   XtFree(text.ptr);
  799.   EndAction(ctx);
  800.   _XawTextSetScrollBars(ctx);
  801. }
  802.  
  803. /************************************************************
  804.  *
  805.  * Selection Routines.
  806.  *
  807.  *************************************************************/
  808.  
  809. static void 
  810. SelectWord(w, event, params, num_params)
  811. Widget w;
  812. XEvent *event;
  813. String *params;
  814. Cardinal *num_params;
  815. {
  816.   TextWidget ctx = (TextWidget) w;
  817.   XawTextPosition l, r;
  818.  
  819.   StartAction(ctx, event);
  820.   l = SrcScan(ctx->text.source, ctx->text.insertPos, 
  821.           XawstWhiteSpace, XawsdLeft, 1, FALSE);
  822.   r = SrcScan(ctx->text.source, l, XawstWhiteSpace, XawsdRight, 1, FALSE);
  823.   _XawTextSetSelection(ctx, l, r, params, *num_params);
  824.   EndAction(ctx);
  825. }
  826.  
  827. static void 
  828. SelectAll(w, event, params, num_params)
  829. Widget w;
  830. XEvent *event;
  831. String *params;
  832. Cardinal *num_params;
  833. {
  834.   TextWidget ctx = (TextWidget) w;
  835.  
  836.   StartAction(ctx, event);
  837.   _XawTextSetSelection(ctx,zeroPosition,ctx->text.lastPos,params,*num_params);
  838.   EndAction(ctx);
  839. }
  840.  
  841. static void
  842. ModifySelection(ctx, event, mode, action, params, num_params)
  843. TextWidget ctx;
  844. XEvent *event;
  845. XawTextSelectionMode mode;
  846. XawTextSelectionAction action;
  847. String *params;        /* unused */
  848. Cardinal *num_params;    /* unused */
  849. {
  850.   StartAction(ctx, event);
  851.   _XawTextAlterSelection(ctx, mode, action, params, num_params);
  852.   EndAction(ctx);
  853. }
  854.         
  855. /* ARGSUSED */
  856. static void 
  857. SelectStart(w, event, params, num_params)
  858. Widget w;
  859. XEvent *event;
  860. String *params;        /* unused */
  861. Cardinal *num_params;    /* unused */
  862. {
  863.   ModifySelection((TextWidget) w, event, 
  864.           XawsmTextSelect, XawactionStart, params, num_params);
  865. }
  866.  
  867. /* ARGSUSED */
  868. static void 
  869. SelectAdjust(w, event, params, num_params)
  870. Widget w;
  871. XEvent *event;
  872. String *params;        /* unused */
  873. Cardinal *num_params;    /* unused */
  874. {
  875.   ModifySelection((TextWidget) w, event, 
  876.           XawsmTextSelect, XawactionAdjust, params, num_params);
  877. }
  878.  
  879. static void 
  880. SelectEnd(w, event, params, num_params)
  881. Widget w;
  882. XEvent *event;
  883. String *params;
  884. Cardinal *num_params;
  885. {
  886.   ModifySelection((TextWidget) w, event, 
  887.           XawsmTextSelect, XawactionEnd, params, num_params);
  888. }
  889.  
  890. /* ARGSUSED */
  891. static void 
  892. ExtendStart(w, event, params, num_params)
  893. Widget w;
  894. XEvent *event;
  895. String *params;        /* unused */
  896. Cardinal *num_params;    /* unused */
  897. {
  898.   ModifySelection((TextWidget) w, event, 
  899.           XawsmTextExtend, XawactionStart, params, num_params);
  900. }
  901.  
  902. /* ARGSUSED */
  903. static void 
  904. ExtendAdjust(w, event, params, num_params)
  905. Widget w;
  906. XEvent *event;
  907. String *params;        /* unused */
  908. Cardinal *num_params;    /* unused */
  909. {
  910.   ModifySelection((TextWidget) w, event, 
  911.           XawsmTextExtend, XawactionAdjust, params, num_params);
  912. }
  913.  
  914. static void 
  915. ExtendEnd(w, event, params, num_params)
  916. Widget w;
  917. XEvent *event;
  918. String *params;
  919. Cardinal *num_params;
  920. {
  921.   ModifySelection((TextWidget) w, event, 
  922.           XawsmTextExtend, XawactionEnd, params, num_params);
  923. }
  924.  
  925. static void
  926. SelectSave(w, event, params, num_params)
  927. Widget  w;
  928. XEvent *event;
  929. String *params;
  930. Cardinal *num_params;
  931. {
  932.     int        num_atoms;
  933.     Atom*   sel;
  934.     Display* dpy = XtDisplay(w);
  935.     Atom    selections[256];
  936.  
  937.     StartAction (w, event);
  938.     num_atoms = *num_params;
  939.     if (num_atoms > 256)
  940.     num_atoms = 256;
  941.     for (sel=selections; --num_atoms >= 0; sel++, params++)
  942.     *sel = XInternAtom(dpy, *params, False);
  943.     num_atoms = *num_params;
  944.     _XawTextSaltAwaySelection (w, selections, num_atoms);
  945.     EndAction (w);
  946. }
  947.  
  948. /************************************************************
  949.  *
  950.  * Misc. Routines.
  951.  *
  952.  ************************************************************/
  953.  
  954. /* ARGSUSED */
  955. static void 
  956. RedrawDisplay(w, event, p, n)
  957. Widget w;
  958. XEvent *event;
  959. String *p;
  960. Cardinal *n;
  961. {
  962.   StartAction( (TextWidget) w, event);
  963.   _XawTextClearAndCenterDisplay((TextWidget) w);
  964.   EndAction( (TextWidget) w);
  965. }
  966.  
  967. /*ARGSUSED*/
  968. static void
  969. TextFocusIn (w, event, p, n)
  970. Widget w;
  971. XEvent *event;
  972. String *p;
  973. Cardinal *n;
  974. {
  975.   TextWidget ctx = (TextWidget) w;
  976.  
  977.   ctx->text.hasfocus = TRUE; 
  978. }
  979.  
  980. /*ARGSUSED*/
  981. static void
  982. TextFocusOut(w, event, p, n)
  983. Widget w;
  984. XEvent *event;
  985. String *p;
  986. Cardinal *n;
  987. {
  988.   TextWidget ctx = (TextWidget) w;
  989.  
  990.   ctx->text.hasfocus = FALSE;
  991. }
  992.  
  993. static XComposeStatus compose_status = {NULL, 0};
  994.  
  995. /*    Function Name: AutoFill
  996.  *    Description: Breaks the line at the previous word boundry when
  997.  *                   called inside InsertChar.
  998.  *    Arguments: ctx - The text widget.
  999.  *    Returns: none
  1000.  */
  1001.  
  1002. static void
  1003. AutoFill(ctx)
  1004. TextWidget ctx;
  1005. {
  1006.   int width, height, x, line_num, max_width;
  1007.   XawTextPosition ret_pos;
  1008.   XawTextBlock text;
  1009.  
  1010.   if ( !((ctx->text.auto_fill) && (ctx->text.mult == 1)) )
  1011.     return;
  1012.  
  1013.   for ( line_num = 0; line_num < ctx->text.lt.lines ; line_num++)
  1014.     if ( ctx->text.lt.info[line_num].position >= ctx->text.insertPos )
  1015.       break;
  1016.   line_num--;            /* backup a line. */
  1017.  
  1018.   max_width = Max(0, (int)(ctx->core.width - HMargins(ctx)));
  1019.  
  1020.   x = ctx->text.margin.left;
  1021.   XawTextSinkFindPosition( ctx->text.sink,ctx->text.lt.info[line_num].position,
  1022.               x, max_width, TRUE, &ret_pos, &width, &height);
  1023.   
  1024.   if ( ret_pos >= ctx->text.insertPos )
  1025.     return;
  1026.   
  1027.   text.ptr = "\n";
  1028.   text.length = 1;
  1029.   text.firstPos = 0;
  1030.   text.format = FMT8BIT;
  1031.  
  1032.   if (_XawTextReplace(ctx, ret_pos - 1, ret_pos, &text))
  1033.     XBell(XtDisplay((Widget) ctx), 0);    /* Unable to edit, complain. */
  1034.  
  1035. }
  1036.  
  1037. /*ARGSUSED*/
  1038. static void
  1039. InsertChar(w, event, p, n)
  1040. Widget w;
  1041. XEvent *event;
  1042. String *p;
  1043. Cardinal *n;
  1044. {
  1045.   TextWidget ctx = (TextWidget) w;
  1046.   char *ptr, strbuf[BUFSIZ];
  1047.   int count, error;
  1048.   KeySym keysym;
  1049.   XawTextBlock text;
  1050.  
  1051.   if ( (text.length = XLookupString (&event->xkey, strbuf, BUFSIZ,
  1052.                    &keysym, &compose_status)) == 0) {
  1053.     return;
  1054.   }
  1055.   
  1056.   text.ptr = ptr = XtMalloc(sizeof(char) * text.length * ctx->text.mult);
  1057.   for (count = 0 ; count < ctx->text.mult ; count++) {
  1058.     strncpy(ptr, strbuf, text.length);
  1059.     ptr += text.length;
  1060.   }
  1061.  
  1062.   text.length = text.length * ctx->text.mult;
  1063.   text.firstPos = 0;
  1064.   text.format = FMT8BIT;
  1065.   
  1066.   StartAction(ctx, event);
  1067.   
  1068.   error = _XawTextReplace(ctx, ctx->text.insertPos,ctx->text.insertPos, &text);
  1069.  
  1070.   if (error == XawEditDone) {
  1071.     ctx->text.insertPos = 
  1072.       SrcScan(ctx->text.source, ctx->text.insertPos,
  1073.           XawstPositions, XawsdRight, text.length, TRUE);
  1074.     AutoFill(ctx);
  1075.   }
  1076.   else 
  1077.     XBell(XtDisplay(ctx), 50);
  1078.  
  1079.   XtFree(text.ptr);
  1080.   EndAction(ctx);
  1081.   _XawTextSetScrollBars(ctx);
  1082. }
  1083.  
  1084. /*ARGSUSED*/
  1085. static void 
  1086. InsertString(w, event, params, num_params)
  1087. Widget w;
  1088. XEvent *event;
  1089. String *params;
  1090. Cardinal *num_params;
  1091. {
  1092.   TextWidget ctx = (TextWidget) w;
  1093.   XawTextBlock text;
  1094.   int       i;
  1095.  
  1096.   text.firstPos = 0;
  1097.   StartAction(ctx, event);
  1098.   for (i = *num_params; i; i--, params++) {
  1099.     unsigned char hexval;
  1100.     if ((*params)[0] == '0' && (*params)[1] == 'x' && (*params)[2] != '\0') {
  1101.       char c, *p;
  1102.       hexval = 0;
  1103.       for (p = *params+2; (c = *p); p++) {
  1104.     hexval *= 16;
  1105.     if (c >= '0' && c <= '9')
  1106.       hexval += c - '0';
  1107.     else if (c >= 'a' && c <= 'f')
  1108.       hexval += c - 'a' + 10;
  1109.     else if (c >= 'A' && c <= 'F')
  1110.       hexval += c - 'A' + 10;
  1111.     else break;
  1112.       }
  1113.       if (c == '\0') {
  1114.     text.ptr = (char*)&hexval;
  1115.     text.length = 1;
  1116.       } else text.length = strlen(text.ptr = *params);
  1117.     } else text.length = strlen(text.ptr = *params);
  1118.     if (text.length == 0) continue;
  1119.     if (_XawTextReplace(ctx, ctx->text.insertPos, 
  1120.             ctx->text.insertPos, &text)) {
  1121.       XBell(XtDisplay(ctx), 50);
  1122.       EndAction(ctx);
  1123.       return;
  1124.     }
  1125.     ctx->text.insertPos =
  1126.       SrcScan(ctx->text.source, ctx->text.insertPos,
  1127.           XawstPositions, XawsdRight, text.length, TRUE);
  1128.   }
  1129.   EndAction(ctx);
  1130. }
  1131.  
  1132. static void 
  1133. DisplayCaret(w, event, params, num_params)
  1134. Widget w;
  1135. XEvent *event;        /* CrossingNotify special-cased */
  1136. String *params;        /* Off, False, No, On, True, Yes, etc. */
  1137. Cardinal *num_params;    /* 0, 1 or 2 */
  1138. {
  1139.   TextWidget ctx = (TextWidget)w;
  1140.   Boolean display_caret = True;
  1141.  
  1142.   if (event->type == EnterNotify || event->type == LeaveNotify) {
  1143.     /* for Crossing events, the default case is to check the focus
  1144.      * field and only change the caret when focus==True.  A second
  1145.      * argument of "always" will cause the focus field to be ignored.
  1146.      */
  1147.     Boolean check_focus = True;
  1148.     if (*num_params == 2 && strcmp(params[1], "always") == 0)
  1149.       check_focus = False;
  1150.     if (check_focus && !event->xcrossing.focus) return;
  1151.   }
  1152.  
  1153.   if (*num_params > 0) {    /* default arg is "True" */
  1154.     XrmValue from, to;
  1155.     from.size = strlen(from.addr = params[0]);
  1156.     XtConvert(w, XtRString, &from, XtRBoolean, &to);
  1157.     if (to.addr != NULL) display_caret = *(Boolean*)to.addr;
  1158.     if (ctx->text.display_caret == display_caret) return;
  1159.   }
  1160.   StartAction(ctx, event);
  1161.   ctx->text.display_caret = display_caret;
  1162.   EndAction(ctx);
  1163. }
  1164.  
  1165. /*    Function Name: Multiply
  1166.  *    Description: Multiplies the current action by the number passed.
  1167.  *    Arguments: w - the text widget.
  1168.  *                 event - ** NOT USED **.
  1169.  *                 params, num_params - The parameter list, see below.
  1170.  *    Returns: none.
  1171.  *
  1172.  * Parameter list;
  1173.  *  
  1174.  * The parameter list may contain either a number or the string 'Reset'.
  1175.  * 
  1176.  * A number will multiply the current multiplication factor by that number.
  1177.  * Many of the text widget actions will will perform n actions, where n is
  1178.  * the multiplication factor.
  1179.  *
  1180.  * The string reset will reset the mutiplication factor to 1.
  1181.  * 
  1182.  */
  1183.  
  1184. /* ARGSUSED */
  1185. static void 
  1186. Multiply(w, event, params, num_params)
  1187. Widget w;
  1188. XEvent *event;
  1189. String * params;
  1190. Cardinal * num_params;
  1191. {
  1192.   TextWidget ctx = (TextWidget) w;
  1193.   int mult;
  1194.  
  1195.   if (*num_params != 1) {
  1196.     XtAppError(XtWidgetToApplicationContext(w), 
  1197.            "The multiply action takes exactly one argument.");
  1198.     XBell(XtDisplay(w), 0);
  1199.     return;
  1200.   }
  1201.  
  1202.   if ( (params[0][0] == 'r') || (params[0][0] == 'R') ) {
  1203.     XBell(XtDisplay(w), 0);
  1204.     ctx->text.mult = 1;
  1205.     return;
  1206.   }
  1207.  
  1208.   if ( (mult = atoi(params[0])) == 0 ) {
  1209.     char buf[BUFSIZ];
  1210.     sprintf(buf, "%s %s", "Text Widget: The multiply action's argument",
  1211.         "must be a number greater than zero, or 'Reset'.");
  1212.     XtAppError(XtWidgetToApplicationContext(w), buf);
  1213.     XBell(XtDisplay(w), 0);
  1214.     return;
  1215.   }
  1216.  
  1217.   ctx->text.mult *= mult;
  1218. }
  1219.  
  1220. /*    Function Name: StripOutOldCRs
  1221.  *    Description: strips out the old carrige returns.
  1222.  *    Arguments: ctx - the text widget.
  1223.  *                 from - starting point.
  1224.  *                 to - the ending point
  1225.  *    Returns: the new ending location (we may add some characters),
  1226.  *         or XawTextReplaceError, which indicates failure.
  1227.  */
  1228.  
  1229. static XawTextPosition
  1230. StripOutOldCRs(ctx, from, to)
  1231. TextWidget ctx;
  1232. XawTextPosition from, to;
  1233. {
  1234.   XawTextPosition startPos, endPos, eop_begin, eop_end, temp;
  1235.   Widget src = ctx->text.source;
  1236.   XawTextBlock text;
  1237.   char *buf;
  1238.  
  1239.   text.ptr= "  ";
  1240.   text.firstPos = 0;
  1241.   text.format = FMT8BIT;
  1242.    
  1243. /*
  1244.  * Strip out CR's. 
  1245.  */
  1246.  
  1247.   eop_begin = eop_end = startPos = endPos = from;
  1248.   while (TRUE) {
  1249.     endPos=SrcScan(src, startPos, XawstEOL, XawsdRight, 1, FALSE);
  1250.  
  1251.     temp=SrcScan(src, endPos, XawstWhiteSpace, XawsdLeft, 1, FALSE);
  1252.     temp=SrcScan(src, temp, XawstWhiteSpace, XawsdRight, 1, FALSE);
  1253.  
  1254.     if (temp > startPos)
  1255.     endPos = temp;
  1256.  
  1257.     if (endPos >= to)
  1258.       break;
  1259.  
  1260.     if (endPos >= eop_begin) {
  1261.       startPos = eop_end;
  1262.       eop_begin = SrcScan(src, startPos, XawstParagraph, XawsdRight, 1, FALSE);
  1263.       eop_end = SrcScan(src, startPos, XawstParagraph, XawsdRight, 1, TRUE);
  1264.     }
  1265.     else {
  1266.       XawTextPosition periodPos, next_word;
  1267.       int i, len;
  1268.  
  1269.       periodPos= SrcScan(src, endPos, XawstPositions, XawsdLeft, 1, TRUE);
  1270.       next_word = SrcScan(src, endPos, XawstWhiteSpace, XawsdRight, 1, FALSE);
  1271.  
  1272.       len = next_word - periodPos;
  1273.  
  1274.       text.length = 1;
  1275.       buf = _XawTextGetText(ctx, periodPos, next_word);
  1276.       if ( (periodPos < endPos) && (buf[0] == '.') )
  1277.       text.length++;    /* Put in two spaces. */
  1278.  
  1279.       /*
  1280.        * Remove all extra spaces. 
  1281.        */
  1282.  
  1283.       for (i = 1 ; i < len; i++) 
  1284.       if ( !isspace(buf[i]) || ((periodPos + i) >= to) ) {
  1285.           break;
  1286.       }
  1287.       
  1288.       XtFree(buf);
  1289.  
  1290.       to -= (i - text.length - 1);
  1291.       startPos = SrcScan(src, periodPos, XawstPositions, XawsdRight, i, TRUE);
  1292.       if (_XawTextReplace(ctx, endPos, startPos, &text) != XawEditDone)
  1293.       return XawReplaceError;
  1294.       startPos -= i - text.length;
  1295.     }
  1296.   }
  1297.   return(to);
  1298. }
  1299.  
  1300. /*    Function Name: InsertNewCRs
  1301.  *    Description: Inserts the new Carrige Returns.
  1302.  *    Arguments: ctx - the text widget.
  1303.  *                 from, to - the ends of the region.
  1304.  *    Returns: none
  1305.  */
  1306.  
  1307. static void
  1308. InsertNewCRs(ctx, from, to)
  1309. TextWidget ctx;
  1310. XawTextPosition from, to;
  1311. {
  1312.   XawTextPosition startPos, endPos, space, eol;
  1313.   XawTextBlock text;
  1314.   int i, width, height, len;
  1315.   char * buf;
  1316.  
  1317.   text.ptr = "\n";
  1318.   text.length = 1;
  1319.   text.firstPos = 0;
  1320.   text.format = FMT8BIT;
  1321.  
  1322.   startPos = from;
  1323.   while (TRUE) {
  1324.     XawTextSinkFindPosition( ctx->text.sink, startPos, 
  1325.                 (int) ctx->text.margin.left,
  1326.                 (int) (ctx->core.width - HMargins(ctx)), 
  1327.                 TRUE, &eol, &width, &height);
  1328.     if (eol >= to)
  1329.       break;
  1330.  
  1331.     eol = SrcScan(ctx->text.source, eol, XawstPositions, XawsdLeft, 1, TRUE);
  1332.     space= SrcScan(ctx->text.source, eol, XawstWhiteSpace, XawsdRight, 1,TRUE);
  1333.     
  1334.     startPos = endPos = eol;
  1335.     if (eol == space) 
  1336.       return;
  1337.  
  1338.     len = (int) (space - eol);
  1339.     buf = _XawTextGetText(ctx, eol, space);
  1340.     for ( i = 0 ; i < len ; i++)
  1341.       if (!isspace(buf[i]))
  1342.     break;
  1343.  
  1344.     to -= (i - 1);
  1345.     endPos = SrcScan(ctx->text.source, endPos,
  1346.              XawstPositions, XawsdRight, i, TRUE);
  1347.     XtFree(buf);
  1348.     
  1349.     if (_XawTextReplace(ctx, startPos, endPos, &text))
  1350.     return;
  1351.     startPos = SrcScan(ctx->text.source, startPos,
  1352.                XawstPositions, XawsdRight, 1, TRUE);
  1353.   }
  1354. }  
  1355.   
  1356. /*    Function Name: FormRegion
  1357.  *    Description: Forms up the region specified.
  1358.  *    Arguments: ctx - the text widget.
  1359.  *                 from, to - the ends of the region.
  1360.  *    Returns: XawEditDone if successful, or XawReplaceError.
  1361.  */
  1362.  
  1363. static int
  1364. FormRegion(ctx, from, to)
  1365. TextWidget ctx;
  1366. XawTextPosition from, to;
  1367. {
  1368.   if (from >= to) return XawEditDone;
  1369.  
  1370.   if ((to = StripOutOldCRs(ctx, from, to)) == XawReplaceError)
  1371.       return XawReplaceError;
  1372.   /* insure that the insertion point is within legal bounds */
  1373.   if (ctx->text.insertPos >
  1374.       SrcScan(ctx->text.source, 0, XawstAll, XawsdRight, 1, TRUE))
  1375.       ctx->text.insertPos = to;
  1376.   InsertNewCRs(ctx, from, to);
  1377.   _XawTextBuildLineTable(ctx, ctx->text.lt.top, TRUE);
  1378.   return XawEditDone;
  1379. }
  1380.  
  1381. /*    Function Name: FormParagraph.
  1382.  *    Description: reforms up the current paragraph.
  1383.  *    Arguments: w - the text widget.
  1384.  *                 event - the X event.
  1385.  *                 params, num_params *** NOT USED ***.
  1386.  *    Returns: none
  1387.  */
  1388.  
  1389. /* ARGSUSED */
  1390. static void 
  1391. FormParagraph(w, event, params, num_params)
  1392. Widget w;
  1393. XEvent *event;
  1394. String * params;
  1395. Cardinal * num_params;
  1396. {
  1397.   TextWidget ctx = (TextWidget) w;
  1398.   XawTextPosition from, to;
  1399.  
  1400.   StartAction(ctx, event);
  1401.  
  1402.   from =  SrcScan(ctx->text.source, ctx->text.insertPos,
  1403.           XawstParagraph, XawsdLeft, 1, FALSE);
  1404.   to  =  SrcScan(ctx->text.source, from,
  1405.          XawstParagraph, XawsdRight, 1, FALSE);
  1406.  
  1407.   if (FormRegion(ctx, from, to) == XawReplaceError)
  1408.       XBell(XtDisplay(w), 0);
  1409.   EndAction(ctx);
  1410.   _XawTextSetScrollBars(ctx);
  1411. }
  1412.  
  1413. /*    Function Name: TransposeCharacters
  1414.  *    Description: Swaps the character to the left of the mark with
  1415.  *                   the character to the right of the mark.
  1416.  *    Arguments: w - the text widget.
  1417.  *                 event - the event that cause this action.
  1418.  *                 params, num_params *** NOT USED ***.
  1419.  *    Returns: none.
  1420.  */
  1421.          
  1422. /* ARGSUSED */
  1423. static void 
  1424. TransposeCharacters(w, event, params, num_params)
  1425. Widget w;
  1426. XEvent *event;
  1427. String * params;
  1428. Cardinal * num_params;
  1429. {
  1430.   TextWidget ctx = (TextWidget) w;
  1431.   XawTextPosition start, end;
  1432.   XawTextBlock text;
  1433.   unsigned char * buf, c;
  1434.   int i;
  1435.  
  1436.   StartAction(ctx, event);
  1437.  
  1438. /*
  1439.  * Get bounds. 
  1440.  */
  1441.  
  1442.   start = SrcScan(ctx->text.source, ctx->text.insertPos, XawstPositions, 
  1443.           XawsdLeft, 1, TRUE);
  1444.   end = SrcScan(ctx->text.source, ctx->text.insertPos, XawstPositions, 
  1445.         XawsdRight, ctx->text.mult, TRUE);
  1446.  
  1447.   if ( (start == ctx->text.insertPos) || (end == ctx->text.insertPos) ) 
  1448.     XBell(XtDisplay(w), 0);    /* complain. */
  1449.   else {
  1450.     ctx->text.insertPos = end;
  1451.  
  1452.     /*
  1453.      * Retrieve text and swap the characters. 
  1454.      */
  1455.     
  1456.     buf = (unsigned char *) _XawTextGetText(ctx, start, end);
  1457.     text.length = strlen((char *)buf);
  1458.     text.firstPos = 0;
  1459.     text.format = FMT8BIT;
  1460.     
  1461.     c = buf[0];
  1462.     for (i = 1 ; i < text.length ; i++)
  1463.       buf[i - 1] = buf[i];
  1464.     buf[i - 1] = c;
  1465.     
  1466.     /* 
  1467.      * Store new text is source.
  1468.      */
  1469.     
  1470.     text.ptr = (char *) buf;
  1471.     if (_XawTextReplace (ctx, start, end, &text))
  1472.     XBell(XtDisplay(w), 0);    /* Unable to edit, complain. */
  1473.     XtFree((char *) buf);
  1474.   }
  1475.   EndAction(ctx);
  1476. }
  1477.  
  1478. /*    Function Name: NoOp
  1479.  *    Description: This action performs no action, and allows
  1480.  *                   the user or application programmer to unbind a 
  1481.  *                   translation.
  1482.  *    Arguments: w - the text widget.
  1483.  *                 event - *** UNUSED ***.
  1484.  *                 parms and num_params - the action parameters.
  1485.  *    Returns: none.
  1486.  *
  1487.  * Note: If the parameter list contains the string "RingBell" then
  1488.  *       this action will ring the bell.
  1489.  */
  1490.  
  1491. /*ARGSUSED*/
  1492. static void
  1493. NoOp(w, event, params, num_params)
  1494. Widget w;
  1495. XEvent *event;
  1496. String *params;
  1497. Cardinal *num_params;
  1498. {
  1499.     if (*num_params != 1)
  1500.     return;
  1501.  
  1502.     switch(params[0][0]) {
  1503.     case 'R':
  1504.     case 'r':
  1505.     XBell(XtDisplay(w), 0);
  1506.     default:            /* Fall Through */
  1507.     break;
  1508.     }
  1509. }
  1510.     
  1511. /* Action Table */
  1512.  
  1513. XtActionsRec _XawTextActionsTable[] = {
  1514. /* motion bindings */
  1515.   {"forward-character",     MoveForwardChar},
  1516.   {"backward-character",     MoveBackwardChar},
  1517.   {"forward-word",         MoveForwardWord},
  1518.   {"backward-word",         MoveBackwardWord},
  1519.   {"forward-paragraph",     MoveForwardParagraph},
  1520.   {"backward-paragraph",     MoveBackwardParagraph},
  1521.   {"beginning-of-line",     MoveToLineStart},
  1522.   {"end-of-line",         MoveToLineEnd},
  1523.   {"next-line",         MoveNextLine},
  1524.   {"previous-line",         MovePreviousLine},
  1525.   {"next-page",         MoveNextPage},
  1526.   {"previous-page",         MovePreviousPage},
  1527.   {"beginning-of-file",     MoveBeginningOfFile},
  1528.   {"end-of-file",         MoveEndOfFile},
  1529.   {"scroll-one-line-up",     ScrollOneLineUp},
  1530.   {"scroll-one-line-down",     ScrollOneLineDown},
  1531. /* delete bindings */
  1532.   {"delete-next-character",     DeleteForwardChar},
  1533.   {"delete-previous-character", DeleteBackwardChar},
  1534.   {"delete-next-word",         DeleteForwardWord},
  1535.   {"delete-previous-word",     DeleteBackwardWord},
  1536.   {"delete-selection",         DeleteCurrentSelection},
  1537. /* kill bindings */
  1538.   {"kill-word",         KillForwardWord},
  1539.   {"backward-kill-word",     KillBackwardWord},
  1540.   {"kill-selection",         KillCurrentSelection},
  1541.   {"kill-to-end-of-line",     KillToEndOfLine},
  1542.   {"kill-to-end-of-paragraph",     KillToEndOfParagraph},
  1543. /* new line stuff */
  1544.   {"newline-and-indent",     InsertNewLineAndIndent},
  1545.   {"newline-and-backup",     InsertNewLineAndBackup},
  1546.   {"newline",             InsertNewLine},
  1547. /* Selection stuff */
  1548.   {"select-word",         SelectWord},
  1549.   {"select-all",         SelectAll},
  1550.   {"select-start",         SelectStart},
  1551.   {"select-adjust",         SelectAdjust},
  1552.   {"select-end",         SelectEnd},
  1553.   {"select-save",        SelectSave},
  1554.   {"extend-start",         ExtendStart},
  1555.   {"extend-adjust",         ExtendAdjust},
  1556.   {"extend-end",         ExtendEnd},
  1557.   {"insert-selection",        InsertSelection},
  1558. /* Miscellaneous */
  1559.   {"redraw-display",         RedrawDisplay},
  1560.   {"insert-file",         _XawTextInsertFile},
  1561.   {"search",                _XawTextSearch},
  1562.   {"insert-char",         InsertChar},
  1563.   {"insert-string",        InsertString},
  1564.   {"focus-in",                  TextFocusIn},
  1565.   {"focus-out",         TextFocusOut},
  1566.   {"display-caret",        DisplayCaret},
  1567.   {"multiply",                Multiply},
  1568.   {"form-paragraph",            FormParagraph},
  1569.   {"transpose-characters",      TransposeCharacters},
  1570.   {"no-op",                     NoOp},
  1571. /* Action to bind special translations for text Dialogs. */
  1572.   {"InsertFileAction",          _XawTextInsertFileAction},
  1573.   {"DoSearchAction",            _XawTextDoSearchAction},
  1574.   {"DoReplaceAction",           _XawTextDoReplaceAction},
  1575.   {"SetField",                  _XawTextSetField},
  1576.   {"PopdownSearchAction",       _XawTextPopdownSearchAction},
  1577. };
  1578.  
  1579. Cardinal _XawTextActionsTableCount = XtNumber(_XawTextActionsTable);
  1580.