Path: news.gsfc.nasa.gov!newsfeed.gsfc.nasa.gov!ames!hookup!news.mathworks.com!uhog.mit.edu!bloom-beacon.mit.edu!senator-bedfellow.mit.edu!faqserv
From: ksall@cen.com (Ken Sall)
Newsgroups: comp.windows.x.motif,comp.answers,news.answers
Subject: Motif FAQ (Part 4 of 9)
Supersedes: <motif-faq/part4_808593962@rtfm.mit.edu>
Followup-To: poster
Date: 24 Aug 1995 14:14:54 GMT
Organization: none
Lines: 1097
Approved: news-answers-request@MIT.EDU
Distribution: inet
Expires: 7 Oct 1995 14:10:38 GMT
Message-ID: <motif-faq/part4_809273438@rtfm.mit.edu>
References: <motif-faq/part1_809273438@rtfm.mit.edu>
Reply-To: ksall@cen.com (Ken Sall)
NNTP-Posting-Host: bloom-picayune.mit.edu
Keywords: FAQ question answer
X-Last-Updated: 1995/08/07
Originator: faqserv@bloom-picayune.MIT.EDU
Xref: news.gsfc.nasa.gov comp.windows.x.motif:29799 comp.answers:13767 news.answers:46240

Archive-name: motif-faq/part4
Last-modified: AUGUST 7, 1995
Posting-Frequency: monthly
Organization: Century Computing, Inc. <URL: http://www.cen.com/>
Version: 4.7



-----------------------------------------------------------------------------

Subject: 73) TOPIC: TEXT WIDGET


-----------------------------------------------------------------------------

Subject: 74) 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: 75) 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: 76) 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: 77)+ How do I scroll text to display the most recently added

information?

[Last modified: Aug 95]
Answer: If you're using the XmScrolledText widget, use XmTextSetTopCharacter() or XmTextScroll(). Thanks to Ken Lee, kenton@rahul.net. -----------------------------------------------------------------------------

Subject: 78) 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: 79) 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: 80) 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: 81) 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: 82) 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: 83) How can I select all of the text in a widget programmatically?

So that some initial text is displayed, but anything typed replaces it.

[Last modified: July 95]
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. Jon A. Christopher (jac8792@tam2000.tamu.edu) writes: I have had difficulty getting this to work as described (even though it agrees with the documentation). I believe that it may be because I usually change the TextField to some value and then try to select it. I haven't looked at the internals of the TextField widget, but it must only select the text if the text hasn't changed since the time specified. Ususally the "LastTimestampProcessed" will be be *before* you modify the text, and the selection is therefore ignored. I'd suggest using the CurrentTime variable. This is an X variable which, if used will make sure that your text is always selected. -----------------------------------------------------------------------------

Subject: 84) How can I change colours of text in the Text widget? I want

some of the text in one colour, some in another.

[Last modified: June 95]
Answer: In Motif 1.x, 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. However, in Motif 2.0, XmStrings may be different colors in the same widget. Thanks to Ken Lee, kenton@rahul.net, for the update. -----------------------------------------------------------------------------

Subject: 85) 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: 86) 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: 87) 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: 88) 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: 89) 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: 90) 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: 91) Can I change the tab stops in the XmText widget?


[Last modified: May 95]
Answer: No. Thanks to Ken Lee, kenton@rahul.net -----------------------------------------------------------------------------

Subject: 92) TOPIC: LIST WIDGET


-----------------------------------------------------------------------------

Subject: 93) Should I create an XmList widget as a child of automatic

XmScrolledWindow or use the XmCreateScrolledList() convenience function?

Answer: With most implementations, the convenience function use internal hooks
to give somewhat better scrolling performance.

Thanks to Ken Lee, kenton@rahul.net

-----------------------------------------------------------------------------

Subject: 94) How do I best put a new set of items into a list?


Answer: Set the new list count and list by XtSetArgs and install them by
XtSetValues.

    XmString list[SIZE];
    int list_size;

    XtSetArg (args[n], XmNitemCount, list_size); n++;
    XtSetArg (args[n], XmNitems, list); n++;
    XtSetValues (w, args, n);


or similarly with XtVaSetValues:


    XtVaSetValues (w,
       XmNitemCount, list_size,
       XmNitems, list,
       NULL);


Each time the list is reset by this the old contents are freed by the widget
and the new supplied list is copied.  Do *not* free the old list of items
yourself as this would result in the space being freed twice.  It is not
necessary to remove the items one at a time, nor to "zero" out the list first.

