[comp.windows.x.motif] XmLabel question

daf@mbunix.mitre.org (Dennis Franciskovich) (08/29/90)

(I am using Motif 1.0 under R4 on a VAXstation 3100)

I have a question about the proper way to create an XmLabel widget.
The widget has the XmNlabelString resource, which can be used to specify
the label string.  However, if this resource is not set, the label seems
to use the name of the widget as the label string.  For example, I've
been using the following function call:

XmCreateLabel(parent, "label string", NULL, 0);

This works fine with no apparent problem.  My question is, is this a
bad thing to do?  This is related to another discovery I made:
I accidentally left out the last two arguments,

XmCreateLabel(parent, "label string");

and this also worked with no error at either compilation or run time.
Any comments?

--
Dennis

argv@turnpike.Eng.Sun.COM (Dan Heller) (09/01/90)

In article <118526@linus.mitre.org> daf@mbunix.mitre.org (Dennis Franciskovich) writes:
>   For example, I've
> been using the following function call:
> XmCreateLabel(parent, "label string", NULL, 0);
> This works fine with no apparent problem.  My question is, is this a
> bad thing to do?

It depends on how you want to utilize (or make available) the ability
for the user to configure the user interface.  This particular issue
is important because it addresses all widgets of your program.  To answer
your question directly: "no, it's not a 'bad' thing."  And I say that
because my definition of "bad" is a practice that is inefficient, difficult
to maintain, or counter-productive.  There -are- better methods, but that
doesn't imply that this is a "bad" method.  Because you are using the name
of the widget itself as the label, the user's resource file would specify
attributes about the widget using the label's name:

    *label string.labelString: another label

This means: all widgets that have the name "label string" should use a
label string that says: "another label".  This is true because you did
*not* set the resource XmNlabelString to be some value in the call to
XmCreateLabel():

    XmString string = XmStringCreateLtoR("another label", charset);
    XtSetArg(args[0], XmLabelString, string);
    XmCreateLabel(parent, "label string", args, 1);
    XmStringFree(string);

Here, the label string is "hard-coded" and cannot be changed by resources
at all.  Thus, the previous resource specification won't work.  This may or
may not be what you want!  Don't let people tell you this is a "bad thing."
There are certainly very good reasons for *not* doing this -- but there
are equally good reasons *for* doing this.  You have to ultimately decide
whether or not you want the user or system admins to be able to change the
labels on your widgets.

