From: ksall@cen.com (Ken Sall)
Newsgroups: comp.windows.x.motif,comp.answers,news.answers
Subject: Motif FAQ (Part 3 of 9)
Date: 7 May 1995 12:28:43 GMT
Organization: none
Approved: news-answers-request@MIT.EDU
Expires: 20 Jun 1995 12:27:35 GMT
Message-ID: <motif-faq/part3_799849655@rtfm.mit.edu>
Reply-To: ksall@cen.com (Ken Sall)
Keywords: FAQ question answer

Archive-name: motif-faq/part3
Last-modified: MAY 05, 1995
Posting-Frequency: monthly
Organization: Century Computing, Inc. <URL:http://www.cen.com/>
Version: 4.4




-----------------------------------------------------------------------------
Subject: 64)  TOPIC: MOTIF DEVELOPMENT TOOLS (GUI BUILDERS and UIMS's)

-----------------------------------------------------------------------------
Subject: 65)  What GUI tools exist to assist in developing Motif applications?

[Last modified: Mar 95 ]

Answer: [A FAQ is not for "personal opinions" on these tools.  I don't think
it is appropriate to give such opinions through this particular posting, so I
haven't included any. I will include vendor-provided descriptions provided
they are concise and informative. See Subject 0 for contribution details.]

`Prototyping tools' and `code generation tools' come in two forms:

    GUI (Graphical User Interface) builder -
    those that can be used to design (and perhaps rehearse)
    the interface only ; and

    UIMS (User Interface Management Systems) -
    those that are a system supporting the development and
    execution of user interfaces.

However, this distinction can be somewhat arbitrary when specific tools are
categorized as either one or the other.  (Therefore, the classification below
should be taken with a kilogram of salt. :-)

A number of commercial and non-commercial tools of both kinds that will
support Motif are listed below. [NOTE: Vendors or individuals wishing to add
their product or tool to this list, or to change their entry, should email to
the maintainer of this FAQ.]

GUI builders:

        Builder Xcessory (bx)
        Druid
        ExoCODE/xm
        iXBUILD (formerly X Build)
        MOTIFATION
        WKSH (Windowing Korn Shell)
        X-Designer

UIMS:

        ALEX
        ezX User Interface Management System
        Galaxy
        MetaCard
        Serpent
        TAE Plus
        TeleUse
        UIMX
        VXP (Visual X windows Programming Interface)
        Widget Creation Library (Wcl)
        WINTERP
        XFaceMaker2


For users of the WWW, see also Brad A. Myers' `User Interface Software Tools'
list (which is not limited to Motif tools):
http://www.cs.cmu.edu:8001/afs/cs.cmu.edu/user/bam/www/toolnames.html


Some contact addresses, presented in alphabetical order (without regard to GUI
or UIMS categorization), follow:


o  ALEX: For more information contact Michael Karliner on (+44) 81 566 2307 or
E-mail to alex@s-strat.co.uk.  ALEX Technologies, Waterman's Yard, 32a The
Mall, Ealing, London W5, UK.


o  Builder Xcessory (bx): is from ICS.  More details are available by sending
a request to info@ics.com.  Address:


        ICS Inc.,
        201 Broadway,
        Cambridge MA 02139,
        Tel. (617) 621-0060,
        Fax. (617) 621-9555
        http://www.ics.com/


o  Druid: is a commercial product. It currently supports Motif1.1 and 4 unix
platforms: SPARC, HP 9000, RS6000, and SGI. For further information contact:

        Mr. Fred Lee,
        Automated Systems (Pte) Limited,
        203 Henderson Road, #12-07/14,
        Henderson Industrial Park,
        Singapore 0315.
        FAX: (65)272-2029


Or: Dr. Gurminder Singh (gsingh@iss.nus.sg), Institute of Systems Science,
National University of Singapore


o  ExoCODE/xm: By Expert Object Corp., 7250 Cicero Avenue, Lincolnwood, IL
60646 (708)676-5555.  Also: ExoCODE, EXOC, 500 Hyacinth Place, Highland Park,
IL, 60035, (708) 926-8500, $1,500, Motif or OpenLook or SunView.


o  ezX: Contact information:

        ezX User Interface Management System
        Sunrise Software, International
        170 Enterprise Center
        Middletown, RI 02840
        401-847-7868
        email: support@sunrise.com


o  Galaxy, Visix Software Inc., 11440 Commerce Park Drive, Reston, VA, 22091,
(800) 832-8668, $9,600, Mac, Windows, Motif, OpenLook; very complete, Virtual
Toolkit, UIMS


o  iXBUILD (formerly X Build):

        iXOS Software GmbH,
        Bretonischer Ring 12,
        8011 Grasbrunn/Munich, Germany,
        email support@ixos.de or office@ixos.de,
        phone ++49-89-46005 0

or in the US:

        UniPress Software,
        2025 Lincoln Hwy.,
        Edison, NJ 08817,
        phone 1-800-222-0550


o  MetaCard: MetaCard 1.0 is supported on five popular UNIX/X11 platforms:
SPARC, Sun3, DECstation, HP-9000/300, and SCO ODT.  An HP-9000/700 port is
underway and should be available by the end of July.  [They] plan to support
IBM RS/6000, SGI Iris, and DG AViiON sometime fall '92.  For more information,
or to receive a free save-disabled but licensable copy of MetaCard, email to
info@metacard.com or call 303- 447-3936.  If you have anonymous FTP access to
the Internet, you can download the current engines, documentation, and an
unlicensed Home stack from ftp.metacard.com (128.138.213.21), directory
MetaCard.  Commercial users can get MetaCard from world.std.com
(192.74.137.5), directory pub/Metacard.  If you don't have an anonymous ftp
access, you can also download MetaCard from The World using kermit or xmodem
from the ~ftp/pub/MetaCard directory.  Sign up by calling 617-739-0202 (voice)
or via modem by dialing 617-739-9753 (7 bits even parity) and logging in as
new.

