[comp.windows.x] Changing case in a Motif Text Widget?

chuck@Morgan.COM (Chuck Ocheret) (11/08/89)

All I want to do is have a Text widget which inverts upper/lower
case keystrokes. That is, when you type a lower case 'm', an upper
case 'M' should appear in the widget and vice versa.  Other keys
should be unaffected.

Section 10.5, "KeyCode-to-KeySym Conversions" of the X Intrinsics
manual (X11, Release 3, Oct. 1988) specifies how to provide your own
key translator with XtSetKeyTranslator().  After lifting code for
the default key translator, the following translator was produced:

void myTranslateKey(dpy, keycode, modifiers,
                            modifiers_return, keysym_return)
	Display		*dpy;
	KeyCode		keycode;
	Modifiers	modifiers;
	Modifiers	*modifiers_return;
	KeySym		*keysym_return;
{
	KeySym		ks;
	XtPerDisplay	perDisplay;

	perDisplay = _XtGetPerDisplay(dpy);
	*modifiers_return = 0;
	if ((modifiers & StandardMask) == 0)
		ks =_XtKeyCodeToKeySym(dpy,perDisplay,keycode,0);
	else if ((modifiers & (ShiftMask | LockMask)) != 0)
		ks =_XtKeyCodeToKeySym(dpy,perDisplay,keycode,1);
	else
		ks = NoSymbol;

	if (ks >= XK_a && ks <= XK_z)
		ks = ks-0x20;
	else if (ks >= XK_A && ks <= XK_Z)
		ks = ks+0x20;

	*keysym_return = ks;
}

Dbx shows that this function does indeed get called and it does the
translation.  However, the Text widget still shows untranslated
keystrokes.  What am I doing wrong?  Is there some other mechanism
I should be using?  Do I really have to provide a big table for the
translation manager?

--
+------------------+   Chuck Ocheret, Sr. Staff Engineer   +------------------+
| chuck@morgan.com |       Morgan Stanley & Co., Inc.      |  (212)703-4474   |
|   Duty now ...   |19th Floor, 1251 Avenue of the Americas| for the future.  |
+------------------+       New York, N.Y.  10020 USA       +------------------+

swick@ATHENA.MIT.EDU (Ralph R. Swick) (11/08/89)

> Dbx shows that this function does indeed get called and it does the
> translation.  However, the Text widget still shows untranslated
> keystrokes.  What am I doing wrong?

Probably nothing.  I can't speak authoritatively for Motif, but I
suspect that they're doing the same thing that the R3 Xaw Text widget
does; i.e.  re-interpreting the XEvent in the action proc using
straight Xlib functions.  In R3 there was no support for a client of
Xt discovering the resulting KeySym that the Xt translation manager
produced when it called an action proc.  This addition is a part of
the R4 proposed changes.

ries@venice.SEDD.TRW.COM (Marc Ries) (11/09/89)

In article <CHUCK.89Nov7121348@s6.Morgan.COM> chuck@Morgan.COM (Chuck Ocheret) writes:
>All I want to do is have a Text widget which inverts upper/lower
>case keystrokes. That is, when you type a lower case 'm', an upper
>case 'M' should appear in the widget and vice versa.  Other keys
>should be unaffected.

  While the following example (highlight the text, then "U" or "L" keystroke
  will translate the highlighted text to upper or lower) does not solve your 
  problem, it >might< give you something to go on [I haven't run this through
  a compiler so there may be some typos]:

/*
 *  RESOURCES
 *  toplevel*text.editMode:               MULTI_LINE_EDIT
 *  toplevel*text.rows:                   20
 *  toplevel*text.columns:                70
 *  toplevel*text.insertionPointVisible:  TRUE
 *  toplevel*text.autoShowCursorPosition: TRUE
 */

#include <Xm/MainW.h>
#include <Xm/Text.h>

void myTextAction ();
XtActionsRex myTextActions[] =
    {"changeCase", (XtActionProc) myTextAction) };

String myTransUpper = "Ctrl<Key>U:  changeCase(U)";
String myTransLower = "Ctrl<Key>L:  changeCase(L)";

void main(argc, argv)
     unsigned int   argc;
     char         **argv;
{
     Widget         toplevel, main, text;
     Arg            myArgs[10];
     int            i;
     toplevel = XtInitialize (argv[0], "toplevel", NULL, 0, &argc, argv);

     main = XmCreateMainWindow(toplevel, "main", (Arglist)NULL, (Cardinal)0);
     XtManageChild(main);

     text = XmCreateScrolledText(main, "text", (Arglist)NULL, (Cardinal)0);
     XtManageChild(text);

     XtAddActions(myNewActions, XtNumber (myNewActions);
     XtOverrideTranlations(text, XtParseTranslationTable(myTransUpper));
     XtOverrideTranlations(text, XtParseTranslationTable(myTransLower));

     XtRealizeWidget(toplevel);

     XtMainLoop();
}

/ARGSUSED*/
void myTextAction(w, ev, params)
       Widget     w;
       XEvent    *ev;
       String    *params;
{
       int        i=0;
       char      *myStr = XmTextGetSelection(w);
       XmTextPosition tpos;
       Arg        al[2];
       int        ac;

       if(myStr != NULL)
           {
           DeletePrimarySelection(w);

           switch(params[0][0]) {
               case 'L': i = 0;
                         while(myStr[i] != '\0'
                             {
                             myStr[i] = tolower(myStr[i]); i++
                             }
                         break;
               case 'U': i = 0;
                         while(myStr[i] != '\0'
                             {
                             myStr[i] = toupper(myStr[i]); i++
                             }
               default:  break;

           }
       ac = 0;
       XtSetArg(al[ac], XmNcursorPosition, &tpos); a++;
       XtGetValues(w, al, ac);
       XmTextReplace(w, tpos, tpos, myStr);
       XtFree(myStr);
       }
}

void DeletePrimarySelection(w)
       Widget w;
{
       XClientMessageEvent cm;

       cm.type = ClientMessage;
       cm.display = XtDisplay(w); 
       cm.message_type = XmInternAtom(XtDisplay(w), "KILL_SELECTION", FALSE);
       cm.window = XtWindow(w); 
       cm.format = 32;
       cm.data[0] = XA_PRIMARY;
       XSendEvent(XtDisplay(w), cm.window, TRUE, NoEventMask, &cm);
}

-- 
Marc Ries
           ries@venice.sedd.trw.com     (ARPA)
           somewhere!trwind!venice!ries (UUCP)
           #include <std.disclaimer>