Introduction to Motif Application Development

Part 3: Working with resources

by Marshall Brain , brain@iftech.com
Interface Technologies, Inc.
(800) 224-4965
© Copyright 1994 by Marshall Brain. All rights reserved.
Version 2.01, 5/25/95

These tutorials are excerpted from the book "Motif Programming: The Essentials and More" , by Marshall Brain.


One of the keys to understanding Motif programming is understanding the concept of resources. Every widget in Motif has a set of resources associated with it to control the appearance and behavior of the widget. These resources are just variables. For example, a label widget has resources (or variables) that determine the value of the label, the font used to display the label, the margins around the label, etc. These variables can be read or set to new values.

In the program used in tutorials 1 and 2, only one resource was set: the value of the label widget's labelString resource was set to "hello". In this tutorial we will explore some of the other things that can be done by setting and getting resource values.

Changing the height and width

All widgets have resources that control their height and width. For example, the shell widget that is the window for the program has a height and a width. When it first starts up, the window (or shell widget) is sized so that it holds the label widget perfectly. What if you want the height and width of the shell widget to be different at startup? You can do this within the program by setting the height and width resources of the shell widget. This process is shown in the code below:

 #include <Xm/Xm.h>  #include <Xm/Label.h>   XtAppContext context; XmStringCharSet char_set=XmSTRING_DEFAULT_CHARSET;   Widget toplevel, label;   main(argc,argv)   int argc;    char *argv[]; {   Arg al[10];   int ac;     /* create the toplevel shell */   toplevel = XtAppInitialize(&context,"",NULL,0,     &argc,argv,NULL,NULL,0);     /* create label widget */   ac=0;   XtSetArg(al[ac],XmNlabelString,      XmStringCreateLtoR("Hello World", char_set)); ac++;   label=XmCreateLabel(toplevel,"label",al,ac);   XtManageChild(label);     ac=0;   XtSetArg(al[ac],XmNheight,200); ac++;   XtSetArg(al[ac],XmNwidth,200); ac++;   XtSetValues(toplevel,al,ac);      XtRealizeWidget(toplevel);   XtAppMainLoop(context); } 

In this code, four new lines have been added to "first.c" right above the call to realize the shell widget. An argument list is loaded with the new values for the height and width resources, and this argument list is then used to set the values of those resources in the toplevel widget. When you run this code, the window should open up with a size of 200x200 pixels.