MetaCard 1.2 Beta 5 is now available for anonymous FTP from ftp.metacard.com
(directory MetaCard/1.2B5), and ftp.uu.net (directory vendor/MetaCard/1.2B5).

There is also a MetaCard mailing list.  To subscribe to the metacard-list,
send mail to listserv@grot.starconn.com with the following commands in the
body of the message:

      subscribe metacard-list firstname lastname
      quit

Replace "firstname lastname" with your name, not your e-mail address.


o  MOTIFATION: PEM GmbH, Vaihinger Strasse 49, 7000 Stuttgart 80, Germany,
Tel: +49 (0) 711 713045, Fax: +49 (0) 711 713047 Email: basien@pem-
stuttgart.de.  Available for (Motif 1.2/1.1) on SunOS, Solaris 2.1, HP,
Interactive, ODT 3.0, Silicon Graphics, PCS, ...


o  Serpent: The S/W is free (anonymous ftp) from ftp.sei.cmu.edu.  For more
info contact erik/robert at serpent-info@sei.cmu.edu.  NOTE: This is no longer
supported, and is apparently replaced by a commercial product called Alpha.


o  TAE Plus: TAE Plus is a mature, portable software development environment
that supports rapid prototyping, tailoring, and management of Motif-based
graphical user interfaces.  It particularly supports GUI development by non-
programmers and by programmers who are not well-versed in the details of X and
Motif.  Its code generator can produce C, C++, and Ada code and allows for
automatic merging of regenerated code with previously modified parts of the
interface code.  It supports generation of a UIL/Mrm representation of the
interface.

Scripting capabilities are provided to facilitate automatic testing, on-line
demos, and tutorials.  A record and playback feature lets you build scripts
simply by interacting with your GUI.  Dynamic Data Objects allow the developer
to create pictorial objects (e.g., a thermometer to show temperature), whose
dynamic portions (e.g., the mercury in the themometer) can change to reflect
changing data or be directly manipulated by the end-user. TAE Plus is
available on Sun, HP, IBM, SGI, and SCO Unix platforms.  Evaluation software
is available via anonymous ftp.

TAE Plus contact information:

        Century Computing, Inc.
        8101 Sandy Spring Road
        Laurel, MD 20707
        1-800-823-3228
        tae-info@cen.com
        http://www.cen.com/tae/


o  TeleUSE: Built around X Windows and OSF/Motif, TeleUSE's comprehensive
toolset gives you maximum control over every phase of graphical user interface
development, including static screen layout and design, automatic
implementation of callbacks, building the executable, and the interactive
test, debug, and maintenance cycles.  For more information, please contact:

In North America and countries not specified below:

        Alsys (formerly TeleSoft)
        10251 Vista Sorrento Parkway Suite 300
        San Diego, CA 92121 USA
        (619) 457-2700 X244
        (619) 452-1334 (fax)
        leigh@alsys.com

        In France: +33 1 47 66 21 83
        In the UK: +49 491 579 090
        In Scandinavia: +46 8 520 69010
        In the Benelux: +31 15 62 21 21
        In Germany: +49 7531 65022
        In Italy: +39 6 5045 1
        In Japan: +81 3 522 85620
        In South Korea: +82 2 577 2044


o  UIMX:

        Visual Edge Software Limited
        3870 Cote Vertu
        St Laurent, Quebec
        H4R 1V4
        Phone: (514) 332-6430
        Fax:   (514) 332-5914
or:
        Visual Edge Software Ltd.
        101 First Street, Suite 443
        Los Altos, CA 94022
        Phone: (415) 948-0753
        Fax:   (415) 948-0843


o  VXP (Visual X windows Programming Interface):

Yong Chen (stdyxc05@pip.shsu.edu) developed a Motif GUI builder called VXP --
Visual X windows Programming Interface. VXP has some UIMS capabilities. VXP is
now distributed as a freeware, and has been ported to SGI irix, HP hp-ux, Sun
OS4 and Solaris 2.x, DEC OSF/1, IBM AIX, Linux, SCO, NetBSD.  For more
information, visit VXP's WWW home page at

        http://www.shsu.edu/~stdyxc05/VXP/
or ftp at
        ftp.shsu.edu    /pub/VXP/


o  Widget Creation Library (Wcl): The distribution is available in several
ways.  The preferred approach it for you to get the compressed tar file using
anonymous ftp from:


        ftp.x.org       /R5contrib/Wcl-2.5.tar.Z
        WWW URL: ftp://ftp.x.org/R5contrib/Wcl-2.5.tar.Z


o  WINTERP: (Widget INTERPreter) An object-oriented rapid prototyping,
development and delivery environment for building extensible applications with
the OSF/Motif UI Toolkit and Xtango-based graphics/animation. By Niels Mayer
(mayer@netcom.com).  Mailing list: winterp-request@netcom.com. Available via
ftp from ftp.x.org:/contrib/devel_tools/winterp-2.xx.tar.gz (where 'xx' is
currently '03').

