TextAction.c

Go to the documentation of this file.
00001 /* $XConsortium: TextAction.c,v 1.53 95/06/14 15:07:27 kaleb Exp $ */
00002 
00003 /*
00004 
00005 Copyright (c) 1989, 1994  X Consortium
00006 
00007 Permission is hereby granted, free of charge, to any person obtaining a copy
00008 of this software and associated documentation files (the "Software"), to deal
00009 in the Software without restriction, including without limitation the rights
00010 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00011 copies of the Software, and to permit persons to whom the Software is
00012 furnished to do so, subject to the following conditions:
00013 
00014 The above copyright notice and this permission notice shall be included in
00015 all copies or substantial portions of the Software.
00016 
00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
00020 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00021 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023 
00024 Except as contained in this notice, the name of the X Consortium shall not be
00025 used in advertising or otherwise to promote the sale, use or other dealings
00026 in this Software without prior written authorization from the X Consortium.
00027 
00028 */
00029 #include <X11/IntrinsicP.h>
00030 #include <X11/StringDefs.h>
00031 #include <X11/Xutil.h>
00032 #include <X11/Xatom.h>
00033 #include <X11/Xmu/Misc.h>
00034 #include <X11/Xmu/StdSel.h>             /* for XmuConvertStandardSelection */
00035 #include <X11/Xmu/Atoms.h>              /* for XA_COMPOUND_TEXT */
00036 #include <X11/Xaw3d/TextP.h>
00037 #include <X11/Xaw3d/MultiSrcP.h>
00038 #include <X11/Xaw3d/XawImP.h>
00039 #include <X11/Xfuncs.h>
00040 #include "XawI18n.h"
00041 #include <stdio.h>
00042 #include <ctype.h>
00043 
00044 #define SrcScan                XawTextSourceScan
00045 #define FindDist               XawTextSinkFindDistance
00046 #define FindPos                XawTextSinkFindPosition
00047 
00048 #define XawTextActionMaxHexChars 100
00049 
00050 /*
00051  * These are defined in TextPop.c
00052  */
00053 
00054 void _XawTextInsertFileAction(), _XawTextInsertFile(), _XawTextSearch();
00055 void _XawTextSearch(), _XawTextDoSearchAction(), _XawTextDoReplaceAction();
00056 void _XawTextSetField(), _XawTextPopdownSearchAction();
00057 
00058 /*
00059  * These are defined in Text.c
00060  */
00061 
00062 char * _XawTextGetText();
00063 void _XawTextAlterSelection(), _XawTextVScroll();
00064 void _XawTextSetSelection(), _XawTextCheckResize(), _XawTextExecuteUpdate();
00065 void _XawTextSetScrollBars(), _XawTextClearAndCenterDisplay();
00066 Atom * _XawTextSelectionList();
00067 void _XawTextPrepareToUpdate();
00068 int _XawTextReplace();
00069 
00070 static void ParameterError(w, param)
00071     Widget w; 
00072     String param;
00073 {
00074     String params[2];
00075     Cardinal num_params = 2;
00076     params[0] = XtName(w);
00077     params[1] = param;
00078     
00079     XtAppWarningMsg( XtWidgetToApplicationContext(w),
00080         "parameterError", "textAction", "XawError",
00081         "Widget: %s Parameter: %s", 
00082         params, &num_params);
00083     XBell( XtDisplay( w ), 50 );
00084 }
00085 
00086 static void
00087 StartAction(ctx, event)
00088 TextWidget ctx;
00089 XEvent *event;
00090 {
00091   _XawTextPrepareToUpdate(ctx);
00092   if (event != NULL) {
00093     switch (event->type) {
00094     case ButtonPress:
00095     case ButtonRelease:
00096       ctx->text.time = event->xbutton.time;
00097       break;
00098     case KeyPress:
00099     case KeyRelease:
00100       ctx->text.time = event->xkey.time;
00101       break;
00102     case MotionNotify:
00103       ctx->text.time = event->xmotion.time;
00104       break;
00105     case EnterNotify:
00106     case LeaveNotify:
00107       ctx->text.time = event->xcrossing.time;
00108     }
00109   }
00110 }
00111 
00112 static void
00113 NotePosition(ctx, event)
00114 TextWidget ctx;
00115 XEvent* event;
00116 {
00117   switch (event->type) {
00118   case ButtonPress:
00119   case ButtonRelease:
00120     ctx->text.ev_x = event->xbutton.x;
00121     ctx->text.ev_y = event->xbutton.y;
00122     break;
00123   case KeyPress:
00124   case KeyRelease:
00125     {
00126       XRectangle cursor;
00127       XawTextSinkGetCursorBounds(ctx->text.sink, &cursor);
00128       ctx->text.ev_x = cursor.x + cursor.width / 2;;
00129       ctx->text.ev_y = cursor.y + cursor.height / 2;;
00130     }
00131     break;
00132   case MotionNotify:
00133     ctx->text.ev_x = event->xmotion.x;
00134     ctx->text.ev_y = event->xmotion.y;
00135     break;
00136   case EnterNotify:
00137   case LeaveNotify:
00138     ctx->text.ev_x = event->xcrossing.x;
00139     ctx->text.ev_y = event->xcrossing.y;
00140   }
00141 }
00142 
00143 static void
00144 EndAction(ctx)
00145 TextWidget ctx;
00146 {
00147   _XawTextCheckResize(ctx);
00148   _XawTextExecuteUpdate(ctx);
00149   ctx->text.mult = 1;
00150 }
00151 
00152 
00153 struct _SelectionList {
00154     String* params;
00155     Cardinal count;
00156     Time time;
00157     Boolean CT_asked;   /* flag if asked XA_COMPOUND_TEXT */
00158     Atom selection;     /* selection atom when asking XA_COMPOUND_TEXT */
00159 };
00160 
00161 static int ProbablyMB(s)
00162     char* s;
00163 {
00164     int escapes = 0;
00165     int has_hi_bit = False;
00166 
00167     /* if it has more than one ESC char, I assume it is COMPOUND_TEXT.
00168     If it has at least one hi bit set character, I pretend it is multibyte. */
00169 
00170     while ( (wchar_t)(*s) != (wchar_t)0 ) {
00171         if ( *s & 128 )
00172             has_hi_bit = True;
00173         if ( *s++ == '\033' )
00174             escapes++;
00175         if ( escapes >= 2 )
00176             return( 0 );
00177     }
00178     return( has_hi_bit );
00179 }
00180 static void GetSelection();
00181 
00182 /* ARGSUSED */
00183 static void 
00184 _SelectionReceived(w, client_data, selection, type, value, length, format)
00185 Widget w;
00186 XtPointer client_data;
00187 Atom *selection, *type;
00188 XtPointer value;
00189 unsigned long *length;
00190 int* format;
00191 {
00192   TextWidget ctx = (TextWidget)w;
00193   XawTextBlock text;
00194   
00195   if (*type == 0 /*XT_CONVERT_FAIL*/ || *length == 0) {
00196     struct _SelectionList* list = (struct _SelectionList*)client_data;
00197     if (list != NULL) {
00198       if (list->CT_asked) {
00199 
00200         /* If we just asked for a XA_COMPOUND_TEXT and got a null
00201         response, we'll ask again, this time for an XA_STRING. */
00202 
00203         list->CT_asked = False;
00204         XtGetSelectionValue(w, list->selection, XA_STRING, _SelectionReceived,
00205                             (XtPointer)list, list->time);
00206       } else {
00207         GetSelection(w, list->time, list->params, list->count);
00208         XtFree(client_data);
00209      }
00210     }
00211     return;
00212   }
00213 
00214   /* Many programs, especially old terminal emulators, give us multibyte text
00215 but tell us it is COMPOUND_TEXT :(  The following routine checks to see if the
00216 string is a legal multibyte string in our locale using a spooky heuristic :O
00217 and if it is we can only assume the sending client is using the same locale as
00218 we are, and convert it.  I also warn the user that the other client is evil. */
00219 
00220   StartAction( ctx, (XEvent*) NULL );
00221   if (_XawTextFormat(ctx) == XawFmtWide) {
00222       XTextProperty textprop;
00223       Display *d = XtDisplay((Widget)ctx);
00224       wchar_t **wlist;
00225       int count;
00226       int try_CT = 1;
00227 
00228       /* IS THE SELECTION IN MULTIBYTE FORMAT? */
00229 
00230       if ( ProbablyMB( (char *) value ) ) {
00231           char * list[1];
00232           list[0] = (char *) value;
00233           if ( XmbTextListToTextProperty( d, (char**) list, 1,
00234                                 XCompoundTextStyle, &textprop ) == Success )
00235               try_CT = 0;
00236       }
00237 
00238       /* OR IN COMPOUND TEXT FORMAT? */
00239 
00240       if ( try_CT ) {
00241           textprop.encoding = XA_COMPOUND_TEXT(d);
00242           textprop.value = (unsigned char *)value;
00243           textprop.nitems = strlen(value);
00244           textprop.format = 8;
00245       }
00246 
00247       if ( XwcTextPropertyToTextList( d, &textprop, (wchar_t***) &wlist, &count )
00248                 !=  Success) {
00249           XwcFreeStringList( (wchar_t**) wlist );
00250 
00251           /* Notify the user on strerr and in the insertion :) */
00252           textprop.value = (unsigned char *) " >> ILLEGAL SELECTION << ";
00253           count = 1;
00254           fprintf( stderr, "Xaw Text Widget: An attempt was made to insert an illegal selection.\n" );
00255 
00256           if ( XwcTextPropertyToTextList( d, &textprop, (wchar_t***) &wlist, &count )
00257                 !=  Success) return;
00258       }
00259 
00260       XFree(value);
00261       value = (XPointer)wlist[0];
00262 
00263       *length = wcslen(wlist[0]);
00264       XtFree((XtPointer)wlist);
00265       text.format = XawFmtWide;
00266   } else
00267       text.format = XawFmt8Bit;
00268   text.ptr = (char*)value;
00269   text.firstPos = 0;
00270   text.length = *length;
00271   if (_XawTextReplace(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) {
00272     XBell(XtDisplay(ctx), 0);
00273     return;
00274   }
00275   ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos, 
00276                                 XawstPositions, XawsdRight, text.length, TRUE);
00277 
00278   _XawTextSetScrollBars(ctx);
00279   EndAction(ctx);
00280   XtFree(client_data);
00281   XFree(value);         /* the selection value should be freed with XFree */
00282 }
00283 
00284 static void 
00285 GetSelection(w, time, params, num_params)
00286 Widget w;
00287 Time time;
00288 String* params;         /* selections in precedence order */
00289 Cardinal num_params;
00290 {
00291     Atom selection;
00292     int buffer;
00293 
00294     selection = XInternAtom(XtDisplay(w), *params, False);
00295 
00296     switch (selection) {
00297       case XA_CUT_BUFFER0: buffer = 0; break;
00298       case XA_CUT_BUFFER1: buffer = 1; break;
00299       case XA_CUT_BUFFER2: buffer = 2; break;
00300       case XA_CUT_BUFFER3: buffer = 3; break;
00301       case XA_CUT_BUFFER4: buffer = 4; break;
00302       case XA_CUT_BUFFER5: buffer = 5; break;
00303       case XA_CUT_BUFFER6: buffer = 6; break;
00304       case XA_CUT_BUFFER7: buffer = 7; break;
00305       default:         buffer = -1;
00306     }
00307     if (buffer >= 0) {
00308         int nbytes;
00309         unsigned long length;
00310         int fmt8 = 8;
00311         Atom type = XA_STRING;
00312         char *line = XFetchBuffer(XtDisplay(w), &nbytes, buffer);
00313         if ((length = nbytes))
00314             _SelectionReceived(w, (XtPointer) NULL, &selection, &type, (XPointer)line,
00315                                &length, &fmt8);
00316         else if (num_params > 1)
00317             GetSelection(w, time, params+1, num_params-1);
00318     } else {
00319         struct _SelectionList* list;
00320         if (--num_params) {
00321             list = XtNew(struct _SelectionList);
00322             list->params = params + 1;
00323             list->count = num_params;
00324             list->time = time;
00325             list->CT_asked = True;
00326             list->selection = selection;
00327         } else list = NULL;
00328         XtGetSelectionValue(w, selection, XA_COMPOUND_TEXT(XtDisplay(w)),
00329                             _SelectionReceived, (XtPointer)list, time);
00330     }
00331 }
00332 
00333 static void 
00334 InsertSelection(w, event, params, num_params)
00335 Widget w;
00336 XEvent* event;
00337 String* params;         /* precedence list of selections to try */
00338 Cardinal* num_params;
00339 {
00340   StartAction((TextWidget)w, event); /* Get Time. */
00341   GetSelection(w, ((TextWidget)w)->text.time, params, *num_params);
00342   EndAction((TextWidget)w);
00343 }
00344 
00345 /************************************************************
00346  *
00347  * Routines for Moving Around.
00348  *
00349  ************************************************************/
00350 
00351 static void
00352 Move(ctx, event, dir, type, include)
00353 TextWidget ctx;
00354 XEvent* event;
00355 XawTextScanDirection dir;
00356 XawTextScanType type;
00357 Boolean include;
00358 {
00359   StartAction(ctx, event);
00360   ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos,
00361                                 type, dir, ctx->text.mult, include);
00362   EndAction(ctx);
00363 }
00364 
00365 /*ARGSUSED*/
00366 static void 
00367 MoveForwardChar(w, event, p, n)
00368 Widget w;
00369 XEvent* event;
00370 String* p;
00371 Cardinal* n;
00372 {
00373    Move((TextWidget) w, event, XawsdRight, XawstPositions, TRUE);
00374 }
00375 
00376 /*ARGSUSED*/
00377 static void 
00378 MoveBackwardChar(w, event, p, n)
00379 Widget w;
00380 XEvent* event;
00381 String* p;
00382 Cardinal* n;
00383 {
00384   Move((TextWidget) w, event, XawsdLeft, XawstPositions, TRUE);
00385 }
00386 
00387 /*ARGSUSED*/
00388 static void 
00389 MoveForwardWord(w, event, p, n)
00390 Widget w;
00391 XEvent* event;
00392 String* p;
00393 Cardinal* n;
00394 {
00395   Move((TextWidget) w, event, XawsdRight, XawstWhiteSpace, FALSE);
00396 }
00397 
00398 /*ARGSUSED*/
00399 static void 
00400 MoveBackwardWord(w, event, p, n)
00401 Widget w;
00402 XEvent* event;
00403 String* p;
00404 Cardinal* n;
00405 {
00406   Move((TextWidget) w, event, XawsdLeft, XawstWhiteSpace, FALSE);
00407 }
00408 
00409 /*ARGSUSED*/
00410 static void MoveForwardParagraph(w, event, p, n)
00411 Widget w;
00412 XEvent* event;
00413 String* p;
00414 Cardinal* n;
00415 {
00416   Move((TextWidget) w, event, XawsdRight, XawstParagraph, FALSE);
00417 }
00418 
00419 /*ARGSUSED*/
00420 static void MoveBackwardParagraph(w, event, p, n)
00421 Widget w;
00422 XEvent* event;
00423 String* p;
00424 Cardinal* n;
00425 {
00426   Move((TextWidget) w, event, XawsdLeft, XawstParagraph, FALSE);
00427 }
00428 
00429 /*ARGSUSED*/
00430 static void 
00431 MoveToLineEnd(w, event, p, n)
00432 Widget w;
00433 XEvent* event;
00434 String* p;
00435 Cardinal* n;
00436 {
00437   Move((TextWidget) w, event, XawsdRight, XawstEOL, FALSE);
00438 }
00439 
00440 /*ARGSUSED*/
00441 static void 
00442 MoveToLineStart(w, event, p, n)
00443 Widget w;
00444 XEvent* event;
00445 String* p;
00446 Cardinal* n;
00447 {
00448   Move((TextWidget) w, event, XawsdLeft, XawstEOL, FALSE);
00449 }
00450 
00451 
00452 static void
00453 MoveLine(ctx, event, dir)
00454 TextWidget ctx;
00455 XEvent* event;
00456 XawTextScanDirection dir;
00457 {
00458   XawTextPosition new, next_line, junk;
00459   int from_left, garbage;
00460 
00461   StartAction(ctx, event);
00462 
00463   if (dir == XawsdLeft)
00464     ctx->text.mult++;
00465 
00466   new = SrcScan(ctx->text.source, ctx->text.insertPos,
00467                 XawstEOL, XawsdLeft, 1, FALSE);
00468 
00469   FindDist(ctx->text.sink, new, ctx->text.margin.left, ctx->text.insertPos,
00470            &from_left, &junk, &garbage);
00471 
00472   new = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, dir,
00473                 ctx->text.mult, (dir == XawsdRight));
00474 
00475   next_line = SrcScan(ctx->text.source, new, XawstEOL, XawsdRight, 1, FALSE);
00476 
00477   FindPos(ctx->text.sink, new, ctx->text.margin.left, from_left, FALSE,
00478           &(ctx->text.insertPos), &garbage, &garbage);
00479   
00480   if (ctx->text.insertPos > next_line)
00481     ctx->text.insertPos = next_line;
00482 
00483   EndAction(ctx);
00484 }
00485 
00486 /*ARGSUSED*/
00487 static void 
00488 MoveNextLine(w, event, p, n)
00489 Widget w;
00490 XEvent* event;
00491 String* p;
00492 Cardinal* n;
00493 {
00494   MoveLine( (TextWidget) w, event, XawsdRight);
00495 }
00496 
00497 /*ARGSUSED*/
00498 static void 
00499 MovePreviousLine(w, event, p, n)
00500 Widget w;
00501 XEvent* event;
00502 String* p;
00503 Cardinal* n;
00504 {
00505   MoveLine( (TextWidget) w, event, XawsdLeft);
00506 }
00507 
00508 /*ARGSUSED*/
00509 static void
00510 MoveBeginningOfFile(w, event, p, n)
00511 Widget w;
00512 XEvent* event;
00513 String* p;
00514 Cardinal* n;
00515 {
00516   Move((TextWidget) w, event, XawsdLeft, XawstAll, TRUE);
00517 }
00518 
00519 /*ARGSUSED*/
00520 static void 
00521 MoveEndOfFile(w, event, p, n)
00522 Widget w;
00523 XEvent* event;
00524 String* p;
00525 Cardinal* n;
00526 {
00527   Move((TextWidget) w, event, XawsdRight, XawstAll, TRUE);
00528 }
00529 
00530 static void 
00531 Scroll(ctx, event, dir)
00532 TextWidget ctx;
00533 XEvent* event;
00534 XawTextScanDirection dir;
00535 {
00536   StartAction(ctx, event);
00537 
00538   if (dir == XawsdLeft)
00539     _XawTextVScroll(ctx, ctx->text.mult);
00540   else
00541     _XawTextVScroll(ctx, -ctx->text.mult);
00542 
00543   EndAction(ctx);
00544 }
00545 
00546 /*ARGSUSED*/
00547 static void 
00548 ScrollOneLineUp(w, event, p, n)
00549 Widget w;
00550 XEvent* event;
00551 String* p;
00552 Cardinal* n;
00553 {
00554   Scroll( (TextWidget) w, event, XawsdLeft);
00555 }
00556 
00557 /*ARGSUSED*/
00558 static void 
00559 ScrollOneLineDown(w, event, p, n)
00560 Widget w;
00561 XEvent* event;
00562 String* p;
00563 Cardinal* n;
00564 {
00565   Scroll( (TextWidget) w, event, XawsdRight);
00566 }
00567 
00568 static void 
00569 MovePage(ctx, event, dir)
00570 TextWidget ctx;
00571 XEvent* event;
00572 XawTextScanDirection dir;
00573 {
00574   int scroll_val = Max(1, ctx->text.lt.lines - 2);
00575 
00576   if (dir == XawsdLeft)
00577     scroll_val = -scroll_val;
00578 
00579   StartAction(ctx, event);
00580   _XawTextVScroll(ctx, scroll_val);
00581   ctx->text.insertPos = ctx->text.lt.top;
00582   EndAction(ctx);
00583 }
00584 
00585 /*ARGSUSED*/
00586 static void 
00587 MoveNextPage(w, event, p, n)
00588 Widget w;
00589 XEvent* event;
00590 String* p;
00591 Cardinal* n;
00592 {
00593   MovePage((TextWidget) w, event, XawsdRight);
00594 }
00595 
00596 /*ARGSUSED*/
00597 static void 
00598 MovePreviousPage(w, event, p, n)
00599 Widget w;
00600 XEvent* event;
00601 String* p;
00602 Cardinal* n;
00603 {
00604   MovePage((TextWidget) w, event, XawsdLeft);
00605 }
00606 
00607 /************************************************************
00608  *
00609  * Delete Routines.
00610  *
00611  ************************************************************/
00612 
00613 static Boolean
00614 MatchSelection(selection, s)
00615     Atom selection;
00616     XawTextSelection* s;
00617 {
00618     Atom    *match;
00619     int     count;
00620 
00621     for (count = 0, match = s->selections; count < s->atom_count; match++, count++)
00622         if (*match == selection)
00623             return True;
00624     return False;
00625 }
00626 
00627 #define SrcCvtSel       XawTextSourceConvertSelection
00628 
00629 static Boolean 
00630 ConvertSelection(w, selection, target, type, value, length, format)
00631     Widget w;
00632     Atom *selection, *target, *type;
00633     XtPointer* value;
00634     unsigned long* length;
00635     int* format;
00636 {
00637   Display* d = XtDisplay(w);
00638   TextWidget ctx = (TextWidget)w;
00639   Widget src = ctx->text.source;
00640   XawTextEditType edit_mode;
00641   Arg args[1];
00642   XawTextSelectionSalt  *salt = NULL;
00643   XawTextSelection  *s;
00644 
00645   if (*target == XA_TARGETS(d)) {
00646     Atom* targetP, * std_targets;
00647     unsigned long std_length;
00648 
00649     if ( SrcCvtSel(src, selection, target, type, value, length, format) ) 
00650         return True;
00651 
00652     XmuConvertStandardSelection(w, ctx->text.time, selection, 
00653                                 target, type, (XPointer*)&std_targets,
00654                                 &std_length, format);
00655     
00656     *value = XtMalloc((unsigned) sizeof(Atom)*(std_length + 7));
00657     targetP = *(Atom**)value;
00658 
00659     *length = std_length + 6;
00660     *targetP++ = XA_STRING;
00661     *targetP++ = XA_TEXT(d);
00662     *targetP++ = XA_COMPOUND_TEXT(d);
00663     *targetP++ = XA_LENGTH(d);
00664     *targetP++ = XA_LIST_LENGTH(d);
00665     *targetP++ = XA_CHARACTER_POSITION(d);
00666 
00667     XtSetArg(args[0], XtNeditType,&edit_mode);
00668     XtGetValues(src, args, 1);
00669 
00670     if (edit_mode == XawtextEdit) {
00671       *targetP++ = XA_DELETE(d);
00672       (*length)++;
00673     }
00674     memcpy((char*)targetP, (char*)std_targets, sizeof(Atom)*std_length);
00675     XtFree((char*)std_targets);
00676     *type = XA_ATOM;
00677     *format = 32;
00678     return True;
00679   }
00680   
00681   if ( SrcCvtSel(src, selection, target, type, value, length, format) )
00682     return True;
00683 
00684   for (salt = ctx->text.salt2; salt; salt = salt->next)
00685     if (MatchSelection (*selection, &salt->s))
00686       break;
00687   if (!salt)
00688     return False;
00689   s = &salt->s;
00690   if (*target == XA_STRING ||
00691       *target == XA_TEXT(d) ||
00692       *target == XA_COMPOUND_TEXT(d)) {
00693         if (*target == XA_TEXT(d)) {
00694             if (_XawTextFormat(ctx) == XawFmtWide)
00695                 *type = XA_COMPOUND_TEXT(d);
00696             else
00697                 *type = XA_STRING;
00698         } else {
00699             *type = *target;
00700         }
00701         /* 
00702          * If salt is True, the salt->contents stores CT string, 
00703          * its length is measured in bytes.
00704          * Refer to _XawTextSaltAwaySelection().
00705          *
00706          * by Li Yuhong, Mar. 20, 1991.
00707          */
00708         if (!salt) {
00709             *value = (char *)_XawTextGetSTRING(ctx, s->left, s->right);
00710             if (_XawTextFormat(ctx) == XawFmtWide) {
00711                 XTextProperty textprop;
00712                 if (XwcTextListToTextProperty(d, (wchar_t**)value, 1,
00713                                               XCompoundTextStyle, &textprop)
00714                         < Success) {
00715                     XtFree(*value);
00716                     return False;
00717                 }
00718                 XtFree(*value);
00719                 *value = (XtPointer)textprop.value;
00720                 *length = textprop.nitems;
00721             } else {
00722                 *length = strlen(*value);
00723             }
00724         } else {
00725             *value = XtMalloc((salt->length + 1) * sizeof(unsigned char));
00726             strcpy (*value, salt->contents);
00727             *length = salt->length;
00728         }
00729         if (_XawTextFormat(ctx) == XawFmtWide && *type == XA_STRING) {
00730             XTextProperty textprop;
00731             wchar_t** wlist;
00732             int count;
00733             textprop.encoding = XA_COMPOUND_TEXT(d);
00734             textprop.value = (unsigned char *)*value;
00735             textprop.nitems = strlen(*value);
00736             textprop.format = 8;
00737             if (XwcTextPropertyToTextList(d, &textprop, (wchar_t***)&wlist, &count)
00738                         < Success) {
00739                 XtFree(*value);
00740                 return False;
00741             }
00742             XtFree(*value);
00743             if (XwcTextListToTextProperty(d, (wchar_t**)wlist, 1,
00744                                           XStringStyle, &textprop) < Success) {
00745                 XwcFreeStringList( (wchar_t**) wlist );
00746                 return False;
00747             }
00748             *value = (XtPointer)textprop.value;
00749             *length = textprop.nitems;
00750             XwcFreeStringList( (wchar_t**) wlist );
00751         }
00752         *format = 8;
00753         return True;
00754   }
00755 
00756   if ( (*target == XA_LIST_LENGTH(d)) || (*target == XA_LENGTH(d)) ) {
00757     long * temp;
00758     
00759     temp = (long *) XtMalloc(sizeof(long));
00760     if (*target == XA_LIST_LENGTH(d))
00761       *temp = 1L;
00762     else                        /* *target == XA_LENGTH(d) */
00763       *temp = (long) (s->right - s->left);
00764     
00765     *value = (XPointer) temp;
00766     *type = XA_INTEGER;
00767     *length = 1L;
00768     *format = 32;
00769     return True;
00770   }
00771 
00772   if (*target == XA_CHARACTER_POSITION(d)) {
00773     long * temp;
00774     
00775     temp = (long *) XtMalloc(2 * sizeof(long));
00776     temp[0] = (long) (s->left + 1);
00777     temp[1] = s->right;
00778     *value = (XPointer) temp;
00779     *type = XA_SPAN(d);
00780     *length = 2L;
00781     *format = 32;
00782     return True;
00783   }
00784 
00785   if (*target == XA_DELETE(d)) {
00786     void _XawTextZapSelection(); /* From TextAction.c */
00787     
00788     if (!salt)
00789         _XawTextZapSelection( ctx, (XEvent *) NULL, TRUE);
00790     *value = NULL;
00791     *type = XA_NULL(d);
00792     *length = 0;
00793     *format = 32;
00794     return True;
00795   }
00796 
00797   if (XmuConvertStandardSelection(w, ctx->text.time, selection, target, type,
00798                                   (XPointer *)value, length, format))
00799     return True;
00800   
00801   /* else */
00802   return False;
00803 }
00804 
00805 static void 
00806 LoseSelection(w, selection)
00807     Widget w;
00808     Atom* selection;
00809 {
00810   TextWidget ctx = (TextWidget) w;
00811   Atom* atomP;
00812   int i;
00813   XawTextSelectionSalt  *salt, *prevSalt, *nextSalt;
00814 
00815     prevSalt = 0;
00816     for (salt = ctx->text.salt2; salt; salt = nextSalt)
00817     {
00818         atomP = salt->s.selections;
00819         nextSalt = salt->next;
00820         for (i = 0 ; i < salt->s.atom_count; i++, atomP++)
00821             if (*selection == *atomP)
00822                 *atomP = (Atom)0;
00823         
00824         while (salt->s.atom_count &&
00825                salt->s.selections[salt->s.atom_count-1] == 0)
00826         {
00827             salt->s.atom_count--;
00828         }
00829         
00830         /*
00831          * Must walk the selection list in opposite order from UnsetSelection.
00832          */
00833         
00834         atomP = salt->s.selections;
00835         for (i = 0 ; i < salt->s.atom_count; i++, atomP++)
00836             if (*atomP == (Atom)0)
00837             {
00838               *atomP = salt->s.selections[--salt->s.atom_count];
00839               while (salt->s.atom_count &&
00840                      salt->s.selections[salt->s.atom_count-1] == 0)
00841                 salt->s.atom_count--;
00842             }
00843         if (salt->s.atom_count == 0)
00844         {
00845             XtFree ((char *) salt->s.selections);
00846 
00847             /* WARNING: the next line frees memory not allocated in Xaw. */
00848             /* Could be a serious bug.  Someone look into it. */
00849             XtFree (salt->contents);
00850             if (prevSalt)
00851                 prevSalt->next = nextSalt;
00852             else
00853                 ctx->text.salt2 = nextSalt;
00854             XtFree ((char *) salt);
00855         }
00856         else
00857             prevSalt = salt;
00858     }
00859 }
00860 
00861 static void 
00862 _DeleteOrKill(ctx, from, to, kill)
00863 TextWidget ctx;
00864 XawTextPosition from, to;
00865 Boolean kill;
00866 {
00867   XawTextBlock text;
00868   
00869   if (kill && from < to) {
00870     XawTextSelectionSalt    *salt;
00871     Atom selection = XInternAtom(XtDisplay(ctx), "SECONDARY", False);
00872 
00873     LoseSelection ((Widget) ctx, &selection);
00874     salt = (XawTextSelectionSalt *) XtMalloc (sizeof (XawTextSelectionSalt));
00875     if (!salt)
00876         return;
00877     salt->s.selections = (Atom *) XtMalloc (sizeof (Atom));
00878     if (!salt->s.selections)
00879     {
00880         XtFree ((char *) salt);
00881         return;
00882     }
00883     salt->s.left = from;
00884     salt->s.right = to;
00885     salt->contents = (char *)_XawTextGetSTRING(ctx, from, to);
00886     if (_XawTextFormat(ctx) == XawFmtWide) {
00887         XTextProperty textprop;
00888         if (XwcTextListToTextProperty(XtDisplay((Widget)ctx),
00889                         (wchar_t**)(&(salt->contents)), 1, XCompoundTextStyle,
00890                         &textprop) <  Success) {
00891             XtFree(salt->contents);
00892             salt->length = 0;
00893             return;
00894         }
00895         XtFree(salt->contents);
00896         salt->contents = (char *)textprop.value;
00897         salt->length = textprop.nitems;
00898     } else
00899        salt->length = strlen (salt->contents);
00900     salt->next = ctx->text.salt2;
00901     ctx->text.salt2 = salt;
00902     salt->s.selections[0] = selection;
00903     XtOwnSelection ((Widget) ctx, selection, ctx->text.time,
00904                     ConvertSelection, LoseSelection, NULL);
00905     salt->s.atom_count = 1;
00906 /*
00907     XStoreBuffer(XtDisplay(ctx), ptr, strlen(ptr), 1);
00908     XtFree(ptr);
00909 */
00910   }
00911   text.length = 0;
00912   text.firstPos = 0;
00913 
00914   text.format = _XawTextFormat(ctx);
00915   text.ptr = "";        /* These two lines needed to make legal TextBlock */
00916 
00917   if (_XawTextReplace(ctx, from, to, &text)) {
00918     XBell(XtDisplay(ctx), 50);
00919     return;
00920   }
00921   ctx->text.insertPos = from;
00922   ctx->text.showposition = TRUE; 
00923 }
00924 
00925 static void
00926 DeleteOrKill(ctx, event, dir, type, include, kill)
00927 TextWidget         ctx;
00928 XEvent* event;
00929 XawTextScanDirection dir;
00930 XawTextScanType type;
00931 Boolean    include, kill;
00932 {
00933   XawTextPosition from, to;
00934   
00935   StartAction(ctx, event);
00936   to = SrcScan(ctx->text.source, ctx->text.insertPos,
00937                type, dir, ctx->text.mult, include);
00938 
00939 /*
00940  * If no movement actually happened, then bump the count and try again. 
00941  * This causes the character position at the very beginning and end of 
00942  * a boundary to act correctly. 
00943  */
00944 
00945   if (to == ctx->text.insertPos)
00946       to = SrcScan(ctx->text.source, ctx->text.insertPos,
00947                    type, dir, ctx->text.mult + 1, include);
00948 
00949   if (dir == XawsdLeft) {
00950     from = to;
00951     to = ctx->text.insertPos;
00952   }
00953   else 
00954     from = ctx->text.insertPos;
00955 
00956   _DeleteOrKill(ctx, from, to, kill);
00957   _XawTextSetScrollBars(ctx);
00958   EndAction(ctx);
00959 }
00960 
00961 /*ARGSUSED*/
00962 static void 
00963 DeleteForwardChar(w, event, p, n)
00964 Widget w;
00965 XEvent* event;
00966 String* p;
00967 Cardinal* n;
00968 {
00969   DeleteOrKill((TextWidget) w, event, XawsdRight, XawstPositions, TRUE, FALSE);
00970 }
00971 
00972 /*ARGSUSED*/
00973 static void
00974 DeleteBackwardChar(w, event, p, n)
00975 Widget w;
00976 XEvent* event;
00977 String* p;
00978 Cardinal* n;
00979 {
00980   DeleteOrKill((TextWidget) w, event, XawsdLeft, XawstPositions, TRUE, FALSE);
00981 }
00982 
00983 /*ARGSUSED*/
00984 static void 
00985 DeleteForwardWord(w, event, p, n)
00986 Widget w;
00987 XEvent* event;
00988 String* p;
00989 Cardinal* n;
00990 {
00991   DeleteOrKill((TextWidget) w, event,
00992                XawsdRight, XawstWhiteSpace, FALSE, FALSE);
00993 }
00994 
00995 /*ARGSUSED*/
00996 static void 
00997 DeleteBackwardWord(w, event, p, n)
00998 Widget w;
00999 XEvent* event;
01000 String* p;
01001 Cardinal* n;
01002 {
01003   DeleteOrKill((TextWidget) w, event,
01004                XawsdLeft, XawstWhiteSpace, FALSE, FALSE);
01005 }
01006 
01007 /*ARGSUSED*/
01008 static void 
01009 KillForwardWord(w, event, p, n)
01010 Widget w;
01011 XEvent* event;
01012 String* p;
01013 Cardinal* n;
01014 {
01015   DeleteOrKill((TextWidget) w, event, 
01016                XawsdRight, XawstWhiteSpace, FALSE, TRUE);
01017 }
01018 
01019 /*ARGSUSED*/
01020 static void 
01021 KillBackwardWord(w, event, p, n)
01022 Widget w;
01023 XEvent* event;
01024 String* p;
01025 Cardinal* n;
01026 {
01027   DeleteOrKill((TextWidget) w, event,
01028                XawsdLeft, XawstWhiteSpace, FALSE, TRUE);
01029 }
01030 
01031 /*ARGSUSED*/
01032 static void
01033 KillToEndOfLine(w, event, p, n)
01034 Widget w;
01035 XEvent* event;
01036 String* p;
01037 Cardinal* n;
01038 {
01039   TextWidget ctx = (TextWidget) w;
01040   XawTextPosition end_of_line;
01041 
01042   StartAction(ctx, event);
01043   end_of_line = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, 
01044                         XawsdRight, ctx->text.mult, FALSE);
01045   if (end_of_line == ctx->text.insertPos)
01046     end_of_line = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, 
01047                           XawsdRight, ctx->text.mult, TRUE);
01048 
01049   _DeleteOrKill(ctx, ctx->text.insertPos, end_of_line, TRUE);
01050   _XawTextSetScrollBars(ctx);
01051   EndAction(ctx);
01052 }
01053 
01054 /*ARGSUSED*/
01055 static void 
01056 KillToEndOfParagraph(w, event, p, n)
01057 Widget w;
01058 XEvent* event;
01059 String* p;
01060 Cardinal* n;
01061 {
01062   DeleteOrKill((TextWidget) w, event, XawsdRight, XawstParagraph, FALSE, TRUE);
01063 }
01064 
01065 void 
01066 _XawTextZapSelection(ctx, event, kill)
01067 TextWidget ctx;
01068 XEvent* event;
01069 Boolean kill;
01070 {
01071    StartAction(ctx, event);
01072    _DeleteOrKill(ctx, ctx->text.s.left, ctx->text.s.right, kill);
01073   _XawTextSetScrollBars(ctx);
01074    EndAction(ctx);
01075 }
01076 
01077 /*ARGSUSED*/
01078 static void 
01079 KillCurrentSelection(w, event, p, n)
01080 Widget w;
01081 XEvent* event;
01082 String* p;
01083 Cardinal* n;
01084 {
01085   _XawTextZapSelection( (TextWidget) w, event, TRUE);
01086 }
01087 
01088 /*ARGSUSED*/
01089 static void 
01090 DeleteCurrentSelection(w, event, p, n)
01091 Widget w;
01092 XEvent* event;
01093 String* p;
01094 Cardinal* n;
01095 {
01096   _XawTextZapSelection( (TextWidget) w, event, FALSE);
01097 }
01098 
01099 /************************************************************
01100  *
01101  * Insertion Routines.
01102  *
01103  ************************************************************/
01104 
01105 static int 
01106 InsertNewLineAndBackupInternal(ctx)
01107 TextWidget ctx;
01108 {
01109   int count, error = XawEditDone;
01110   XawTextBlock text;
01111 
01112   text.format = _XawTextFormat(ctx);
01113   text.length = ctx->text.mult;
01114   text.firstPos = 0;
01115 
01116   if ( text.format == XawFmtWide ) {
01117       wchar_t* wptr;
01118       text.ptr =  XtMalloc(sizeof(wchar_t) * ctx->text.mult);
01119       wptr = (wchar_t *)text.ptr;
01120       for (count = 0; count < ctx->text.mult; count++ )
01121           wptr[count] = _Xaw_atowc(XawLF);
01122   }
01123   else {
01124       text.ptr = XtMalloc(sizeof(char) * ctx->text.mult);
01125       for (count = 0; count < ctx->text.mult; count++ )
01126           text.ptr[count] = XawLF;
01127   }
01128 
01129   if (_XawTextReplace(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) {
01130     XBell( XtDisplay(ctx), 50);
01131     error = XawEditError;
01132   }
01133   else 
01134     ctx->text.showposition = TRUE;
01135 
01136   XtFree( text.ptr );
01137   return( error );
01138 }
01139 
01140 /*ARGSUSED*/
01141 static void 
01142 InsertNewLineAndBackup(w, event, p, n)
01143 Widget w;
01144 XEvent* event;
01145 String* p;
01146 Cardinal* n;
01147 {
01148   StartAction( (TextWidget) w, event );
01149   (void) InsertNewLineAndBackupInternal( (TextWidget) w );
01150   _XawTextSetScrollBars( (TextWidget) w);
01151   EndAction( (TextWidget) w );
01152 }
01153 
01154 static int
01155 LocalInsertNewLine(ctx, event)
01156     TextWidget ctx;
01157     XEvent* event;
01158 {
01159   StartAction(ctx, event);
01160   if (InsertNewLineAndBackupInternal(ctx) == XawEditError)
01161     return(XawEditError);
01162   ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos, 
01163                              XawstPositions, XawsdRight, ctx->text.mult, TRUE);
01164   _XawTextSetScrollBars(ctx);
01165   EndAction(ctx);
01166   return(XawEditDone);
01167 }
01168 
01169 /*ARGSUSED*/
01170 static void
01171 InsertNewLine(w, event, p, n)
01172 Widget w;
01173 XEvent* event;
01174 String* p;
01175 Cardinal* n;
01176 {
01177   (void) LocalInsertNewLine( (TextWidget) w, event);
01178 }
01179 
01180 /*ARGSUSED*/
01181 static void 
01182 InsertNewLineAndIndent(w, event, p, n)
01183 Widget w;
01184 XEvent *event;
01185 String *p;
01186 Cardinal *n;
01187 {
01188   XawTextBlock text;
01189   XawTextPosition pos1;
01190   int length;
01191   TextWidget ctx = (TextWidget) w;
01192   String line_to_ip;
01193 
01194   StartAction(ctx, event);
01195   pos1 = SrcScan(ctx->text.source, ctx->text.insertPos, 
01196                  XawstEOL, XawsdLeft, 1, FALSE);
01197 
01198   line_to_ip = _XawTextGetText(ctx, pos1, ctx->text.insertPos);
01199 
01200   text.format = _XawTextFormat(ctx);
01201   text.firstPos = 0;
01202 
01203   if ( text.format == XawFmtWide ) {
01204      wchar_t* ptr;
01205      text.ptr = XtMalloc( ( 2 + wcslen((wchar_t*)line_to_ip) ) * sizeof(wchar_t) );
01206 
01207      ptr = (wchar_t*)text.ptr;
01208      ptr[0] = _Xaw_atowc( XawLF );
01209      wcscpy( (wchar_t*) ++ptr, (wchar_t*) line_to_ip );
01210 
01211      length = wcslen((wchar_t*)text.ptr);
01212      while ( length && ( iswspace(*ptr) || ( *ptr == _Xaw_atowc(XawTAB) ) ) )
01213          ptr++, length--;
01214      *ptr = (wchar_t)0;
01215      text.length = wcslen((wchar_t*)text.ptr);
01216 
01217   } else {
01218      char *ptr;
01219      length = strlen(line_to_ip);
01220      /* The current line + \0 and LF will be copied to this 
01221         buffer. Before my fix, only length + 1 bytes were
01222         allocated, causing on machine with non-wasteful 
01223         malloc implementation segmentation violations by
01224         overwriting the bypte after the allocated area
01225 
01226         -gustaf neumann
01227       */
01228      text.ptr = XtMalloc( ( 2 + length ) * sizeof( char ) );
01229 
01230      ptr = text.ptr;
01231      ptr[0] = XawLF;
01232      strcpy( ++ptr, line_to_ip );
01233 
01234      length++;
01235      while ( length && ( isspace(*ptr) || ( *ptr == XawTAB ) ) )
01236          ptr++, length--;
01237      *ptr = '\0';
01238      text.length = strlen(text.ptr);
01239   }
01240   XtFree( line_to_ip );
01241 
01242   if (_XawTextReplace(ctx,ctx->text.insertPos, ctx->text.insertPos, &text)) {
01243     XBell(XtDisplay(ctx), 50);
01244     XtFree(text.ptr);
01245     EndAction(ctx);
01246     return;
01247   }
01248   XtFree(text.ptr);
01249   ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos,
01250                                 XawstPositions, XawsdRight, text.length, TRUE);
01251   _XawTextSetScrollBars(ctx);
01252   EndAction(ctx);
01253 }
01254 
01255 /************************************************************
01256  *
01257  * Selection Routines.
01258  *
01259  *************************************************************/
01260 
01261 static void 
01262 SelectWord(w, event, params, num_params)
01263 Widget w;
01264 XEvent* event;
01265 String* params;
01266 Cardinal* num_params;
01267 {
01268   TextWidget ctx = (TextWidget) w;
01269   XawTextPosition l, r;
01270 
01271   StartAction(ctx, event);
01272   l = SrcScan(ctx->text.source, ctx->text.insertPos, 
01273               XawstWhiteSpace, XawsdLeft, 1, FALSE);
01274   r = SrcScan(ctx->text.source, l, XawstWhiteSpace, XawsdRight, 1, FALSE);
01275   _XawTextSetSelection(ctx, l, r, params, *num_params);
01276   EndAction(ctx);
01277 }
01278 
01279 static void 
01280 SelectAll(w, event, params, num_params)
01281 Widget w;
01282 XEvent* event;
01283 String* params;
01284 Cardinal* num_params;
01285 {
01286   TextWidget ctx = (TextWidget) w;
01287 
01288   StartAction(ctx, event);
01289   _XawTextSetSelection(ctx,zeroPosition,ctx->text.lastPos,params,*num_params);
01290   EndAction(ctx);
01291 }
01292 
01293 static void
01294 ModifySelection(ctx, event, mode, action, params, num_params)
01295 TextWidget ctx;
01296 XEvent* event;
01297 XawTextSelectionMode mode;
01298 XawTextSelectionAction action;
01299 String* params;         /* unused */
01300 Cardinal* num_params;   /* unused */
01301 {
01302   StartAction(ctx, event);
01303   NotePosition(ctx, event);
01304   _XawTextAlterSelection(ctx, mode, action, params, num_params);
01305   EndAction(ctx);
01306 }
01307                 
01308 /* ARGSUSED */
01309 static void 
01310 SelectStart(w, event, params, num_params)
01311 Widget w;
01312 XEvent* event;
01313 String* params;         /* unused */
01314 Cardinal* num_params;   /* unused */
01315 {
01316   ModifySelection((TextWidget) w, event, 
01317                   XawsmTextSelect, XawactionStart, params, num_params);
01318 }
01319 
01320 /* ARGSUSED */
01321 static void 
01322 SelectAdjust(w, event, params, num_params)
01323 Widget w;
01324 XEvent* event;
01325 String* params;         /* unused */
01326 Cardinal* num_params;   /* unused */
01327 {
01328   ModifySelection((TextWidget) w, event, 
01329                   XawsmTextSelect, XawactionAdjust, params, num_params);
01330 }
01331 
01332 static void 
01333 SelectEnd(w, event, params, num_params)
01334 Widget w;
01335 XEvent* event;
01336 String* params;
01337 Cardinal* num_params;
01338 {
01339   ModifySelection((TextWidget) w, event, 
01340                   XawsmTextSelect, XawactionEnd, params, num_params);
01341 }
01342 
01343 /* ARGSUSED */
01344 static void 
01345 ExtendStart(w, event, params, num_params)
01346 Widget w;
01347 XEvent* event;
01348 String* params;         /* unused */
01349 Cardinal* num_params;   /* unused */
01350 {
01351   ModifySelection((TextWidget) w, event, 
01352                   XawsmTextExtend, XawactionStart, params, num_params);
01353 }
01354 
01355 /* ARGSUSED */
01356 static void 
01357 ExtendAdjust(w, event, params, num_params)
01358 Widget w;
01359 XEvent* event;
01360 String* params;         /* unused */
01361 Cardinal* num_params;   /* unused */
01362 {
01363   ModifySelection((TextWidget) w, event, 
01364                   XawsmTextExtend, XawactionAdjust, params, num_params);
01365 }
01366 
01367 static void 
01368 ExtendEnd(w, event, params, num_params)
01369 Widget w;
01370 XEvent* event;
01371 String* params;
01372 Cardinal* num_params;
01373 {
01374   ModifySelection((TextWidget) w, event, 
01375                   XawsmTextExtend, XawactionEnd, params, num_params);
01376 }
01377 
01378 static void
01379 SelectSave(w, event, params, num_params)
01380 Widget  w;
01381 XEvent* event;
01382 String* params;
01383 Cardinal* num_params;
01384 {
01385     int     num_atoms;
01386     Atom*   sel;
01387     Display* dpy = XtDisplay(w);
01388     Atom    selections[256];
01389 
01390     StartAction(  (TextWidget) w, event );
01391     num_atoms = *num_params;
01392     if (num_atoms > 256)
01393         num_atoms = 256;
01394     for (sel=selections; --num_atoms >= 0; sel++, params++)
01395         *sel = XInternAtom(dpy, *params, False);
01396     num_atoms = *num_params;
01397     _XawTextSaltAwaySelection( (TextWidget) w, selections, num_atoms );
01398     EndAction(  (TextWidget) w );
01399 }
01400 
01401 /************************************************************
01402  *
01403  * Misc. Routines.
01404  *
01405  ************************************************************/
01406 
01407 /* ARGSUSED */
01408 static void 
01409 RedrawDisplay(w, event, p, n)
01410 Widget w;
01411 XEvent* event;
01412 String* p;
01413 Cardinal* n;
01414 {
01415   StartAction( (TextWidget) w, event);
01416   _XawTextClearAndCenterDisplay((TextWidget) w);
01417   EndAction( (TextWidget) w);
01418 }
01419 
01420 /*ARGSUSED*/
01421 static void
01422 TextFocusIn (w, event, p, n)
01423 Widget w;
01424 XEvent* event;
01425 String* p;
01426 Cardinal* n;
01427 {
01428   TextWidget ctx = (TextWidget) w;
01429 
01430   /* Let the input method know focus has arrived. */
01431   _XawImSetFocusValues (w, NULL, 0);
01432   if ( event->xfocus.detail == NotifyPointer ) return;
01433 
01434   ctx->text.hasfocus = TRUE; 
01435 }
01436 
01437 /*ARGSUSED*/
01438 static void
01439 TextFocusOut(w, event, p, n)
01440 Widget w;
01441 XEvent* event;
01442 String* p;
01443 Cardinal* n;
01444 {
01445   TextWidget ctx = (TextWidget) w;
01446 
01447   /* Let the input method know focus has left.*/
01448   _XawImUnsetFocus(w);
01449   if ( event->xfocus.detail == NotifyPointer ) return;
01450   ctx->text.hasfocus = FALSE;
01451 }
01452 
01453 /*ARGSUSED*/
01454 static void
01455 TextEnterWindow( w, event, params, num_params )
01456     Widget w;
01457     XEvent* event;
01458     String* params;
01459     Cardinal* num_params;
01460 {
01461   TextWidget ctx = (TextWidget) w;
01462 
01463   if ((event->xcrossing.detail != NotifyInferior) && event->xcrossing.focus &&
01464       !ctx->text.hasfocus) {
01465         _XawImSetFocusValues(w, NULL, 0);
01466   }
01467 }
01468 
01469 /*ARGSUSED*/
01470 static void
01471 TextLeaveWindow( w, event, params, num_params )
01472     Widget w;
01473     XEvent* event;
01474     String* params;
01475     Cardinal* num_params;
01476 {
01477   TextWidget ctx = (TextWidget) w;
01478 
01479   if ((event->xcrossing.detail != NotifyInferior) && event->xcrossing.focus &&
01480       !ctx->text.hasfocus) {
01481         _XawImUnsetFocus(w);
01482   }
01483 }
01484 
01485 static XComposeStatus compose_status = {NULL, 0};
01486 
01487 /*      Function Name: AutoFill
01488  *      Description: Breaks the line at the previous word boundry when
01489  *                   called inside InsertChar.
01490  *      Arguments: ctx - The text widget.
01491  *      Returns: none
01492  */
01493 
01494 static void
01495 AutoFill(ctx)
01496 TextWidget ctx;
01497 {
01498   int width, height, x, line_num, max_width;
01499   XawTextPosition ret_pos;
01500   XawTextBlock text;
01501 
01502   if ( !((ctx->text.auto_fill) && (ctx->text.mult == 1)) )
01503     return;
01504 
01505   for ( line_num = 0; line_num < ctx->text.lt.lines ; line_num++)
01506     if ( ctx->text.lt.info[line_num].position >= ctx->text.insertPos )
01507       break;
01508   line_num--;                   /* backup a line. */
01509 
01510   max_width = Max(0, (int)(ctx->core.width - HMargins(ctx)));
01511 
01512   x = ctx->text.margin.left;
01513   XawTextSinkFindPosition( ctx->text.sink,ctx->text.lt.info[line_num].position,
01514                           x, max_width, TRUE, &ret_pos, &width, &height);
01515   
01516   if ( ret_pos >= ctx->text.insertPos )
01517     return;
01518   
01519   text.format = XawFmt8Bit;
01520   if (_XawTextFormat(ctx) == XawFmtWide) {
01521     text.format = XawFmtWide;
01522     text.ptr =  (char *)XtMalloc(sizeof(wchar_t) * 2);
01523     ((wchar_t*)text.ptr)[0] = _Xaw_atowc(XawLF);
01524     ((wchar_t*)text.ptr)[1] = 0;
01525   } else
01526     text.ptr = "\n";
01527   text.length = 1;
01528   text.firstPos = 0;
01529 
01530   if (_XawTextReplace(ctx, ret_pos - 1, ret_pos, &text))
01531     XBell(XtDisplay((Widget) ctx), 0);  /* Unable to edit, complain. */
01532 }
01533 
01534 /*ARGSUSED*/
01535 static void
01536 InsertChar(w, event, p, n)
01537 Widget w;
01538 XEvent* event;
01539 String* p;
01540 Cardinal* n;
01541 {
01542   TextWidget ctx = (TextWidget) w;
01543   char *ptr, strbuf[BUFSIZ];
01544   int count, error;
01545   KeySym keysym;
01546   XawTextBlock text;
01547 
01548   if (XtIsSubclass (ctx->text.source, (WidgetClass) multiSrcObjectClass))
01549     text.length = _XawImWcLookupString (w, &event->xkey,
01550                 (wchar_t*) strbuf, BUFSIZ, &keysym, (Status*) &compose_status);
01551   else
01552     text.length = XLookupString ((XKeyEvent*)event, strbuf, BUFSIZ, &keysym, &compose_status);
01553 
01554   if (text.length == 0)
01555       return;
01556 
01557   text.format = _XawTextFormat( ctx );
01558   if ( text.format == XawFmtWide ) {
01559       text.ptr = ptr = XtMalloc(sizeof(wchar_t) * text.length * ctx->text.mult );
01560       for (count = 0; count < ctx->text.mult; count++ ) {
01561           memcpy((char*) ptr, (char *)strbuf, sizeof(wchar_t) * text.length );
01562           ptr += sizeof(wchar_t) * text.length;
01563       }
01564 
01565   } else { /* == XawFmt8Bit */
01566       text.ptr = ptr = XtMalloc( sizeof(char) * text.length * ctx->text.mult );
01567       for ( count = 0; count < ctx->text.mult; count++ ) {
01568           strncpy( ptr, strbuf, text.length );
01569           ptr += text.length;
01570       }
01571   }
01572 
01573   text.length = text.length * ctx->text.mult;
01574   text.firstPos = 0;
01575 
01576   StartAction(ctx, event);
01577   
01578   error = _XawTextReplace(ctx, ctx->text.insertPos,ctx->text.insertPos, &text);
01579 
01580   if (error == XawEditDone) {
01581       ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos,
01582               XawstPositions, XawsdRight, text.length, TRUE);
01583       AutoFill(ctx);
01584   }
01585   else 
01586       XBell(XtDisplay(ctx), 50);
01587 
01588   XtFree(text.ptr);
01589   _XawTextSetScrollBars(ctx);
01590   EndAction(ctx);
01591 }
01592 
01593 
01594 /* IfHexConvertHexElseReturnParam() - called by InsertString
01595  *
01596  * i18n requires the ability to specify multiple characters in a hexa-
01597  * decimal string at once.  Since Insert was already too long, I made
01598  * this a seperate routine.
01599  *
01600  * A legal hex string in MBNF: '0' 'x' ( HEX-DIGIT HEX-DIGIT )+ '\0'
01601  *
01602  * WHEN:    the passed param is a legal hex string
01603  * RETURNS: a pointer to that converted, null terminated hex string;
01604  *          len_return holds the character count of conversion result
01605  *
01606  * WHEN:    the passed param is not a legal hex string:
01607  * RETURNS: the parameter passed;
01608  *          len_return holds the char count of param.
01609  *
01610  * NOTE:    In neither case will there be strings to free. */
01611 
01612 static char* 
01613 IfHexConvertHexElseReturnParam(param, len_return)
01614     char* param;
01615     int* len_return;
01616 {
01617   char *p;                     /* steps through param char by char */
01618   char c;                      /* holds the character pointed to by p */
01619 
01620   int ind;                     /* steps through hexval buffer char by char */
01621   static char hexval[ XawTextActionMaxHexChars ];
01622   Boolean first_digit;
01623 
01624   /* reject if it doesn't begin with 0x and at least one more character. */
01625 
01626   if ( ( param[0] != '0' ) || ( param[1] != 'x' ) || ( param[2] == '\0' ) ) {
01627       *len_return = strlen( param );
01628       return( param );
01629   }
01630 
01631   /* Skip the 0x; go character by character shifting and adding. */
01632 
01633   first_digit = True;
01634   ind = 0;
01635   hexval[ ind ] = '\0';
01636 
01637   for ( p = param+2; ( c = *p ); p++ ) {
01638       hexval[ ind ] *= 16;
01639       if (c >= '0' && c <= '9')
01640           hexval[ ind ] += c - '0';
01641       else if (c >= 'a' && c <= 'f')
01642           hexval[ ind ] += c - 'a' + 10;
01643       else if (c >= 'A' && c <= 'F')
01644           hexval[ ind ] += c - 'A' + 10;
01645       else break;
01646 
01647       /* If we didn't break in preceding line, it was a good hex char. */
01648 
01649       if ( first_digit )
01650           first_digit = False;
01651       else {
01652           first_digit = True;
01653           if ( ++ind < XawTextActionMaxHexChars )
01654               hexval[ ind ] = '\0';
01655           else {
01656               *len_return = strlen( param );
01657               return( param );
01658           }
01659       }
01660   }
01661 
01662   /* We quit the above loop becasue we hit a non hex.  If that char is \0... */
01663 
01664   if ( ( c == '\0' ) && first_digit ) {
01665       *len_return = strlen( hexval );
01666       return( hexval );       /* ...it was a legal hex string, so return it.*/
01667   }
01668 
01669   /* Else, there were non-hex chars or odd digit count, so... */
01670 
01671   *len_return = strlen( param );
01672   return( param );                         /* ...return the verbatim string. */
01673 }
01674 
01675 
01676 /* InsertString() - action
01677  *
01678  * Mostly rewritten for R6 i18n.
01679  *
01680  * Each parameter, in turn, will be insert at the inputPos
01681  * and the inputPos advances to the insertion's end.
01682  *
01683  * The exception is that parameters composed of the two
01684  * characters 0x, followed only by an even number of
01685  * hexadecimal digits will be converted to characters. */
01686 
01687 /*ARGSUSED*/
01688 static void 
01689 InsertString(w, event, params, num_params)
01690 Widget w;
01691 XEvent* event;
01692 String* params;
01693 Cardinal* num_params;
01694 {
01695   TextWidget ctx = (TextWidget) w;
01696   XtAppContext app_con = XtWidgetToApplicationContext(w);
01697   XawTextBlock text;
01698   int      i;
01699 
01700   text.firstPos = 0;
01701   text.format = _XawTextFormat( ctx );
01702 
01703   StartAction(ctx, event);
01704   for ( i = *num_params; i; i--, params++ ) { /* DO FOR EACH PARAMETER */
01705 
01706       text.ptr = IfHexConvertHexElseReturnParam( *params, &text.length );
01707 
01708       if ( text.length == 0 ) continue;
01709 
01710       if ( _XawTextFormat( ctx ) == XawFmtWide ) { /* convert to WC */
01711 
01712           int temp_len;
01713           text.ptr = (char*) _XawTextMBToWC( XtDisplay(w), text.ptr,
01714                                               &text.length );
01715 
01716           if ( text.ptr == NULL ) { /* conversion error */
01717               XtAppWarningMsg( app_con,
01718                 "insertString", "textAction", "XawError",
01719                 "insert-string()'s parameter contents not legal in this locale.",
01720                 NULL, NULL );
01721               ParameterError( w, *params );
01722               continue;
01723           }
01724 
01725           /* Double check that the new input is legal: try to convert to MB. */
01726 
01727           temp_len = text.length;      /* _XawTextWCToMB's 3rd arg is in_out */ 
01728           if ( _XawTextWCToMB( XtDisplay(w), (wchar_t*)text.ptr, &temp_len ) == NULL ) {
01729               XtAppWarningMsg( app_con,
01730                 "insertString", "textAction", "XawError",
01731                 "insert-string()'s parameter contents not legal in this locale.",
01732                                 NULL, NULL );
01733               ParameterError( w, *params );
01734               continue;
01735           }
01736       } /* convert to WC */
01737 
01738       if ( _XawTextReplace( ctx, ctx->text.insertPos, 
01739                             ctx->text.insertPos, &text ) ) {
01740           XBell( XtDisplay( ctx ), 50 );
01741           EndAction( ctx );
01742           return;
01743       }
01744 
01745       /* Advance insertPos to the end of the string we just inserted. */
01746       ctx->text.insertPos = SrcScan( ctx->text.source, ctx->text.insertPos,
01747                             XawstPositions, XawsdRight, text.length, TRUE );
01748 
01749   } /* DO FOR EACH PARAMETER */
01750 
01751   EndAction( ctx );
01752 }
01753 
01754 
01755 /* DisplayCaret() - action
01756  *  
01757  * The parameter list should contain one boolean value.  If the
01758  * argument is true, the cursor will be displayed.  If false, not.
01759  *
01760  * The exception is that EnterNotify and LeaveNotify events may
01761  * have a second argument, "always".  If they do not, the cursor
01762  * is only affected if the focus member of the event is true.   */
01763 
01764 static void 
01765 DisplayCaret(w, event, params, num_params)
01766 Widget w;
01767 XEvent* event;          /* CrossingNotify special-cased */
01768 String* params;         /* Off, False, No, On, True, Yes, etc. */
01769 Cardinal* num_params;   /* 0, 1 or 2 */
01770 {
01771   TextWidget ctx = (TextWidget)w;
01772   Boolean display_caret = True;
01773 
01774   if  ( ( event->type == EnterNotify || event->type == LeaveNotify ) &&
01775         ( ( *num_params >= 2 ) && ( strcmp( params[1], "always" ) == 0 ) ) &&
01776         ( !event->xcrossing.focus ) )
01777       return;
01778 
01779   if (*num_params > 0) {        /* default arg is "True" */
01780       XrmValue from, to;
01781       from.size = strlen(from.addr = params[0]);
01782       XtConvert( w, XtRString, &from, XtRBoolean, &to );
01783 
01784       if ( to.addr != NULL )
01785           display_caret = *(Boolean*)to.addr;
01786       if ( ctx->text.display_caret == display_caret )
01787           return;
01788   }
01789   StartAction(ctx, event);
01790   ctx->text.display_caret = display_caret;
01791   EndAction(ctx);
01792 }
01793 
01794 
01795 /* Multiply() - action
01796  *  
01797  * The parameter list may contain either a number or the string 'Reset'.
01798  * 
01799  * A number will multiply the current multiplication factor by that number.
01800  * Many of the text widget actions will will perform n actions, where n is
01801  * the multiplication factor.
01802  *
01803  * The string reset will reset the mutiplication factor to 1. */
01804 
01805 /* ARGSUSED */
01806 static void 
01807 Multiply(w, event, params, num_params)
01808 Widget w;
01809 XEvent* event;
01810 String* params;
01811 Cardinal* num_params;
01812 {
01813   TextWidget ctx = (TextWidget) w;
01814   int mult;
01815 
01816   if (*num_params != 1) {
01817       XtAppError( XtWidgetToApplicationContext( w ), 
01818                "Xaw Text Widget: multiply() takes exactly one argument.");
01819       XBell( XtDisplay( w ), 0 );
01820       return;
01821   }
01822 
01823   if ( ( params[0][0] == 'r' ) || ( params[0][0] == 'R' ) ) {
01824       XBell( XtDisplay( w ), 0 );
01825       ctx->text.mult = 1;
01826       return;
01827   }
01828 
01829   if ( ( mult = atoi( params[0] ) ) == 0 ) {
01830       char buf[ BUFSIZ ];
01831       sprintf(buf, "%s %s", "Xaw Text Widget: multiply() argument",
01832             "must be a number greater than zero, or 'Reset'." );
01833       XtAppError( XtWidgetToApplicationContext( w ), buf );
01834       XBell( XtDisplay( w ), 50 );
01835       return;
01836   }
01837 
01838   ctx->text.mult *= mult;
01839 }
01840 
01841 
01842 /* StripOutOldCRs() - called from FormRegion
01843  *
01844  * removes CRs in widget ctx, from from to to.
01845  *
01846  * RETURNS: the new ending location (we may add some characters),
01847  * or XawReplaceError if the widget can't be written to. */
01848 
01849 static XawTextPosition
01850 StripOutOldCRs(ctx, from, to)
01851 TextWidget ctx;
01852 XawTextPosition from, to;
01853 {
01854   XawTextPosition startPos, endPos, eop_begin, eop_end, temp;
01855   Widget src = ctx->text.source;
01856   XawTextBlock text;
01857   char *buf;
01858   static wchar_t wc_two_spaces[ 3 ];
01859 
01860   /* Initialize our TextBlock with two spaces. */
01861 
01862   text.firstPos = 0;
01863   text.format = _XawTextFormat(ctx);
01864   if ( text.format == XawFmt8Bit )
01865       text.ptr= "  ";
01866   else {
01867       wc_two_spaces[0] = _Xaw_atowc(XawSP);
01868       wc_two_spaces[1] = _Xaw_atowc(XawSP);
01869       wc_two_spaces[2] = 0;
01870       text.ptr = (char*) wc_two_spaces;
01871   }
01872    
01873   /* Strip out CR's. */
01874 
01875   eop_begin = eop_end = startPos = endPos = from;
01876   /* CONSTCOND */
01877   while (TRUE) {
01878       endPos=SrcScan(src, startPos, XawstEOL, XawsdRight, 1, FALSE);
01879 
01880       temp = SrcScan(src, endPos, XawstWhiteSpace, XawsdLeft, 1, FALSE);
01881       temp = SrcScan(src, temp,   XawstWhiteSpace, XawsdRight,1, FALSE);
01882 
01883       if (temp > startPos)
01884           endPos = temp;
01885 
01886       if (endPos >= to)
01887           break;
01888 
01889       if (endPos >= eop_begin) {
01890           startPos = eop_end;
01891           eop_begin=SrcScan(src, startPos, XawstParagraph, XawsdRight, 1,FALSE);
01892           eop_end = SrcScan(src, startPos, XawstParagraph, XawsdRight, 1, TRUE);
01893       }
01894     else {
01895       XawTextPosition periodPos, next_word;
01896       int i, len;
01897 
01898       periodPos= SrcScan(src, endPos, XawstPositions, XawsdLeft, 1, TRUE);
01899       next_word = SrcScan(src, endPos, XawstWhiteSpace, XawsdRight, 1, FALSE);
01900 
01901       len = next_word - periodPos;
01902 
01903       text.length = 1;
01904       buf = _XawTextGetText(ctx, periodPos, next_word);
01905       if (text.format == XawFmtWide) {
01906         if ( (periodPos < endPos) && (((wchar_t*)buf)[0] == _Xaw_atowc('.')))
01907           text.length++;
01908       } else
01909         if ( (periodPos < endPos) && (buf[0] == '.') )
01910           text.length++;        /* Put in two spaces. */
01911 
01912       /*
01913        * Remove all extra spaces. 
01914        */
01915 
01916       for (i = 1 ; i < len; i++) 
01917         if (text.format ==  XawFmtWide) {
01918           if ( !iswspace(((wchar_t*)buf)[i]) || ((periodPos + i) >= to) ) {
01919              break;
01920           }
01921         } else
01922           if ( !isspace(buf[i]) || ((periodPos + i) >= to) ) {
01923               break;
01924           }
01925       
01926       XtFree(buf);
01927 
01928       to -= (i - text.length - 1);
01929       startPos = SrcScan(src, periodPos, XawstPositions, XawsdRight, i, TRUE);
01930       if (_XawTextReplace(ctx, endPos, startPos, &text) != XawEditDone)
01931           return XawReplaceError;
01932       startPos -= i - text.length;
01933     }
01934   }
01935   return(to);
01936 }
01937 
01938 
01939 /* InsertNewCRs() - called from FormRegion
01940  *
01941  * inserts new CRs for FormRegion, thus for FormParagraph action */
01942 
01943 static void
01944 InsertNewCRs(ctx, from, to)
01945 TextWidget ctx;
01946 XawTextPosition from, to;
01947 {
01948   XawTextPosition startPos, endPos, space, eol;
01949   XawTextBlock text;
01950   int i, width, height, len;
01951   char * buf;
01952   static wchar_t wide_CR[ 2 ];
01953 
01954   text.firstPos = 0;
01955   text.length = 1;
01956   text.format = _XawTextFormat( ctx );
01957 
01958   if ( text.format == XawFmt8Bit )
01959       text.ptr = "\n";
01960   else {
01961       wide_CR[0] = _Xaw_atowc(XawLF);
01962       wide_CR[1] = 0;
01963       text.ptr = (char*) wide_CR;
01964   }
01965 
01966   startPos = from;
01967   /* CONSTCOND */
01968   while (TRUE) {
01969       XawTextSinkFindPosition( ctx->text.sink, startPos, 
01970                             (int) ctx->text.margin.left,
01971                             (int) (ctx->core.width - HMargins(ctx)), 
01972                             TRUE, &eol, &width, &height);
01973       if (eol >= to)
01974           break;
01975 
01976       eol  = SrcScan(ctx->text.source, eol, XawstPositions, XawsdLeft, 1, TRUE);
01977       space= SrcScan(ctx->text.source, eol, XawstWhiteSpace,XawsdRight,1, TRUE);
01978     
01979       startPos = endPos = eol;
01980       if (eol == space) 
01981           return;
01982 
01983       len = (int) (space - eol);
01984       buf = _XawTextGetText(ctx, eol, space);
01985       for ( i = 0 ; i < len ; i++)
01986       if (text.format == XawFmtWide) {
01987           if (!iswspace(((wchar_t*)buf)[i]))
01988               break;
01989       } else
01990           if (!isspace(buf[i]))
01991               break;
01992 
01993       to -= (i - 1);
01994       endPos = SrcScan(ctx->text.source, endPos,
01995                      XawstPositions, XawsdRight, i, TRUE);
01996       XtFree(buf);
01997     
01998       if (_XawTextReplace(ctx, startPos, endPos, &text))
01999           return;
02000 
02001       startPos = SrcScan(ctx->text.source, startPos,
02002                        XawstPositions, XawsdRight, 1, TRUE);
02003   }
02004 }  
02005 
02006 
02007 /* FormRegion() - called by FormParagraph
02008  * 
02009  * oversees the work of paragraph-forming a region
02010  *
02011  * RETURNS: XawEditDone if successful, or XawReplaceError. */
02012 
02013 static int
02014 FormRegion(ctx, from, to)
02015 TextWidget ctx;
02016 XawTextPosition from, to;
02017 {
02018   if ( from >= to ) return XawEditDone;
02019 
02020   if ( ( to = StripOutOldCRs( ctx, from, to ) ) == XawReplaceError )
02021       return XawReplaceError;
02022 
02023   /* insure that the insertion point is within legal bounds */
02024   if ( ctx->text.insertPos > SrcScan( ctx->text.source, 0,
02025                                        XawstAll, XawsdRight, 1, TRUE ) )
02026       ctx->text.insertPos = to;
02027 
02028   InsertNewCRs(ctx, from, to);
02029   _XawTextBuildLineTable(ctx, ctx->text.lt.top, TRUE);
02030   return XawEditDone;
02031 }
02032 
02033 
02034 /* FormParagraph() - action
02035  *
02036  * removes and reinserts CRs to maximize line length without clipping */
02037 
02038 /* ARGSUSED */
02039 static void 
02040 FormParagraph(w, event, params, num_params)
02041 Widget w;
02042 XEvent* event;
02043 String* params;
02044 Cardinal* num_params;
02045 {
02046   TextWidget ctx = (TextWidget) w;
02047   XawTextPosition from, to;
02048 
02049   StartAction(ctx, event);
02050 
02051   from =  SrcScan( ctx->text.source, ctx->text.insertPos,
02052                   XawstParagraph, XawsdLeft, 1, FALSE );
02053   to  =  SrcScan( ctx->text.source, from,
02054                  XawstParagraph, XawsdRight, 1, FALSE );
02055 
02056   if ( FormRegion( ctx, from, to ) == XawReplaceError )
02057       XBell( XtDisplay( w ), 0 );
02058   _XawTextSetScrollBars( ctx );
02059   EndAction( ctx );
02060 }
02061 
02062 
02063 /* TransposeCharacters() - action
02064  *
02065  * Swaps the character to the left of the mark
02066  * with the character to the right of the mark. */
02067              
02068 /* ARGSUSED */
02069 static void 
02070 TransposeCharacters(w, event, params, num_params)
02071 Widget w;
02072 XEvent* event;
02073 String* params;
02074 Cardinal* num_params;
02075 {
02076   TextWidget ctx = (TextWidget) w;
02077   XawTextPosition start, end;
02078   XawTextBlock text;
02079   char* buf;
02080   int i;
02081 
02082   StartAction(ctx, event);
02083 
02084   /* Get bounds. */
02085 
02086   start = SrcScan( ctx->text.source, ctx->text.insertPos, XawstPositions, 
02087                   XawsdLeft, 1, TRUE );
02088   end = SrcScan( ctx->text.source, ctx->text.insertPos, XawstPositions, 
02089                 XawsdRight, ctx->text.mult, TRUE );
02090 
02091   /* Make sure we aren't at the very beginning or end of the buffer. */
02092 
02093   if ( ( start == ctx->text.insertPos ) || ( end == ctx->text.insertPos ) ) {
02094       XBell( XtDisplay( w ), 0 );       /* complain. */
02095       EndAction( ctx );
02096       return;
02097   }
02098 
02099   ctx->text.insertPos = end;
02100 
02101   text.firstPos = 0;
02102   text.format = _XawTextFormat(ctx);
02103 
02104   /* Retrieve text and swap the characters. */
02105     
02106   if ( text.format == XawFmtWide) {
02107       wchar_t wc;
02108       wchar_t* wbuf;
02109 
02110       wbuf = (wchar_t*) _XawTextGetText(ctx, start, end);
02111       text.length = wcslen( wbuf );
02112       wc = wbuf[ 0 ];
02113       for ( i = 1; i < text.length; i++ )
02114           wbuf[ i-1 ] = wbuf[ i ];
02115       wbuf[ i-1 ] = wc;
02116       buf = (char*) wbuf; /* so that it gets assigned and freed */
02117 
02118   } else { /* thus text.format == XawFmt8Bit */
02119       char c;
02120       buf = _XawTextGetText( ctx, start, end );
02121       text.length = strlen( buf );
02122       c = buf[ 0 ];
02123       for ( i = 1; i < text.length; i++ )
02124           buf[ i-1 ] = buf[ i ];
02125       buf[ i-1 ] = c;
02126   }
02127 
02128   text.ptr = buf;
02129 
02130   /* Store new text in source. */
02131     
02132   if (_XawTextReplace (ctx, start, end, &text)) /* Unable to edit, complain. */
02133       XBell(XtDisplay(w), 0);
02134   XtFree((char *) buf);
02135   EndAction(ctx);
02136 }
02137 
02138 
02139 /* NoOp() - action
02140  * This action performs no action, and allows the user or
02141  * application programmer to unbind a translation.
02142  *
02143  * Note: If the parameter list contains the string "RingBell" then
02144  *       this action will ring the bell.
02145  */
02146 
02147 /*ARGSUSED*/
02148 static void
02149 NoOp(w, event, params, num_params)
02150 Widget w;
02151 XEvent* event;
02152 String* params;
02153 Cardinal* num_params;
02154 {
02155     if (*num_params != 1)
02156         return;
02157 
02158     switch(params[0][0]) {
02159     case 'R':
02160     case 'r':
02161         XBell(XtDisplay(w), 0);
02162     default:                    /* Fall Through */
02163         break;
02164     }
02165 }
02166         
02167 /* Reconnect() - action
02168  * This reconnects to the input method.  The user will typically call
02169  * this action if/when connection has been severed, or when the app
02170  * was started up before an IM was started up.
02171  */
02172 
02173 /*ARGSUSED*/
02174 static void
02175 Reconnect( w, event, params, num_params )
02176     Widget w;
02177     XEvent* event;
02178     String* params;
02179     Cardinal* num_params;
02180 {
02181     _XawImReconnect( w );
02182 }
02183         
02184 
02185 XtActionsRec _XawTextActionsTable[] = {
02186 
02187 /* motion bindings */
02188 
02189   {"forward-character",         MoveForwardChar},
02190   {"backward-character",        MoveBackwardChar},
02191   {"forward-word",              MoveForwardWord},
02192   {"backward-word",             MoveBackwardWord},
02193   {"forward-paragraph",         MoveForwardParagraph},
02194   {"backward-paragraph",        MoveBackwardParagraph},
02195   {"beginning-of-line",         MoveToLineStart},
02196   {"end-of-line",               MoveToLineEnd},
02197   {"next-line",                 MoveNextLine},
02198   {"previous-line",             MovePreviousLine},
02199   {"next-page",                 MoveNextPage},
02200   {"previous-page",             MovePreviousPage},
02201   {"beginning-of-file",         MoveBeginningOfFile},
02202   {"end-of-file",               MoveEndOfFile},
02203   {"scroll-one-line-up",        ScrollOneLineUp},
02204   {"scroll-one-line-down",      ScrollOneLineDown},
02205 
02206 /* delete bindings */
02207 
02208   {"delete-next-character",     DeleteForwardChar},
02209   {"delete-previous-character", DeleteBackwardChar},
02210   {"delete-next-word",          DeleteForwardWord},
02211   {"delete-previous-word",      DeleteBackwardWord},
02212   {"delete-selection",          DeleteCurrentSelection},
02213 
02214 /* kill bindings */
02215 
02216   {"kill-word",                 KillForwardWord},
02217   {"backward-kill-word",        KillBackwardWord},
02218   {"kill-selection",            KillCurrentSelection},
02219   {"kill-to-end-of-line",       KillToEndOfLine},
02220   {"kill-to-end-of-paragraph",  KillToEndOfParagraph},
02221 
02222 /* new line stuff */
02223 
02224   {"newline-and-indent",        InsertNewLineAndIndent},
02225   {"newline-and-backup",        InsertNewLineAndBackup},
02226   {"newline",                   InsertNewLine},
02227 
02228 /* Selection stuff */
02229 
02230   {"select-word",               SelectWord},
02231   {"select-all",                SelectAll},
02232   {"select-start",              SelectStart},
02233   {"select-adjust",             SelectAdjust},
02234   {"select-end",                SelectEnd},
02235   {"select-save",               SelectSave},
02236   {"extend-start",              ExtendStart},
02237   {"extend-adjust",             ExtendAdjust},
02238   {"extend-end",                ExtendEnd},
02239   {"insert-selection",          InsertSelection},
02240 
02241 /* Miscellaneous */
02242 
02243   {"redraw-display",            RedrawDisplay},
02244   {"insert-file",               _XawTextInsertFile},
02245   {"search",                    _XawTextSearch},
02246   {"insert-char",               InsertChar},
02247   {"insert-string",             InsertString},
02248   {"focus-in",                  TextFocusIn},
02249   {"focus-out",                 TextFocusOut},
02250   {"enter-window",              TextEnterWindow},
02251   {"leave-window",              TextLeaveWindow},
02252   {"display-caret",             DisplayCaret},
02253   {"multiply",                  Multiply},
02254   {"form-paragraph",            FormParagraph},
02255   {"transpose-characters",      TransposeCharacters},
02256   {"no-op",                     NoOp},
02257 
02258 /* Action to bind special translations for text Dialogs. */
02259 
02260   {"InsertFileAction",          _XawTextInsertFileAction},
02261   {"DoSearchAction",            _XawTextDoSearchAction},
02262   {"DoReplaceAction",           _XawTextDoReplaceAction},
02263   {"SetField",                  _XawTextSetField},
02264   {"PopdownSearchAction",       _XawTextPopdownSearchAction},
02265 
02266 /* Reconnect to Input Method */
02267   {"reconnect-im",       Reconnect} /* Li Yuhong, Omron KK, 1991 */
02268 };
02269 
02270 Cardinal _XawTextActionsTableCount = XtNumber(_XawTextActionsTable);

Generated on Sun Mar 4 15:03:55 2007 for Scilab [trunk] by  doxygen 1.5.1