28 Additional Example Programs
This appendix provides some additional example programs that illustrate techniques not discussed in the body of the
book.
This appendix contains a number of programs that provide more realistic examples of how the Motif toolkit is used.
Most of the examples are also intended to encourage further investigation into other X−related topics, such as the use
of app−defaults files, fallback resources, and command−line option parsing. Our discussion of the examples is fairly
limited; see the comments in the code for explanations of various implementation details.
28.1 A Postcard Interface for Mail
The first example provides a GUI wrapper for a mail program. The user−interface model is that of a postcard. The
program does not provide any facilities for reading mail messages; it simply allows the user to compose and send one
message at a time. Before compiling the program shown in the source code check the definition of MAIL_CMD. If you
don't have zmail on your system, set the value to the name of the mail agent you normally use.
XtSetLanguageProc() is only available in X11R5; there is no corresponding function in X11R4.
XmStringCreateLocalized() is only available in Motif 1.2; XmStringCreateSimple() is the
corresponding function in Motif 1.1. XmFONTLIST_DEFAULT_TAG replaces XmSTRING_DEFAULT_CHARSET in
Motif 1.2.
/* Written by Dan Heller. Copyright 1991, 1993, Z−Code Software Corp.
* 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.
*/
/* zcard.c −− a postcard interface for zmail.
*/
#include <stdio.h>
#include <Xm/List.h>
#include <Xm/LabelG.h>
#include <Xm/PushB.h>
#include <Xm/MessageB.h>
#include <Xm/RowColumn.h>
#include <Xm/Form.h>
#include <Xm/Text.h>
#include "zcard.icon"
/* redefine to "mush" or "Mail" if you don't have Z−Mail */
#define MAIL_CMD "mush"
extern char *strcpy();
Widget list_w, text_w, to_w, subj_w;
Widget CreateLabeledTextForm();
void add_user(), send_it(), add_to_to(), move();
/* These only take effect if the app−defaults file is not found */
String fallback_resources[] = {
"*XmText.fontList: −*−courier−medium−r−*−−12−*",
"*XmText.translations: #override Ctrl<Key>D: activate() 0 Ctrl<Key>U: kill−to−start−of−line() 0 Ctrl<Key>W: delete−previous−word() 0 <Key>osfDelete: delete−previous−character()",
"*msg−text.rows: 15",
742
"*msg−text.columns: 35",
"*XmPushButton.fontList: −*−new century schoolbook−bold−r−*−−12−*",
"*XmPushButtonGadget.fontList: −*−new century schoolbook−bold−r−*−−12−*",
"*XmLabelGadget.fontList: −*−new century schoolbook−bold−r−*−−12−*",
"*XmList.fontList: −*−courier−medium−r−*−−12−*",
"*zcard.labelString: Z−Card",
"*title.labelString: Quick Message Sender",
"*actions*leftAttachment: attach_position",
"*actions*rightAttachment: attach_position",
"*to−label.labelString: To:",
"*to−list.visibleItemCount: 6",
"*subject−label.labelString: Subject:",
"*add−btn.labelString: Add",
"*delete−btn.labelString: Delete",
"*send−btn.labelString: Send",
"*quit−btn.labelString: Quit",
"*error.messageString: You must provide at least one message recipient.",
NULL
};
main(argc, argv)
int argc;
char *argv[];
{
Widget toplevel, label, left, heading, icon, titles;
Widget actions, rc, w, send_w;
XtAppContext app;
Arg args[5];
int n;
Pixel fg, bg;
Pixmap pixmap;
extern void exit();
XtSetLanguageProc (NULL, NULL, NULL);
toplevel = XtVaAppInitialize (&app, "Zcard", NULL, 0,
&argc, argv, fallback_resources,
XmNallowShellResize, True,
NULL);
/* The form is the general layout manager for the application.
* It contains two main widgets: a rowcolumn and a scrolled text.
*/
rc = XtVaCreateWidget ("rc",
xmRowColumnWidgetClass, toplevel,
XmNorientation, XmHORIZONTAL,
NULL);
/* left side is a RowColumn −− a child of the bigger RowColumn */
left = XtVaCreateWidget ("left", xmRowColumnWidgetClass, rc, NULL);
/* start the left side with a Form to hold the heading */
heading = XtVaCreateWidget ("heading", xmFormWidgetClass, left, NULL);
/* create an icon to make things pretty */
XtVaGetValues (heading,
XmNforeground, &fg,
XmNbackground, &bg,
NULL);
pixmap = XCreatePixmapFromBitmapData (XtDisplay (heading),
RootWindowOfScreen (XtScreen (heading)),
28 Additional Example Programs 28 Additional Example Programs
743
/* these values are defined in "zcard.icon" */
zcard_logo_bits, zcard_logo_width, zcard_logo_height,
fg, bg, DefaultDepthOfScreen (XtScreen (heading)));
icon = XtVaCreateManagedWidget ("zcard_icon",
xmLabelGadgetClass, heading,
XmNleftAttachment, XmATTACH_FORM,
XmNlabelType, XmPIXMAP,
XmNlabelPixmap, pixmap,
XmNalignment, XmALIGNMENT_END,
NULL);
/* identify the program */
titles = XtVaCreateWidget ("titles",
xmRowColumnWidgetClass, heading,
XmNrightAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_WIDGET,
XmNleftWidget, icon,
XmNtopAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
NULL);
XtVaCreateManagedWidget ("zcard", xmLabelGadgetClass, titles, NULL);
XtVaCreateManagedWidget ("title", xmLabelGadgetClass, titles, NULL);
XtManageChild (titles);
XtManageChild (heading);
/* provide the "To:" prompt (see the resources above) */
to_w = CreateLabeledTextForm (left, "to−label", "to");
/* prompt for the subject (see the resources above) */
subj_w = CreateLabeledTextForm (left, "subject−label", "subject−text");
/* when user hits <Return>, advance caret to next input item */
XtAddCallback (subj_w, XmNactivateCallback, move, NULL);
/* right side is a scrolled text region for letter input. */
n = 0;
XtSetArg (args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
XtSetArg (args[n], XmNscrollVertical, True); n++;
XtSetArg (args[n], XmNscrollHorizontal, True); n++;
text_w = XmCreateScrolledText (rc, "msg−text", args, n);
XtManageChild (text_w);
/* Ctrl−D in text_w causes activate() which calls send_it() */
XtAddCallback (text_w, XmNactivateCallback, send_it, send_w);
/* Create a ScrolledList of all the recipients entered in To: */
n = 0;
XtSetArg (args[n], XmNscrollingPolicy, XmAUTOMATIC); n++;
XtSetArg (args[n], XmNselectionPolicy, XmEXTENDED_SELECT); n++;
XtSetArg (args[n], XmNlistSizePolicy, XmRESIZE_IF_POSSIBLE); n++;
list_w = XmCreateScrolledList (left, "to−list", args, n);
XtAddCallback (list_w, XmNdefaultActionCallback, add_to_to, to_w);
XtManageChild (list_w);
/* Any command line args are recipients */
while (argc−− > 1) {
XmString str = XmStringCreateLocalized (*++argv);
XmListAddItemUnselected (list_w, str, 0);
XmStringFree (str);
}
28 Additional Example Programs 28 Additional Example Programs
744
/* Add, Delete, Send and Quit buttons −− space equally */
actions = XtVaCreateWidget ("actions", xmFormWidgetClass, left, NULL);
send_w = XtVaCreateManagedWidget ("send−btn",
xmPushButtonWidgetClass, actions,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, 0,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, 23,
NULL);
XtAddCallback (send_w, XmNactivateCallback, send_it, NULL);
w = XtVaCreateManagedWidget ("add−btn",
xmPushButtonWidgetClass, actions,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, 26,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, 46,
NULL);
/* clicking on Add user adds user to scrolled list */
XtAddCallback (w, XmNactivateCallback, add_user, (XtPointer) 1);
/* Make it appear as tho hitting return in To: text widget
* is just like clicking on the Add button.
*/
XtAddCallback (to_w, XmNactivateCallback, add_user, w);
w = XtVaCreateManagedWidget ("delete−btn",
xmPushButtonWidgetClass, actions,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, 49,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, 75,
NULL);
/* clicking on delete calls add_user() with a 0 client_data */
XtAddCallback (w, XmNactivateCallback, add_user, (XtPointer) 0);
w = XtVaCreateManagedWidget ("quit−btn",
xmPushButtonWidgetClass, actions,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, 78,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, 100,
NULL);
XtAddCallback (w, XmNactivateCallback, exit, NULL);
XtManageChild (actions);
XtManageChild (left);
XtManageChild (rc);
/* specify tab groups in the order we'd like tabbing to follow */
XtVaSetValues (to_w, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, NULL);
XtVaSetValues (subj_w, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, NULL);
XtVaSetValues (text_w, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, NULL);
XtVaSetValues (actions, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, NULL);
XtVaSetValues (list_w, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, NULL);
XtRealizeWidget (toplevel);
XtAppMainLoop (app);
}
28 Additional Example Programs 28 Additional Example Programs
745
/* add_user() −− add an address to the list of recipients.
* The user clicked on either Add or Delete buttons, or he hit return in
* the To: text field. In the latter case, client data is the add_btn,
* so call that widget's ArmAndActivate() action proc.
*/
void
add_user(w, client_data, call_data)
Widget w;
XtPointer client_data;
XtPointer call_data;
{
int data = (int) client_data;
XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data;
if (w == to_w) {
/* User hit return... make it look as tho he clicked on Add */
XtCallActionProc (data, "ArmAndActivate", cbs−>event, NULL, 0);
return;
}
/* User clicked on Add if data == 1, or delete otherwise */
if (data) {
/* get the value of the To: text widget */
char *text = XmTextGetString (to_w);
XmString str = XmStringCreateLocalized (text);
if (text && *text) /* if not a null string, add to List */
XmListAddItemUnselected (list_w, str, 0);
XmStringFree (str);
XtFree (text);
XmTextSetString (to_w, NULL); /* reset so user can add more */
}
else {
/* user clicked on Delete; delete all selected names */
int *sel, n;
if (!XmListGetSelectedPos (list_w, &sel, &n))
return;
/* Must delete in reverse order or positions get messed up! */
while (n−−)
XmListDeletePos (list_w, sel[n]);
XtFree (sel);
}
}
/* add_to_to() −− callback for double−clicking a list item that
* causes the selected item to be added to To: text. Now
* the user can edit the address.
*/
void
add_to_to(list_w, client_data, call_data)
Widget list_w;
XtPointer client_data;
XtPointer call_data;
{
Widget to_w = (Widget) client_data;
XmListCallbackStruct *cbs = (XmListCallbackStruct *) call_data;
char *text;
XmStringGetLtoR (cbs−>item, XmFONTLIST_DEFAULT_TAG, &text);
XmTextSetString (to_w, text);
XmTextSetInsertionPosition (to_w, strlen(text));
XtFree (text);
28 Additional Example Programs 28 Additional Example Programs
746
Get Volume 6A: Motif Programming Manual now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.