39) How can I replace characters typed with say a `*'? I want to

replace input for password entry.

[Last modified: April 93]

Answer: In Motif 1.1 Use the modifyVerifyCallback to tell when input is
received.  Set text->ptr in the callback structure to '*'. This does not work
under 1.0 because of an oversight in which changes to this are ignored.  In
Motif 1.0, what you can do is set the doit flag to 'false' so the text is not
displayed. Then set a static boolean to True to prevent re-entrance.  Next
call XmTextReplace() to display your '*'.  then reset your re-entrance flag to
False.  XmTextReplace() will call the XmNmodifyVerify callback.  To prevent
getting into an infinite loop, you need the re-entrance flag.

The following program from Dan Heller illustrates this:

--------------
/* Written by Dan Heller.  Copyright 1991, O'Reilly && Associates.
 * This program is freely distributable without licensing fees and
 * is provided without guarantee or warranty expressed or implied.
 * This program is -not- in the public domain.  This program appears
 * in the Motif Programming Manual, O'Reilly Volume 6.
 */

/* passwd.c -- prompt for a passwd.  Meaning, all input looks like
 * a series of *'s.  Store the actual data typed by the user in
 * an internal variable.  Don't allow paste operations.  Handle
 * backspacing by deleting all text from insertion point to the
 * end of text.
 */
#include <Xm/Text.h>
#include <Xm/LabelG.h>
#include <Xm/RowColumn.h>
#include <ctype.h>

void check_passwd();
char *passwd; /* store user-typed passwd here. */

main(argc, argv)
int argc;
char *argv[];
{
    Widget        toplevel, text_w, rowcol;
    XtAppContext  app;

    toplevel = XtVaAppInitialize(&app, "Demos",
        NULL, 0, &argc, argv, NULL, NULL);

    rowcol = XtVaCreateWidget("rowcol",
        xmRowColumnWidgetClass, toplevel,
        XmNorientation, XmHORIZONTAL,
        NULL);

    XtVaCreateManagedWidget("Password:",
        xmLabelGadgetClass, rowcol, NULL);
    text_w = XtVaCreateManagedWidget("text_w",
        xmTextWidgetClass, rowcol, NULL);

    XtAddCallback(text_w, XmNmodifyVerifyCallback, check_passwd, NULL);
    XtAddCallback(text_w, XmNactivateCallback, check_passwd, NULL);

    XtManageChild(rowcol);
    XtRealizeWidget(toplevel);
    XtAppMainLoop(app);
}

void
check_passwd(text_w, unused, cbs)
Widget        text_w;
XtPointer     unused;
XmTextVerifyCallbackStruct *cbs;
{
    char *new;
    int len;

    if (cbs->reason == XmCR_ACTIVATE) {
        printf("Password: %s\n", passwd);
        return;
    }

    if (cbs->text->ptr == NULL) { /* backspace */
        cbs->endPos = strlen(passwd); /* delete from here to end */
        if (cbs->endPos <= 0) return; /* catch null passwd - Mark Scoville */
        passwd[cbs->startPos] = 0; /* backspace--terminate */
        return;
    }

    if (cbs->text->length > 1) {
        cbs->doit = False; /* don't allow "paste" operations */
        return; /* make the user *type* the password! */
    }

    new = XtMalloc(cbs->endPos + 2); /* new char + NULL terminator */
    if (passwd) {
        strcpy(new, passwd);
        XtFree(passwd);
    } else
        new[0] = NULL;
    passwd = new;
    strncat(passwd, cbs->text->ptr, cbs->text->length);
    passwd[cbs->endPos + cbs->text->length] = 0;

    for (len = 0; len < cbs->text->length; len++)
        cbs->text->ptr[len] = '*';
}
Go Back Up

Go To Previous

Go To Next