Another thing to consider is the fact that to hard-code the label, you have
to create a compound string (which allocates memory) and then free it.
If you are doing this for hundreds of labels (which isn't uncommon),
then you're going to fragment your heap space pretty quickly and lower
your performance ratio.

Footnote: Probably a good enhancement for Motif 1.1.1 would be a routine
that created and returned a pointer to a compound string that was stored
in static space.  Each call would overwrite the contents of the previous
call -- that way, you can use strings that are temporary all over the 
place without all that overhead of allocating and deallocating memory.
Either that, or provide a string conversion function that puts the new
string in pre-allocated space (so the programmer can provide the same
buffer all the time).

> This is related to another discovery I made:
> I accidentally left out the last two arguments,
> 
> XmCreateLabel(parent, "label string");
> 
> and this also worked with no error at either compilation or run time.

The remaining arguments to the function are literally "garbage" values.
That is, it is completely undefined as to what got pushed onto the stack
at the time that XmCreateLabel() got called.  In short, "you got lucky".
The reason you didn't get a core dump is speculative, but I'm guessing
your program was short and most of what was on the stack was already set
to zeros -- it appeared to XmCreateLabel() that you had passed a NULL and
a 0 as the missing args.  Longer programs will show that this won't work
as conveniently.

--
dan
----------------------------------------------------
O'Reilly && Associates   argv@sun.com / argv@ora.com
Opinions expressed reflect those of the author only.

mayer@hplabsz.HPL.HP.COM (Niels Mayer) (09/02/90)

In article <141712@sun.Eng.Sun.COM> argv@turnpike.Eng.Sun.COM (Dan Heller) writes:
>Another thing to consider is the fact that to hard-code the label, you have
>to create a compound string (which allocates memory) and then free it.
>If you are doing this for hundreds of labels (which isn't uncommon),
>then you're going to fragment your heap space pretty quickly and lower
>your performance ratio.
>
>Footnote: Probably a good enhancement for Motif 1.1.1 would be a routine
>that created and returned a pointer to a compound string that was stored
>in static space. Each call would overwrite the contents of the previous
>call -- that way, you can use strings that are temporary all over the 
>place without all that overhead of allocating and deallocating memory.

This has been my feeling about the Xtoolkit in general, and the problem
becomes ridiculous with compound strings. Such memory usage could be done
in a number of places throughout Motif. There's more than just compound
strings that get gratuitously copied and freed every time you do anything.

I'd like to even go so far as to have the Toolkit not create a copy of
every resource passed in from the user's space; rather, it should take the
user's object, and do whatever the hell it pleases with it, freeing it when
it is done with it (unless it was statically allocated). If you are
planning on doing something with data that you passed in to Motif, then
make a copy of it for yourself!  Afterall, this is programming in C where
you are supposed to understand and worry about memory management yourself.
If you want to be a pinko-commie and program in Lisp or some other wussy
garbage collected language, then do it in Lisp. :-) The way things are now
with Xt/Motif programming, you get all the pain and tedium of programming
in C, and all the efficiency of Lisp. We should be striving for the
opposite.

Note that I have nothing against Lisp -- afterall, my WINTERP rapid
prototyping and extension language is based on a small Lisp interpreter
(XLISP) that is implemented in C. When I'm writing application-UI code, I
am a Lisp pinko-commie about 99% of the time. When I write in C, I expect
to program like a ruthless-capitalist -- laissez-faire -- too bad about the
poor lazy proletariate that can't figure out how to manage their own memory
(nothing like stretching an analogy to the point of stupidity :-)

Another enhancement would be to throw out Motif's XmStrings and allow good
ol' fashioned normal null-terminated char strings to be used by default.
Using Compound strings, or 16byte-char-strings should be something that can
be done optionally, by either a runtime global resource switch, or
compile-time option, or perhaps both. Although I guess having strings that
go left-to-right roman and right-to-left arabic within the same widgit will
be useful when the OSF its Oil Company conspirators annex Iraq. :-(

-------------------------------------------------------------------------------
	    Niels Mayer -- hplabs!mayer -- mayer@hplabs.hp.com
	 "Founding member, UIL and XmString Haters International"
	    THESE OPINIONS ARE PERSONAL, I AM NOT SPEAKING FOR:
		   Human-Computer Interaction Department
		       Hewlett-Packard Laboratories
			      Palo Alto, CA.
				     *

marbru@auto-trol.UUCP (Martin Brunecky) (09/05/90)

In article <5875@hplabsz.HPL.HP.COM> mayer@hplabs.hp.com (Niels Mayer) writes:
>In article <141712@sun.Eng.Sun.COM> argv@turnpike.Eng.Sun.COM (Dan Heller) writes:
>>
>>Footnote: Probably a good enhancement for Motif 1.1.1 would be a routine
>>that created and returned a pointer to a compound string that was stored
>>in static space. ...
>
>This has been my feeling about the Xtoolkit in general, and the problem
>becomes ridiculous with compound strings. Such memory usage could be done
>in a number of places throughout Motif. There's more than just compound
>strings that get gratuitously copied and freed every time you do anything.
>
>I'd like to even go so far as to have the Toolkit not create a copy of
>every resource passed in from the user's space; rather, it should take the
>user's object, and do whatever the hell it pleases with it, freeing it when
>it is done with it (unless it was statically allocated). ...

   I remeber seeing something like "useInPlace" resource in some widget.
   Basically, a widget writer should THINK about copying resources,
   and be reasonable about it. Unfortunatelly, many C programmers, mislead
   by the K&R book, consider alloc/free a "noop".
   Often, a resource value can be described as readonly,static to the application
   (if someone changes such value dynamically, he gets what he desrves).
   
   For example, if you are using the X resource database, most values (strings,
   for example), are already cached in memory. Copying them into yet another
   place is plainly ridiculous.

   But this has nothing to do with Xt. Purely widget writer issue.
   When we get back to Xt, I'd like to see support for bit fields instead of
   Boolean. Most widget instances contain between 10 to 30 Booleans ...


-- 
=*= Opinions presented here are solely of my own and not those of Auto-trol =*=
Martin Brunecky                   marbru@auto-trol.COM
(303) 252-2499                    {...}ncar!ico!auto-trol!marbru
Auto-trol Technology Corp. 12500 North Washington St., Denver, CO 80241-2404 

asente@adobe.com (Paul Asente) (09/05/90)

In article <141712@sun.Eng.Sun.COM> argv@turnpike.Eng.Sun.COM (Dan Heller) writes:
>Because you are using the name
>of the widget itself as the label, the user's resource file would specify
>attributes about the widget using the label's name:
>
>    *label string.labelString: another label
>
>This means: all widgets that have the name "label string" should use a
>label string that says: "another label".

The rest of Dan's message is quite correct and contains some very useful
advice.  This bit, however, isn't quite right.  Space is not a legal character
in a resource specification, so the above line is not a valid resource
specification.

You're fine using the label's name as its text value as long as it contains
only letters and numbers; if it contains spaces or any punctutation characters
you should give it a different name and store the string in the application
defaults file (as above).

	-paul asente

New address!	asente@adobe.com	...decwrl!adobe!asente

argv@turnpike.Eng.Sun.COM (Dan Heller) (09/06/90)

In article <6265@adobe.UUCP> asente@adobe.com (Paul Asente) writes:
> >    *label string.labelString: another label
> >
> >This means: all widgets that have the name "label string" should use a
> >label string that says: "another label".
>   This bit, however, isn't quite right.  Space is not a legal character
> in a resource specification, so the above line is not a valid resource
> specification.

As someone else pointed out, "it seems to work" and it always has.
I must confess, I didn't think it would work, so I tested it and it
did.  so, I thought that the MIT documentation was wrong.. My error.

Something else occured to me that I figured I should mention.  This
is something that I do frequently.

Consider the problem of the desire to set all buttons a of particular
type to "red".  However, you don't want to do:

    *PushButton.foreground: red

because you don't want to set *all* pushbuttons, just those of a
particular type.  For example, you might want to set the color of
all the *default* buttons (those in an action area, for example)
to red, but all the other pushbuttons in the group should be blue.

Remember that widgets need not have *unique* names.  By creating
widgets with identical names, you can set resources for the entire
lot using one resource:

    *default_button.foreground: red
    *other_button.foreground: blue

The coresponding code might be:

    ok_str = XmStringCreateSimple(parent, "Ok");
    XtVaCreateManagedWidget("default_button", xmPushButtonWidgetClass, parent,
	XmNlabelString, ok_str,
	NULL);
    XmStringFree(ok_str);

    cancel_str = XmStringCreateSimple(parent, "Cancel");
    XtVaCreateManagedWidget("other_button", xmPushButtonWidgetClass, parent,
	XmNlabelString, cancel_str,
	NULL);
    XmStringFree(cancel_str);

    help_str = XmStringCreateSimple(parent, "Help");
    XtVaCreateManagedWidget("other_button", xmPushButtonWidgetClass, parent,
	XmNlabelString, help_str,
	NULL);
    XmStringFree(help_str);

Notice that the cancel and help pushbuttons have the same "name", but
have different labelstrings.  This allows the resources to work as I
described.  Note: you can set the name of a widget to the emptry string
(""), but you can't set resources on it.
--
dan
----------------------------------------------------
O'Reilly && Associates   argv@sun.com / argv@ora.com
Opinions expressed reflect those of the author only.