Key WINTERP Features:

        * High-level, Object-oriented interface to OSF/Motif and Xtoolkit.
        * High-level object-oriented 2.5D graphics&animation widget based
          on Xtango path transition animation system.
        * Ability to easily create new widget classes w/ complex graphical
          behavior using Xtango animation/graphics.
        * Automatic storeage management of all X/Xt/Motif data, Pixmaps,
          animations. Automatic resource conversion and management.
        * Asynchronous communications w/ other unix programs via
          expect-based subprocess facility.
        * Includes XmGraph to display graphs (both cyclic, acyclic,
          directed, undirected); graph nodes can be arbitrary widgets
          created by WINTERP; supports direct manipulation editing of graph.
        * GIF image support.
        * Lisp-eval server architecture supports inter-application
          communication.
        * Interactive programming via Gnu-Emacs or Motif-Text-widget interface.
        * Portable, small, fast, and free.


o  WKSH (Windowing Korn Shell):

        EXtensible Korn Shell (C language calling interface,
        dynamic library loading, etc.)
        Motif or OpenLook API
        X Toolkit Intrinsics
        WKSH Convenience Functions
        Fast Learning and Prototyping Feature (ksh interpreter)
Contact:
        Acacia Computer,
        PO Box 4376,
        Warren, NJ 07059,
        Phone: 908 548 6955,
        Email: uunet!aca1


or: Computer Aid Inc, 1-(800)-444-WKSH, or:


        Consensys Corp,
        Europe: +(44)-734-833241 (Roger Chalke), +(44)0734-835391 (Fax),
        US: (416)-940-2903, (416)-940-2903 (Fax).


WKSH was developed by USL. Binaries are available through Acacia Computer for
SUNOS, Solaris, SCO ODT, Intel SVR4.0


o  X-Designer: From Imperial Software Technology in the UK.  Email address is
sales@ist.co.uk.  (+44) 743 587055

V.I. Corporation have become the distributor for the X-Designer product in the
United States.  In addition, IST and V.I. Corporation have developed a product
called DVX-Designer that merges X-Designer with their GUI product called
DataViews.  Other merged products are in the works.  For more information,
people can contact:

        V.I. Corporation
        47 Pleasant Street
        Northampton, MA  01060
        Phone: (413) 586-4144
        Fax: (413) 586-3805
        Email: vi@vicorp.com


o  XFaceMaker2:

        NSL -  Non Standard Logics S.A.,
        57-59, rue Lhomond,
        75005  Paris - France,
        Phone: +33 (1) 43.36.77.50,
        Fax:   +33 (1) 43.36.59.78
        email: requests@nsl.fr or requests%nsl.fr@inria.fr for information.

Their North American office:

        Non Standard Logics, Inc.,
        4141 State Street, Suite B-11,
        Santa Barbara CA 93110,
        Tel: 805 964 9599,
        Fax: 805 964 4367

-----------------------------------------------------------------------------
Subject: 66)  TOPIC: GEOMETRY MANAGEMENT

[NOTE: As you can see, this is a new topic area. Send me your ideas for
answered questions pertaining to this topic.]

-----------------------------------------------------------------------------
Subject: 67)  Why is geometry management so important?

[Last modified: Sept 94]

Answer: Geometry management is a key element of Motif applications for reasons
which include, but are not limited to, the following:


    The user should be able to re-size the shell and get
    some reasonable geometry response (other than clipping).

    The user should be able to tailor fonts and have the
    widgets adjust accordingly.  (Many people over 40 simply
    can't read small fonts without serious eye strain.)

    When the designers decide to change a label, the widgets
    should re-adjust accordingly.

    Some labels must be set dynamically and the widgets should
    re-layout accordingly.

    An internationalized application must work with several resource
    files, one for each supported natural language.  The labels in each
    file have different lengths and the application should adjust
    accordingly.


-----------------------------------------------------------------------------
Subject: 68)  What are good references for reading about geometry management?

[Last modified: Oct 94]

Answer: See the BOOKS topics for detailed reference information.  "X Toolkit
Intrinsics Programming Manual" (Nye & O'Reilly) contains an entire chapter on
geometry management, as does "X Window System Toolkit" (Asente & Swick) on
which the O'Reilly book is based.  Another good reference is the discussion of
the "geometry_manager" and "query_geometry" methods in "X Toolkit Intrinsics
Reference Manual".

"Motif Programming Manual" (Heller & Ferguson) has a chapter devoted to Motif
Manager widgets.  Finally, the widget documentation for each geometry manager
widget typically describes its policy in detail.

-----------------------------------------------------------------------------
Subject: 69)  Why don't my labels resize in a RowColumn widget?  I have a
RowColumn widget in my application, with several rows and columns of XmLabels.
When I update the text in the labels, the label's width does not get updated.

[Last modified: Oct 94]

Answer: Make sure all the ancestor widget resize mechanisms are enabled:

   - on shells, set XmNallowShellResize
   - on row column, set XmNresizeWidth and XmNresizeHeight
   - on bulletin board and form, set XmNresizePolicy

Also, set XmNrecomputeSize on the label itself.  The shell resource is off by
default; the others should be on by default.

Thanks to Ken Lee, kenton@rahul.net

-----------------------------------------------------------------------------
Subject: 70)  Why do dialogs appear smaller under 1.2.3 and later?  The same
problem occurs with parts of a complex main window.  All of my dialogs which
were fine under 1.2.2 and earlier come up too small to work with under 1.2.3
(or later). Why?