Some bugs to watch for when setting resources:

  1. Be sure you init and increment ac correctly.
  2. Be sure you spell the resource names correctly (case matters).
  3. Be sure you pass al and ac to XtSetValues in the correct order (you'll get a bus error otherwise, even though it will compile correctly).
An alternative would be to replace the four lines that set the height and width with the following line:

   XtVaSetValues(toplevel,XmNheight,200,XmNwidth,200,NULL); 

The "Va" in XtVaSetValues means "Variable Argument list". The function can take as many arguments as you care to pass it, and the NULL at the end simply marks the end of the parameter list. Be sure to include the NULL, or the code will attempt to read an infinite parameter list and crash.

Changing the font used

As another example, the label widget also lets you specify the font used for the label. Setting a font is slightly more involved than setting the height of a widget, but follows the same plan, as shown below:

 #include <Xm/Xm.h>  #include <Xm/Label.h>   XtAppContext context; XmStringCharSet char_set=XmSTRING_DEFAULT_CHARSET;   Widget toplevel, label;   main(argc,argv)   int argc;    char *argv[]; {   Arg al[10];   int ac;     /* create the toplevel shell */   toplevel = XtAppInitialize(&context,"",NULL,0,     &argc,argv,NULL,NULL,0);     /* create label widget */   ac=0;   XtSetArg(al[ac],XmNlabelString,      XmStringCreateLtoR("Hello World", char_set)); ac++;   label=XmCreateLabel(toplevel,"label",al,ac);   XtManageChild(label);     /* declare variables and set the font */   {     XFontStruct *font=NULL;     XmFontList fontlist=NULL;     char *namestring=NULL;        namestring="*6x10*";     font=XLoadQueryFont(XtDisplay(label),namestring);     fontlist=XmFontListCreate(font,XmSTRING_DEFAULT_CHARSET);     XtVaSetValues(label,XmNfontList,fontlist,NULL);   }       XtRealizeWidget(toplevel);   XtAppMainLoop(context); } 

The piece of code in braces near the middle sets up a font list and sets the fontList resource of the label widget. The first line of code takes the name of the font and points namestring at it. Next the font is loaded. Next a Motif fontlist is formed, and this fontlist is used to set the resource. When you run this code, you should see the label displayed with a different font than the font that originally appeared. [You can find info on XLoadQueryFont (and all other X and Xt procedures) by firing up Xman and looking in section 3 (system dependent).]

How do you find out which font names are valid on your system? Generally, type the command:

 	xlsfonts -fn "*" > out, 

and then look at "out". All the font names will be in the file. Some of them are short, like "6x10" used above, but some are monsters, as shown in the fragment of my "out" file copied below:

 -adobe-times-bold-i-normal--24-240-75-75-p-128-iso8859-1 -adobe-times-bold-i-normal--25-180-100-100-p-128-iso8859-1 -adobe-times-bold-i-normal--34-240-100-100-p-170-iso8859-1 

To use one of these fonts, I can say:

 	 namestring="*times*-25-*"; 

in the above code. This will get a 25 point times font. If I want a specific times font I can be more specific, like "*times*bold*-25-*". The "*" is a wildcard like it is in a file name.

Reading Resources

It is also possible to read the value of a resource, and this is often useful when responding to a callback or when trying to see what the user has done to a user-modifiable widget (for example, a scroll bar). The code below simply asks for the height and width of the shell widget (toplevel) once the program has set them up:

 #include <Xm/Xm.h> #include <Xm/Label.h>   XtAppContext context; XmStringCharSet char_set=XmSTRING_DEFAULT_CHARSET;   Widget toplevel, label;   main(argc,argv)   int argc;    char *argv[]; {   Arg al[10];   int ac;   Dimension w,h;     /* create the toplevel shell */   toplevel = XtAppInitialize(&context,"",NULL,0,     &argc,argv,NULL,NULL,0);     /* create label widget */   ac=0;   XtSetArg(al[ac],XmNlabelString,      XmStringCreateLtoR("Hello World", char_set)); ac++;   label=XmCreateLabel(toplevel,"label",al,ac);   XtManageChild(label);     ac=0;   XtSetArg(al[ac],XmNheight,&h); ac++;   XtSetArg(al[ac],XmNwidth,&w); ac++;   XtGetValues(label,al,ac);   printf("%d %d \n",w,h);      XtRealizeWidget(toplevel);   XtAppMainLoop(context); } 

Simply use XtSetArg as you have in the past, but pass it the ADDRESS of the variable you want the value to be placed in. Then call XtGetValues to get the resource values requested. You can also use XtVaGetValues just like you use XtVaSetValue, but pass the address of the resources you want to retrieve.

Resources are the key to understanding the widgets. It is also possible to set resources through resource files, and to create your own resources - more on that in a later tutorial.


Here are the resource lists for the widget we used in this tutorial, along with its ancestors. This info is summarized from the PRM - for more info go to the actual book (see tutorial 1). You can also download the complete resource summary for all of the Motif widgets from the ITI FTP Site . See the file named motif.widget.reference. This file will be extremely useful in the following tutorials.

The "superclass" of a widget is the thing that this widget is made out of. For example, the superclass of a label widget is XmPrimitive. This means that a label widget is built from (or on top of) a primitive widget, and therefore inherits all of a primitve widget's resources. This idea of inheritance is an object oriented programming concept. The primitive widget in turn is built from a core widget. Core widgets have an XmNheight and XmNwidth resource, and therefore ALL widgets have a height and width resource.

The include file name is also important. If you use a widget, you must reference the include file for it in a #include statement. If you forget to do this the program will not compile.

 Label Widget - ------------   Class Pointer:	xmLabelWidgetClass  Class Name:	XmLabel Include File:	<Xm/Label.h>  Superclass:	XmPrimitive Description: 	Displays a compound string or a pixmap.   Resources: Name			Type			Default ---------------------   ---------------------   ------------------------ XmNalignment		unsigned char		XmALIGNMENT_CENTER XmNlabelType		unsigned char		XmString XmNmarginWidth		Dimension		2 XmNmarginHeight		Dimension		2 XmNmarginLeft  		Dimesion		0 XmNmarginRight 		Dimension		0 XmNmarginTop   		Dimension		0 XmNmarginBottom		Dimension		0 XmNfontList    		XmFontList		Dynamic XmNlabelPixmap		Pixmap                  XmUNSPECIFIED_PIXMAP XmNlabelInsensitivePixmap Pixmap		XmUNSPECIFIED_PIXMAP XmNlabelString		XmString		NULL XmNmnemonic		KeySym			NULL XmNmnemonicCharSet      String                  Dynamic XmNaccelerator		String   		NULL XmNacceleratorText	XmString		NULL XmNrecomputeSize	Boolean 		True XmNstringDirection	XmStringDirection	XmSTRING_DIRECTION_L_TO_R       Primitive Widget - ---------------- [This is included because a label widget inherits these resources since it is made from a primitive widget.  You can set and read  the resources shown for a primitve widget.]   Class Pointer:	xmPrimitiveWidgetClass Class Name:	XmPrimitive Include File:   <Xm/Xm.h>  Superclass:	Core Description: 	All Motif widgets are built from primitve widgets (and therefore 	all have the resources listed below).   Resources: Name			Type			Default ---------------------   ---------------------   ------------------------ XmNforeground		Pixel   		dynamic XmNtraversalOn		Boolean 	    	TRUE XmNhighlightOnEnter	Boolean 		FALSE XmNunitType		unsigned char		dynamic XmNHighlightThickness	Dimension		2 XmNhighlightColor	Pixel 			dynamic XmNhighlightPixmap	Pixmap          	dynamic XmNshadowThickness	Dimension		2 XmNtopShadowColor	Pixel   		dynamic XmNtopShadowPixmap	Pixmap                  dynamic XmNbottomShadowColor	Pixel	        	dynamic XmNbottomShadowPixmap	Pixmap                  XmUNSPECIFIED_PIXMAP XmNuserData		Pointer 		NULL XmNnavigationType       unsigned char           XmNone   Callbacks: Callback List		Call Data Type		Reason ---------------------   ---------------------   ------------------------ - XmNhelpCallback		XmAnyCallbackStruct	XmCR_HELP       Core Widget - ------------   Class Pointer:	widgetClass Class Name:	Core Include File:	<X11/Core.h> Superclass:	None Description: 	The superclass of all widgets. (all widgets have these resources 	and callbacks).   Resources: Name			Type			Default ---------------------   ---------------------   ------------------------ XmNscreen		Screen    		dynamic XmNcolorMap		Colormap		copy from parent XmNancestorSensitive	Boolean 		dynamic XmNheight		Dimension		dynamic XmNwidth		Dimension		dynamic XmNx			Position		0 XmNy			Position		0 XmNdepth		Int			dynamic XmNbackground		Pixel   		dynamic XmNbackgroundPixmap	Pixmap  		XmUNSPECIFIED_PIXMAP XmNborderWidth		Dimension		1 XmNborderColor		Pixel   		XtDefaultForeground XmNborderPixmap		Pixmap  	 	XmUNSPECIFIED_PIXMAP XmNSensitive		Boolean 		True XmNmappedWhenManaged	Boolean 		True XmNtranslations		XtTranslations  	NULL XmNaccelerators		XtAccelerators  	NULL   Callbacks: Callback List		Call Data Type		Reason ---------------------   ---------------------   ------------------------ - XmNdestroyCallback	NULL