-----------------------------------------------------------------------------

Subject: 95) Can I have strings with different fonts in a list?


Answer: Yes. The strings are XmStrings. Each one can be created using a
different character set using a different font.


-----------------------------------------------------------------------------

Subject: 96) Can I get a bitmap to show in a list item like I can in a Label?

I want to place a bitmap along with some normal text in my list items.

[Last modified: June 95]
Answer: Alan Peery <peery@isc.tamu.edu> writes: Motif 2.0 introduced the "container" widget, which offers 2-D icon and text layout similar to that found in many file management programs. It could probably be used as a 1-D list widget also. A previous source wrote: In Motif 1.x, you cannot do this. The list contains XmStrings, and these only allow text in various character sets. The workaround is to define your font containing the icons you want. Then you can create a fontlist containing your icon font and the font you want the text in, and then make your items multi-segment XmStrings where the first segment contains the code of the icon you want with a charset that matches the icon font in your fontlist and the second segment with a charset matching the text font. -----------------------------------------------------------------------------

Subject: 97) Can I have items with different colours in a list?


[Last modified: June 95]
Answer: Not in Motif 1.x. The list contains XmStrings, and these only allow text in various character sets. However, in Motif 2.0 you _can_ have multiple colors in the same list since colored XmStrings are supported. Thanks to Ken Lee, kenton@rahul.net, for the update. -----------------------------------------------------------------------------

Subject: 98) Can I grey out an item in a list? I want to make insensitive

items in a list so that they cannot be selected.

Answer:

W. Scott Meeks of OSF wrote:

Unfortunately, you can't do it directly since the list items aren't individual
widgets.  We've had other requests for this technology, but it didn't make the
cut for 1.2; it should be in some future release.

However, you can probably fake it in your application with some difficulty.
First, a list item is an XmString, so you can specify a different charset for
the item than for other items in the list and then specify a font in the
list's fontlist that matches the charset and gives you the visual you want.
The next problem is making the item unselectable.  One idea would be to have
the application keep track of the insensitive items and the items currently
selected.  Then you would set up a selection callback that when called would
check the item selected against the list of insensitive items and if the
selected item matched would deselect that item and reselect the previously
selected items.  Otherwise it would just update the application's list of
selected items.  The major drawback with this approach is that you'll get
flashing whenever the list selects an item and your application immediately
de-selects.  Unfortunately I can't think of a way around this without mucking
with the list internals.

Another alternative suggested is to use instead a column of say read only text
widgets which you can make insensitive.

-----------------------------------------------------------------------------

Subject: 99) Can I have multi-line items in a list?

[Last modified: August 92]
Answer: Motif 1.0 and 1.1 both have problems with multi-line items in a list. They should work okay in Motif 1.2. -----------------------------------------------------------------------------

Subject: 100) How can I tell the position of selected items in a list?


[Last modified: Oct 92]
Answer: W. Scott Meeks wrote: 1) All XmList selection callbacks get an XmListCallbackStruct which includes the item selected and its position. In addition, the multiple and extended selection callbacks also get a list of the selected items. This approach requires that your application saves this information if you need it outside of the immediate callback. 2) At any time you can XtGetValues the XmNselectedItems and XmNselectedItemCount resources. The problem with this approach is that identical items may or may not show up in multiple times in this list and the position in the selectedItems list may not relate directly to the position in the items list. 3) You can call XmListGetSelectedPos on the list widget. This will return a list of the positions of all selected items. -----------------------------------------------------------------------------

Subject: 101) TOPIC: FILE SELECTION BOX WIDGET


-----------------------------------------------------------------------------

Subject: 102) What is libPW.a and do I need it? My manual says I need to

link in libPW.a to use the File Selection Box.  I can't find it on my system.

[Last modified: Sept 94]
Answer: The libPW.a is the Programmers Workbench library which is an ATT product not included in Berkeley based systems, hence it is not found in SunOS or Ultrix, but is found on HP-UX (a Berkeley/ATT hybrid which chose ATT in this case). It contains the regex(3) routines (regcmp, regex). Some systems which don't have these in the libc.a need to link with -lPW. Some systems which have the regex(3) routines in there also have the libPW.a. If you have regex(3) in libc, and it works, don't link with libPW. If you don't have regex(3) in libc, and you don't have a libPW, then check some sites on the net for public domain replacements (several exist), or call your vendor. In most versions of Motif (see the doco), you can compile FileSB.c with -DNO_REGEX if you don't have it. Casper H.S. Dik (asper@fwi.uva.nl), Faculty of Mathematics & Computer Science, University of Amsterdam, sent this update for Solaris 2.x users: The regex and regcmp function are part of libgen in SVR4. Motif applications should be linked with -lgen. (However, some SVR4 implementations, especially those of vendors that once shipped SVR3 still contain libPW.) On Solaris 2.x system, you'll need libgen which is located in /usr/ccs/lib. -----------------------------------------------------------------------------