A. Thanks to David Brooks (dbrooks@ics.com) for pointing me to Daniel
Dardailler (daniel@x.org) who wrote this scholarly treatise:

      Application's Geometry Management Advanced Guidelines:
      =====================================================
      (or "How to properly manage children of already realized parent")

Xt Background:
-------------

    XtCreateWidget:        call Initialize ;

    XtManageChild:         if (parent realized)
                              call ChangeManaged ;
                              call Realize ;

    XtRealizeWidget:       postorder ChangeManaged loop ;
                           preorder Window-creation loop ;


Creating a widget only invokes its Initialize method (its parent's
InsertPosition method too, but that has nothing to do with GM).
Composite widgets, by opposition to Primitive, does
not usually get a correct size at initialization time, since their
correct size is based on their children sizes, which do not exist yet
at this time.

Applications usually create an entire tree of managed but
unrealized widgets and then realize their top level widget, which recursively
realize every widgets in the tree. During the creation process, the
managing of the unrealized widgets is a no-op (only mark them managed).

When XtRealizeWidget(toplevel) happens, the change_managed methods of
all the composite widgets in the tree are called in bottom-to-top
order, thus giving each of them a chance to determine their own size
based on their children *current* sizes (composite or not).
Using the current size of the children in this situation is fine,
since they should also be the children's preferred size, not
yet constrained by the parents layout (post-order traversal).

When one create a widget inside an already realized parent, this is
a different story and the order of management vs realization is important.

Consider a MessageBox created in a realized Frame.
The MessageBox itself creates a bunch of managed children
inside its Initialize method.
If you manage the MessageBox right after its creation, the Frame
ChangeManaged will be called (since it is realized), and its will use
the MessageBox current size as its base for its own size.
Unfortunately, the MessageBox ChangeManaged proc has never been called!
so its current size is whatever the default is, usually a non-settable
value (needed for tracking real initial size setting).
The MessageBox ChangeManaged has not been called because its children
were created and managed at a time where it wasn't realized.

What to do ?

The first solution would be to have all the ChangeManaged methods in
Motif call XtQueryGeometry instead of using the current size if it's
not the first time (i.e. if they're already realized).
But this is a lot of code to change and a kind of expensive run-time
process as it results in non-linear traversal order of the realized
tree (looks like an O(n!) but I'm not sure).
It's not even guaranteed that it will always work fine, since it relies on
the assumption that the geometry queried is the same that the geometry
asked for any manager (I mean, it might be the case, but if it's not,
it's just more code to fix in a very "bc-sensitive" part of Xm).


This other solution lies into the application, and is to realize a
manager first and then to manage it.
By realizing it, you are forcing its ChangeManaged proc to be
called (XtRealizeWidget does that), it will get a correct size and
this size will be used by its parent ChangeManaged when
you'll manage the manager. By explicitly realizing the branch
before managing its root, you are reproducing the ordering that
is typical of most applications at startup.

So the trick is:

        XtCreateWidget(realize_parent, MessageBox);
        XtRealizeWidget(MessageBox);  /* needed */
        XtManageChild(MessageBox);

and the model is:

    "Always explicitly realize a composite widget child of an already
     realized parent before managing it if all its children have been
     already managed"

One can always realize every widget children of realized parents, that
won't hurt, but it's useless for Primitives and Composites that
get more children added later in the program.
Why? because Primitives get their correct size at initialization
time anyway and adding a child to a Composite will generate a geometry
request and a layout that will have the same effect as if the
ChangeManaged method had been called (well, nearly the same effect,
that a complication I will address later).

If we consider Motif, this trick is only useful for MessageBox,
SelectionBox and subclasses, and Scale, since those are the only
Composites that create managed children in their Initialize method and
don't usually get additional kids from the application.

However, any application that re-creates this order of actions will
need to apply the "realize<manage" method too.
For instance:

        XtCreateWidget(realize_parent, DrawingArea);
        XtRealizeWidget(DrawingArea);   /* not needed */
        XtManageChild(DrawingArea);
        XtCreateWidget(DrawingArea, any_child) ;
        XtManageChild(any_child);
but
        XtCreateWidget(realize_parent, DrawingArea);
        XtCreateWidget(DrawingArea, any_child) ;
        XtManageChild(any_child);
        XtRealizeWidget(DrawingArea);   /* needed */
        XtManageChild(DrawingArea);

Now this is becoming interesting: there are exceptions to the model :-)

The first one is the Xt Shell widget, which has what I consider to be a
bug, but what MIT has, until recently, always considered to be a specific
behavior overridable by a subclass (like our VendorShell):
the ChangeManaged method always resizes the child to its own size
when the Shell is realized.

A side effect of this behavior is that even the realized<managed trick
won't work for direct descendant of Shell widget:

        XtCreateWidget(realize_shell, MessageBox);
        XtRealizeWidget(MessageBox);  /* needless */
        XtManageChild(MessageBox);    /* will get resized anyway */

To get rid of this problem, one needs to add a regular manager
between the Shell and the MessageBox in this case, for the sake
of having this manager doing a request to the Shell from its
ChangeManaged proc. This request will then be handled by the Shell
geometry manager, not its ChangeManaged proc, and it will take into
account the child size.
Note that we could also change our VendorShell ChangeManaged code to not
systematically envelop the Xt Shell ChangeManaged class method, and
check for the already realized case, but I would rather wait
for an Xt fix instead (I'm working on it).

If you broader the scope of the Xt Shell situation, you find that there are
also some resources in Xm that come into effect upon geometry request
reception but are not used in the ChangeManaged method.

Take the PanedWindow constraint resource XmNallowResize for instance,
which controls the validity of a geometry request made by a PW child.

If you do:

        XtCreateWidget(realize_shell, PanedWindow);
        XtManageChild(PanedWindow);

        XtCreateWidget(PanedWindow, button);
        XtManageChild(button);

that works fine since the ChangeManaged of the PanedWindow will
handle the insertion of the button and allowResize won't be used.

But if you add a manager in this hierarchy:

        XtCreateWidget(realize_parent, PanedWindow);
        XtManageChild(PanedWindow);

        XtCreateWidget(PanedWindow, manager);
        XtManageChild(manager);

        XtCreateWidget(manager, button);
        XtManageChild(button);

That doesn't work anymore since the button management results in
its parent manager's ChangeManaged being called, which in turn makes a
*request* to the PanedWindow, resulting in a No reply because
of allowResize (set to False by default).

The PanedWindow parent wouldn't have been realized that everything
would have worked fine, since no request would have been made.
It really depends on the early realization scheme.

I think XmNresizable in Form is the only other resource to present
this problem. There is not much to do in those cases except than
setting the corresponding resource to True, which makes sense.


-----------------------------------------------------------------------------
Subject: 71)  TOPIC: TEXT WIDGET

-----------------------------------------------------------------------------
Subject: 72)  How do XmTextField and a single line XmText widget differ?

[Last modified: Oct 94]

Answer: XmTextField is designed to be a lightweight, single line text editor.
It does not provide as much functionality as does XmText in order to achieve
better performance.

Thanks to Kevin Till, kev@osf.org

-----------------------------------------------------------------------------
Subject: 73)  Why does  pressing  <return> in a text widget do nothing?  This
happens using Motif 1.0 when I have a text widget inside a bulletin board (or
form) inside a dialog shell. (In Motif 1.1 it is fixed for both text and list
widgets.)

