Parent document is top of "Motif FAQ (Part 4 of 9)"
Previous document is "101) How can I stop the text widget from echoing characters typed?"
Next document is "103) How can I best add a large piece of text to a scrolled text"

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

replace input for password entry.

[Last modified: Nov 96]

Answer:  The solution involves the use of XmNmodifyVerifyCallback and then
examining the XmTextVerifyCallbackStruct.  The following program from Dan
Heller and Paula Ferguson illustrates this:

/* Written by Dan Heller and Paula Ferguson.
 * Copyright 1994, O'Reilly & Associates, Inc.
 * Permission to use, copy, and modify this program without
 * restriction is hereby granted, as long as this copyright
 * notice appears in each copy of the program source code.
 * This program is freely distributable without licensing fees and
 * is provided without guarantee or warrantee expressed or implied.
 * This program is -not- in the public domain.
 *
 * 9Sept1996 RAF -- this is a working version, at least under Sol2.4,
 * using gcc.  I only modified check_passwd().
 *
 */

/* password.c -- prompt for a password. 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;

    XtSetLanguageProc (NULL, NULL, NULL);

    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);
}

/* check_passwd() -- handle the input of a password. */
void
check_passwd(text_w, client_data, call_data)
Widget        text_w;
XtPointer     client_data;
XtPointer     call_data;
{
    char *new;
    char *oldpasswd;
    int len;
    XmTextVerifyCallbackStruct *cbs =
        (XmTextVerifyCallbackStruct *) call_data;

    if (cbs->reason == XmCR_ACTIVATE) {
        printf ("5assword: %s0, passwd);
        return;
    }

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

    if( cbs->startPos < cbs->endPos ) {
        /* shrink the password by moving endPos... characters forward to
        /* the point of deletion */
        memmove( &(passwd[cbs->startPos]),
                 &(passwd[cbs->endPos]),
                 strlen(passwd) - cbs->endPos + 1 );
        if( cbs->text->length == 0 ) /* then just a delete, not a replace */
            return;
    }

    new = XtMalloc( cbs->text->length + 1 );
    strncpy( new, cbs->text->ptr, cbs->text->length ); /* just the new chars */
    new[cbs->text->length]=' ';

    if( passwd ) {
        /* open a hole for the new characters, and insert them
        /* in the proper place */
        passwd = XtRealloc( passwd, strlen(passwd) + cbs->text->length + 1 );
        memmove( &(passwd[cbs->startPos + cbs->text->length]),
                 &(passwd[cbs->startPos]),
                 strlen(passwd) - cbs->startPos + 1 );
        memcpy( &(passwd[cbs->startPos]), new, cbs->text->length );
    } else {
        passwd = new;
    }

    memset( cbs->text->ptr, '*', cbs->text->length ); /* makes it all stars */

}


Thanks to OM1_JDA@pki-nbg.philips.de (Joerg Danne) for alerting me to updating
this code sample. Thanks also to Russell Fink (rfink@polaris.umuc.edu) for
providing the Nov. 1996 code update.

Parent document is top of "Motif FAQ (Part 4 of 9)"
Previous document is "101) How can I stop the text widget from echoing characters typed?"
Next document is "103) How can I best add a large piece of text to a scrolled text"