Subject: 103) What are these compile errors: Undefined symbol _regcmp and

_regex?

[Last modified: Sept 94]
Answer: You need to link in the libPW or libgen library - see previous question. -----------------------------------------------------------------------------

Subject: 104) What's wrong with the Motif 1.0 File Selection Box? I can't

set the directory, change the directory or get the file mask to work.

Answer: The 1.0 File Selection Box is broken, and these don't work.  They
weren't fixed until Motif 1.04.  Use these later versions of 1.0 or switch to
Motif 1.1 where it changed a lot.

Joe Hildebrand has a work-around for some of this: Before popping up an
XmFileSelectionDialog, change to the directory you want.  When a file is
selected, check if it is a directory, so that we can change to it.  i.e.

static void show_file_box_CB(w, client_data, call_data)
   Widget               w;
   Widget               client_data;
   XmAnyCallbackStruct  *call_data;
{
   chdir("/users/hildjj/files");
   XtManageChild(client_data);
}

static void val_save(w, client_data, call_data)
   Widget       w;
   Widget       client_data;
   XmSelectionBoxCallbackStruct *call_data;
{
   struct stat buf;  /* struct stat is defined in stat.h */
   char *filename;

   /* get the file name from the FileSelectionBox */
   filename = SmX(call_data->value);

   /* get the status of the file named filename, and put it into buf */
   if (!stat(filename, &buf))
   {
      /* if it's a directory */
      /* if it's a directory */
      if(S_ISDIR(buf.st_mode))
      {
         /* change to that directory, and update the FileSelectionBox */
        chdir(filename);
        XmFileSelectionDoSearch(w, NULL);
      }
      else
         /* if it's a regular file */
         if(S_ISREG(buf.st_mode))
            /* ask if it should be overwritten */
            XtManageChild(valbox);
         else
            /* it's another kind of file.  What type, i can't think of,
               but it might happen */
            pop_up_error_box(client_data, "Error saving file");
   }
   else  /* we couldn't get the file status */
   {
      /* if it's because the file doesn't exist, we're golden */
      if (errno == ENOENT)
         save_file();
      else   /* there is some other problem getting the status.
                e.g. bad path */
         pop_up_error_box(client_data, "Error saving file");
   }
}

this still doesn't implement the file masking stuff.


-----------------------------------------------------------------------------

Subject: 105) What's wrong with the FileSelectionBox under Solaris?


[Last modified: Apr 95]
Answer: Jim Guyton (guyton@burton.cs.colorado.edu) writes: While not strictly a Motif problem, this one had me confused for [awhile]. If under Solaris the entries in a FileSelectionBox look strange and seem to be missing the first two characters of many filenames, then be sure you're linking -lc before -lucb. If on the other hand, the filenames look strange and seem to have two garbage characters in front of every filename, be sure to link -lucb before -lc. There are two versions of readdir(). The one in -lucb returns a structure that has the filename at an offset of 8 bytes (which matches /usr/ucbinclude/sys/dir.h). But the version in -lc returns the filename at an offset of 10 bytes (which matches /usr/include/dirent.h). So depending on how Motif was built for your Solaris, vs. how you link your application, your filenames could be two bytes off in either direction. -----------------------------------------------------------------------------

Subject: 106) TOPIC: FORM WIDGET



-----------------------------------------------------------------------------

Subject: 107) Why don't labels in a Form resize when the label is changed?

I've got some labels in a form. The labels don't resize whenever the label
string resource is changed. As a result, the operator has to resize the window
to see the new label contents. I am using Motif 1.1.

Answer: This problem may happen to any widget inside a Form widget. The
problem was that the Form will resize itself when it gets geometry requests
from its children. If its preferred size is not allowed, the Form will
disallow all geometry requests from its children. The workaround is that you
should set any ancestor of the Form to be resizable. For the shell which
contains the Form you should set the shell resource XmNallowShellResize to be
True (by default, it is set to FALSE).  There is currently an inconsistency on
how resizing is being done, and it may get fixed in Motif 1.2.

db@sunbim.be (Danny Backx) wrote:

Basically what you have to do is set the XmNresizePolicy on the Form to
XmRESIZE_NONE.  The facts seem to be that XmRESIZE_NONE does NOT mean "do not
allow resizes".  You may also have to set XmNresizable on the form to True.

-----------------------------------------------------------------------------

Subject: 108) How can I center a widget in a form?


Answer: One of Motif's trickier questions.  The problems are that: Form gives
no support for centering, only for edge attachments, and the widget must stay
in the center if the form or the widget is resized.  Just looking at
horizontal centering (vertical is similar) some solutions are:

 a.  Use the table widget instead of Form.

 b.  A hack free solution is from Dan Heller:

     /* 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 is
      * taken from the Motif Programming Manual, O'Reilly Volume 6.
      */

     /* corners.c -- demonstrate widget layout management for a
      * BulletinBoard widget.  There are four widgets each labeled
      * top-left, top-right, bottom-left and bottom-right.  Their
      * positions in the bulletin board correspond to their names.
      * Only when the widget is resized does the geometry management
      * kick in and position the children in their correct locations.
      */
     #include <Xm/BulletinB.h>
     #include <Xm/PushBG.h>

     char *corners[] = {
         "Top-Left", "Top-Right", "Bottom-Left", "Bottom-Right",
     };

     static void resize();

     main(argc, argv)
     int argc;
     char *argv[];
     {
         Widget toplevel, bboard;
         XtAppContext app;
         XtActionsRec rec;
         int i;

         /* Initialize toolkit and create toplevel shell */
         toplevel = XtVaAppInitialize(&app, "Demos", NULL, 0,
             &argc, argv, NULL, NULL);

         /* Create your standard BulletinBoard widget */
         bboard = XtVaCreateManagedWidget("bboard",
             xmBulletinBoardWidgetClass, toplevel, NULL);

         /* Set up a translation table that captures "Resize" events
          * (also called ConfigureNotify or Configure events).  If the
          * event is generated, call the function resize().
          */
         rec.string = "resize";
         rec.proc = resize;
         XtAppAddActions(app, &rec, 1);
         XtOverrideTranslations(bboard,
             XtParseTranslationTable("<Configure>: resize()"));

         /* Create children of the dialog -- a PushButton in each corner. */
         for (i = 0; i < XtNumber(corners); i++)
             XtVaCreateManagedWidget(corners[i],
                 xmPushButtonGadgetClass, bboard, NULL);

         XtRealizeWidget(toplevel);
         XtAppMainLoop(app);
     }

     /* resize(), the routine that is automatically called by Xt upon the
      * delivery of a Configure event.  This happens whenever the widget
      * gets resized.
      */
     static void
     resize(w, event, args, num_args)
     CompositeWidget w;   /* The widget (BulletinBoard) that got resized */
     XConfigureEvent *event;  /* The event struct associated with the event */
     String args[]; /* unused */
     int *num_args; /* unused */
     {
         WidgetList children;
         int width = event->width;
         int height = event->height;
         Dimension w_width, w_height;
         short margin_w, margin_h;

         /* get handle to BulletinBoard's children and marginal spacing */
         XtVaGetValues(w,
             XmNchildren, &children,
             XmNmarginWidth, &margin_w,
             XmNmarginHeight, &margin_h,
             NULL);

         /* place the top left widget */
         XtVaSetValues(children[0],
             XmNx, margin_w,

             XmNy, margin_h,
             NULL);

         /* top right */
         XtVaGetValues(children[1], XmNwidth, &w_width, NULL);

         /* To Center a widget in the middle of the BulletinBoard (or Form),
          * simply call:
          *   XtVaSetValues(widget,
               XmNx,    (width - w_width)/2,
               XmNy,    (height - w_height)/2,
               NULL);
          * and return.
          */
         XtVaSetValues(children[1],
             XmNx, width - margin_w - w_width,
             XmNy, margin_h,
             NULL);
         /* bottom left */
         XtVaGetValues(children[2], XmNheight, &w_height, NULL);
         XtVaSetValues(children[2],

             XmNx, margin_w,
             XmNy, height - margin_h - w_height,
             NULL);
         /* bottom right */
         XtVaGetValues(children[3],
             XmNheight, &w_height,
             XmNwidth, &w_width,
             NULL);
         XtVaSetValues(children[3],
             XmNx, width - margin_w - w_width,
             XmNy, height - margin_h - w_height,
             NULL);
     }

 c.  No uil solution has been suggested, because of the widget size problem

-----------------------------------------------------------------------------
END OF PART FOUR