Answer: In single line mode, pressing the <return> key usually invokes the
activate() action, and in multi-line mode, the newline() action.  However,
whenever a widget is the child of a bulletin board widget which is the child
of a dialog shell, the bulletin board forces all of its children to translate
<return> to the bulletin board action Return() which is usually associated
with the default button of the dialog.  To restore the text actions of
activate() or newline(), you need to overide the Return() action of the
bulletin board.


        /* declarations */
        /* for a single line widget */
        char newTrans[] = "<Key>Return : activate()";
        /* for a multi line widget */
        char newTrans[] = "<Key>Return : newline()";
        XtTranslations transTable;

        /* in executable section */

        transTable = XtParseTranslationTable(newTrans);

        /* after creating but before managing text widget */

        XtOverrideTranslations(textWidget, transTable);


-----------------------------------------------------------------------------
Subject: 74)  When I add text to a scrolling text widget, how can I get the
new text to show?

[Last modified: Sept 94]

Answer: Use the (fully supported) function XmTextShowPosition:

        void XmTextShowPosition(w, position)
        Widget w;
        XmTextPosition position;

where the position is the number of characters from the beginning of the
buffer of the text to be displayed. If you don't know how many characters are
in the buffer, use XmTextGetLastPosition.

        position = XmTextGetLastPosition(w)


-----------------------------------------------------------------------------
Subject: 75)  Does the text widget support 16 bit character fonts?


[Last modified: November 92]

Answer: R5 has support for 16 bit character sets, and Motif 1.2 uses that.
Neither Motif 1.0 nor 1.1 support 16 bit sets.

-----------------------------------------------------------------------------
Subject: 76)  How can I stop the text widget from echoing characters typed?  I
need to turn off echo for password input.

Answer: Use the XmNmodifyVerifyCallback to tell when input is received. Set
the `doit' field in the XmTextVerifyCallbackStruct to False to stop the echo.
(In Motif 1.0 this will cause a beep per character: Live with it, because at
1.1 you can turn it off.) Note that password hiding is inherently insecure in
X - someone may have an X grab on the keyboard and be reading all characters
typed in anyway.

Another solution often proposed is to set the foreground and background
colours to be the same, effectively hiding the text.  This has a major flaw:
someone may select the text (triple click the mouse to get the line), and then
paste the password into say an xterm with *different* foreground and
background colours.  This immediately shows the password.

-----------------------------------------------------------------------------
Subject: 77)* How can I replace characters typed with say a `*'?  I want to
replace input for password entry.

[Last modified: May 95]

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.
 */

/* 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;
    int len;
    XmTextVerifyCallbackStruct *cbs =
        (XmTextVerifyCallbackStruct *) call_data;

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

    if (cbs->startPos < cbs->currInsert) {   /* backspace */
        cbs->endPos = strlen (passwd);       /* delete from here to end */
        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] = '*';
}

Thanks to OM1_JDA@pki-nbg.philips.de (Joerg Danne) for alerting me to updating
this code sample.

-----------------------------------------------------------------------------
Subject: 78)  How can I best add a large piece of text to a scrolled text
widget?

[Last modified: Sept 94]

[NOTE: This problem is probably only relevant for Motif 1.0 which probably no
one is using anymore. If you know this to still be a problem, send mail to
ksall@cen.com. I'll probably remove this question otherwise.]

In some versions of Motif 1.0 even using XmTextSetString, it insists on adding
the text one line at a time, adjusting the scroll bar each time. It looks
awful and is slow.

Answer: If you don't have this problem, use XmTextSetString to set all of the
text in the widget.  If you do have this slowdown problem even using
XmTextSetString, unmanage the widget, add the text and then manage it again.
This may cause the window to blink, but you have to put up with that or switch
to a different version of Motif.

-----------------------------------------------------------------------------
Subject: 79)  How can I highlight text in the Text widget?

Answer: argv@zipcode.com (Dan Heller) wrote:

If you don't need font or color changes, you can do all this using a Text
widget very easily [in Motif 1.1, anyway].

        loop() {
            pos = offset_of_pattern_in_text_widget(pattern, text_w);
            search_len = strlen(pattern);
            XmTextSetHighlight(text_w, pos, pos+search_len,
                        XmHIGHLIGHT_SELECTED);
        }


There are two choices for highlighting: reverse video (HIGHLIGHT_SELECTED) and
underlined (HIGHLIGHT_SECONDARY_SELECTED).  Be careful that your users won't
confuse your highlights with actual selections!

-----------------------------------------------------------------------------
Subject: 80)  How can I select all of the text in a widget programmatically?
So that some initial text is displayed, but anything typed replaces it.

Answer: XmTextSetSelection(Text1, 0, XmTextGetLastPosition(Text1), event-
>xbutton.time);

where Text1 is the widget in question (obviously) and event is some event that
triggered this call.  You can use XtLastTimestampProcessed( display) instead
of xbutton.time if you don't happen to have an event pointer handy.


-----------------------------------------------------------------------------
Subject: 81)  How can I change colours of text in the Text widget?  I want
some of the text in one colour, some in another.

Answer: You can't.  Text stores an ordinary string, and points where
`highlights' of various types begin and end.  These highlights are all the
control you have over components of the text.  See the previous question.


-----------------------------------------------------------------------------
Subject: 82)  How can I change the font of text in the Text widget?  I want
some of the text in one font, some in another.

[Last modified: Sept 94]

Answer: You can't in Text (see the previous question).  If you wanted readonly
text, you could do it by using a label instead.  Label uses XmStrings, which
can contain multiple character sets in the one string.

If you are using Motif 2.0, however, XmStrings are now permitted in XmText
widgets, which solves this particular problem.

-----------------------------------------------------------------------------
Subject: 83)  Is there an emacs binding for the text widget?

Answer: This set is due to Kee Hinckley (nazgul@utopia.com):


*XmText.translations: #override\n\
        Ctrl <Key>b:            backward-character()\n\
        Alt <Key>b:             backward-word()\n\
        Meta <Key>b:            backward-word()\n\
        Shift Alt <Key>b:       backward-word(extend)\n\
        Shift Meta <Key>b:      backward-word(extend)\n\
        Alt <Key>[:             backward-paragraph()\n\
        Meta <Key>[:            backward-paragraph()\n\
        Shift Alt <Key>[:       backward-paragraph(extend)\n\
        Shift Meta <Key>[:      backward-paragraph(extend)\n\
        Alt <Key><:             beginning-of-file()\n\
        Meta <Key><:            beginning-of-file()\n\
        Ctrl <Key>a:            beginning-of-line()\n\
        Shift Ctrl <Key>a:      beginning-of-line(extend)\n\
        Ctrl <Key>osfInsert:    copy-clipboard()\n\
        Shift <Key>osfDelete:   cut-clipboard()\n\
        Shift <Key>osfInsert:   paste-clipboard()\n\
        Alt <Key>>:             end-of-file()\n\
        Meta <Key>>:            end-of-file()\n\
        Ctrl <Key>e:            end-of-line()\n\
        Shift Ctrl <Key>e:      end-of-line(extend)\n\
        Ctrl <Key>f:            forward-character()\n\
        Alt <Key>]:             forward-paragraph()\n\
        Meta <Key>]:            forward-paragraph()\n\
        Shift Alt <Key>]:       forward-paragraph(extend)\n\
        Shift Meta <Key>]:      forward-paragraph(extend)\n\
        Ctrl Alt <Key>f:        forward-word()\n\
        Ctrl Meta <Key>f:       forward-word()\n\
        Ctrl <Key>d:            kill-next-character()\n\
        Alt <Key>BackSpace:     kill-previous-word()\n\
        Meta <Key>BackSpace:    kill-previous-word()\n\
        Ctrl <Key>w:            key-select() kill-selection()\n\
        Ctrl <Key>y:            unkill()\n\
        Ctrl <Key>k:            kill-to-end-of-line()\n\
        Alt <Key>Delete:        kill-to-start-of-line()\n\
        Meta <Key>Delete:       kill-to-start-of-line()\n\
        Ctrl <Key>o:            newline-and-backup()\n\
        Ctrl <Key>j:            newline-and-indent()\n\
        Ctrl <Key>n:            next-line()\n\
        Ctrl <Key>osfLeft:      page-left()\n\
        Ctrl <Key>osfRight:     page-right()\n\
        Ctrl <Key>p:            previous-line()\n\
        Ctrl <Key>g:            process-cancel()\n\
        Ctrl <Key>l:            redraw-display()\n\
        Ctrl <Key>osfDown:      next-page()\n\
        Ctrl <Key>osfUp:        previous-page()\n\
        Ctrl <Key>space:        set-anchor()\n


! If you'd like the Delete key to work like backspace instead of deleting
! backwards, add the following definition to the lines above.
!       <Key>osfDelete: delete-previous-character()\n\

! These aren't included because they could intefere with
| menu accelerators (or vice versa)
!       Alt <Key>p:             backward-paragraph()\n\
!       Meta <Key>p:            backward-paragraph()\n\
!       Shift Alt<Key>p:        backward-paragraph(extend)\n\
!       Shift Meta<Key>p:       backward-paragraph(extend)\n\
!       Alt <Key>w:             copy-clipboard()\n\
!       Meta <Key>w:            copy-clipboard()\n\
!       Ctrl Alt <Key>w:        cut-clipboard()\n\
!       Ctrl Meta <Key>w:       cut-clipboard()\n\
!       Alt <Key>y:             paste-clipboard()\n\
!       Meta <Key>y:            paste-clipboard()\n\
!       Alt <Key>f:             forward-word()\n\
!       Meta <Key>f:            forward-word()\n\
!       Alt <Key>n:             forward-paragraph()\n\
!       Meta <Key>n:            forward-paragraph()\n\
!       Shift Alt <Key>n:       forward-paragraph(extend)\n\
!       Shift Meta <Key>n:      forward-paragraph(extend)\n\
!       Shift Alt <Key>f:       forward-word(extend)\n\
!       Shift Meta <Key>f:      forward-word(extend)\n\
!       Alt <Key>d:             kill-next-word()\n\
!       Meta <Key>d:            kill-next-word()\n\
!       Alt <Key>h:             select-all()\n\
!       Meta <Key>h:            select-all()\n\

Similar sets of translations have been suggested by others.

-----------------------------------------------------------------------------
Subject: 84)  What if I have problems with the backspace/delete keys?

[Last modified: Dec 94]

Answer: mclarnon@maths.ox.ac.uk (Gerald.McLarnon) writes:

  I am running a precompiled program based on motif and am having some
problems
  with the backspace/delete keys. Following the instructions of the faq I put
th e
  following lines in my .Xdefaults file

     *XmText.translations: #override                     <Key>osfDelete:
delete-previous-character()
     *XmTextField.translations: #override                     <Key>osfDelete:
delete-previous-character()
  This meant that in dialogue boxes (such as 'Open File') the delete key
  deleted to the left, but not in the main application window.

  Any hints for someone who isn't much of an X-pert?

David Kaelbling <drk@x.org> replied:

There are a couple possibilities.  In addition to the precedence of loading
resource files (explained in section 2.3 of the X11R5 X Toolkit Intrinsics
manual), resource values in the database are chosen based on a "most explicit
match" algorithm (i.e. those with the most qualifiers on the left hand side
win -- see section 15.2 of the X11R5 Xlib - C Library manual).  So if this
application's app-defaults file or fallback resources says
*Foo*XmText.translations:... that value will be used instead of yours.

Find the app-defaults file for your application and look to see if it
specifies translations for text widgets in the main application; if it does
you'll need to make yours at least as explicit.

If the app-defaults file isn't the problem then the application may be hard-
wiring the translations.  If that's the case you'll probably have to change
your virtual key bindings so that the key you think of as osfDelete is really
osfBackSpace.  You can do that for an individual application by setting its
defaultVirtualBindings resource, or for all Motif applications with a
$HOME/.motifbind file ("man xmbind" and "man VirtualBindings" give more detail
and alternatives).  In either case you'll need to specify a complete list of
virtual key bindings; there is no equivalent to #override.  To find out your
current virtual key bindings run "xprop -root | fgrep BINDINGS" and clean up
the result.

-----------------------------------------------------------------------------
Subject: 85)  How can I use a file as the text source for a Text widget?

Answer: You can't do it directly like you can with the Athena Text widget.
Instead, read the text from the file into a string (all of it!) and then use
XmTextSetString.  Alternatively, read blocks of characters and add them at the
end of the text using XmTextInsertString.  The following is an excerpt from
Dan Heller's "file_browser.c":

    /* file_browser.c -- use a ScrolledText object to view the
     * contents of arbitrary files chosen by the user from a
     * FileSelectionDialog or from a single-line text widget.
     */

    ...
    struct stat statb;

    /* make sure the file is a regular text file and open it */
    if (stat(filename, &statb) == -1 ||
            (statb.st_mode & S_IFMT) != S_IFREG ||
            !(fp = fopen(filename, "r"))) {
        if ((statb.st_mode & S_IFMT) == S_IFREG)
            perror(filename); /* send to stderr why we can't read it */
        else
            fprintf(stderr, "%s: not a regular file0, filename);
        XtFree(filename);
        return;
    }

    /* put the contents of the file in the Text widget by allocating
     * enough space for the entire file, reading the file into the
     * allocated space, and using XmTextFieldSetString() to show the file.
     */
    if (!(text = XtMalloc((unsigned)(statb.st_size+1)))) {
        fprintf(stderr, "Can't alloc enough space for %s", filename);
        XtFree(filename);
        fclose(fp);
        return;
    }

    if (!fread(text, sizeof(char), statb.st_size+1, fp))
        fprintf(stderr, "Warning: may not have read entire file!0);

    text[statb.st_size] = 0; /* be sure to NULL-terminate */

    /* insert file contents in Text widget */
    XmTextSetString(text_w, text);


-----------------------------------------------------------------------------
Subject: 86)  How can put Text in overstrike mode instead of insert?

[Last modified: Mar 95]

Answer: (Be sure to read the update after the first answer. This is also a
second update which cautions against the approach.)

There is no direct way. This was posted by Edmond Pitt (ejp@bohra.cpg.oz) The
correct answer to the question is to put the following in a modifyVerify
callback, where 'mvcb' is the XmTextVerifyCallbackStruct, and 'overstriking'
is defined by you:

    if (overstriking && mvcb->text->length == 1)
    {
        _XmTextDisableRedisplay(w,FALSE);
        XtCallActionProc(w,"delete-next-character",mvcb->event,0);
        _XmTextEnableRedisplay(w);
    }

_XmText{Dis,En}ableRedisplay() are XmText{Dis,En}ableRedisplay() in 1.0, but
X11R3 has no XtCallActionProc() anyway. For this environment you need my 1.0.3
Text widget patches posted last year & available on request.

An update was provided by Ingeborg (inca@osf.org):

In 1.2 and later releases, there is an action function toggle-overstrike()
which will toggle between overstrike and insert mode. Before 1.2.3, there is
no visual difference, and at most one character will get overstruck. In 1.2.3,
a block cursor was added as a visual cue to that the widget is in overstrike
mode, and the code was fixed to overstrike the actual number of characters
input (this makes a difference if you have preediting - for example in
japanese).

There is no default binding in 1.2, but the recommended key is osfInsert
without modifiers.  No resource exists.


Ed Kaltenbach (kaltenba@ataway.aptec.com) wrote:

    I was simulating overstrike mode in the Text Field widget by using
    the delete_next_character solution listed in subject 71.
    When the software is compiled with Motif 1.2.2, the modifyVerify
    callback does not get called for the last character when XmNmaxLength
    is specified.  It seems that the check if maxLength has been reached
    is done before the modifyVerify gets called and it keeps the modifyVerify
    from being called.  Is this a Motif bug? Does anybody have a solution that
    will work with Versions 1.1 and 1.2 of Motif?


Phil Day <phil@cfmu.eurocontrol.be> responded to Ed (and apologized for only
sending pseudocode!):

I've had the same problem, and for my money it's a bug.  My workaround is to
make all text widgets (I don't use textfield because of some other problems in
the past) have XmNmaxLength > XmNcolumns, so that the modifyVerify callback
gets a chance to do its stuff.

If you only want to support overstrike for typing, 1 extra charater is enough,
but if you want to support cut-and-paste for any length string you need
maxLength = 2*columns.  In the modifyVerify you have to check the result is <
columns.

I've tried using the Motif 1.2 support for overstrike, but this just seems to
work on a kind of pending-delete and only works for the single charater
replacement caes (that's my main argument for calling it a bug).

I don't use delete-next-character (I can't remember why just now, but I know I
had some problem with it).  Instead I have something like the following:

modifyVerify()
{
        if (acceptable)
                XmReplaceText(...)

        cd->doit = False;
        // we've just done it, we don't wnat Motif to !

    XtVaSetValues (w,
                   XmNverifyBell, False,
                   NULL);
        // Otherwise we'll get a beep.
}

valueChanged()
{

    XtVaSetValues (w,
                   XmNverifyBell, True,
                   NULL);
        // turned off in modifyVerify

}

Glenn Mandelkern <gmandel@Corp.Megatest.Com> writes about a problem with the
above solution.


    We have been running our software on Sparc 20's, under Motif 1.1
    and Motif 1.2, X11R5, Solaris 2.4.
    Unfortunately, some colleagues and I have found a disturbing side effect
    when following this suggestion.  Calling XtVaSetValues() in the
    modifyVerifyCallback causes the Text widget to flash.

    The O'Reilly guides say not to call XtVaSetValues() during text
    modification callbacks.  Motif Volume 6 has this on page 511 and
    Motif Volume 6A has it on page 496.

    I myself thought it would be fairly trivial to just switch the bell
    on and off.  But since XtVaSetValues() calls XmText's set_values() method,
    my guess is that its set_values() does something that causes this.

    So when you enter characters, the Text widget flashes.  It also slows
    down the performance of the Text widget.  You'll see this on a multi-line
    Text widget, especially with it occupying a full screen with text.

    If you want to see this, take the editor.c program in Volume 6 or 6A,
    then add a modifyVerifyCallback to the text_output widget.  Then inside
    that callback, call XtVaSetValues with the XmNverifyBell like above.

    This is a common "mistake", one which I've done more than once.
    I remember also that when I did not have the XtVaSetValues() in place,
    I got the beeps.

    So now we've reworked the application as follows:
        1.  The Text widget is initially created with XmNverifyBell
            set to False.

        2.  We ring the bell using XBell() when we detect a condition
            for which we want to veto text modifications.

    For our application, this provides the wanted feedback and gets rid
    of the flashes.


-----------------------------------------------------------------------------
Subject: 87)  How can I make the Delete key do a Backspace?  Related question:
How can I swap Delete and Backspace?

[Last modified: Oct 94]

Answer: Put this in your .Xdefaults

    *XmText.translations: #override <Key>osfDelete: delete-previous-character()


Additional information from David Kaelbling <drk@x.org>:

You can also supply an arbitrary file name to xmbind (so you can conditionally
run xmbind from your .xinitrc file based on the hostname, architecture,
xdpyinfo output, or whatever).

Some people prefer to use xmodmap to swap the keysyms for all applications,
but what you're doing will work fine if you specify all of the virtual key
bindings.  The current bindings are stored on the root window -- use "xprop
-root" and look for a _MOTIF_BINDINGS or _MOTIF_DEFAULT_BINDINGS property.
OSF/Motif is also distributed with a "bindings" directory containing all the
fallback virtkey binding files.

There are several ways to do display-specific customization: make

-----------------------------------------------------------------------------
Subject: 88)+ Can I change the tab stops in the XmText widget?

[Last modified: May 95]

Answer: No.

Thanks to Ken Lee, kenton@rahul.net

-----------------------------------------------------------------------------
END OF PART THREE
