the current one, change_color() returns, as there is no point in reloading an identical pixmap. For additional
information about loading and using colors, see Volume One, Xlib Programming Manual, and Volume Two, Xlib
Reference Manual.
The help_cb() function is the callback routine for the Help menu item on the Help menu. It simply displays an
InformationDialog that contains a message describing how to use the program. See Chapter 5, Introduction to
Dialogs, and Chapter 21, Advanced Dialog Programming, for a complete description of these dialogs and
suggestions on implementing a functional help system.
5.3 The Command and Message Areas
We have already covered most of what you need to know about the MainWindow of an application in this chapter and
Chapter 3, Overview of the Motif Toolkit. The material in the rest of the chapter is considered somewhat advanced, so
you could skip the remaining sections and be relatively secure in moving on to the next chapter. The remaining
material provides details about the MainWindow widget that need to be discussed in order to make this chapter
complete.
The greatest difficulty with the command and message areas of the MainWindow is that these objects are better
defined in the Motif specification than in the Motif toolkit. The command area is intended to support a tty−style
command−line interface to an application. The command area is not supposed to act like xterm or any sort of terminal
emulator; it is just a single−line text area for entering individually typed commands for an application. The message
area is just an output−only area that is used for error and status messages as needed by an application. While both of
these areas are optional MainWindow elements, the message area is usually more common than the command area.
Nevertheless, let's begin by discussing the command area.
A command area is especially convenient for applications that are being converted from a tty−style interface to a
graphical user interface. Properly converted, such applications can do rather well as GUI−based programs, although
the conversion can be more difficult than you might expect. For example, a PostScript interpreter could be
implemented using a command area in the MainWindow. However, since PostScript is a verbose language, it does not
work well with single−line text entry fields.
the source code shows how the command area can be used to allow the user to input standard UNIX commands. The
output of the commands is displayed in the ScrolledText object, which is the work area of the MainWindow. For
simplicity, we've kept the MenuBar small so as to dedicate most of the program to the use of the command area.
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.
/* cmd_area.c −− use a ScrolledText object to view the
* output of commands input by the user in a Command window.
*/
#include <Xm/Text.h>
#include <Xm/MainW.h>
#include <Xm/Command.h>
#include <stdio.h> /* For popen() */
/* main() −− initialize toolkit, create a main window, menubar,
* a Command Area and a ScrolledText to view the output of commands.
*/
main(argc, argv)
int argc;
char *argv[];
5 The Main Window 5.3 The Command and Message Areas
100
{
Widget top, main_w, menubar, menu, command_w, text_w;
XtAppContext app;
XmString file, quit;
extern void exec_cmd(), exit();
Arg args[5];
int n = 0;
XtSetLanguageProc (NULL, NULL, NULL);
/* initialize toolkit and create toplevel shell */
top = XtVaAppInitialize (&app, "Demos",
NULL, 0, &argc, argv, NULL, NULL);
(void) close (0); /* don't let commands read from stdin */
/* MainWindow for the application −− contains menubar, ScrolledText
* and CommandArea (which prompts for filename).
*/
main_w = XtVaCreateManagedWidget ("main_w",
xmMainWindowWidgetClass, top,
XmNcommandWindowLocation, XmCOMMAND_BELOW_WORKSPACE,
NULL);
/* Create a simple MenuBar that contains one menu */
file = XmStringCreateLocalized ("File");
menubar = XmVaCreateSimpleMenuBar (main_w, "menubar",
XmVaCASCADEBUTTON, file, 'F',
NULL);
XmStringFree (file);
/* "File" menu has only one item (Quit), so make callback exit() */
quit = XmStringCreateLocalized ("Quit");
menu = XmVaCreateSimplePulldownMenu (menubar, "file_menu", 0, exit,
XmVaPUSHBUTTON, quit, 'Q', NULL, NULL,
NULL);
XmStringFree (quit);
/* Menubar is done −− manage it */
XtManageChild (menubar);
/* Create ScrolledText −− this is work area for the MainWindow */
XtSetArg (args[n], XmNrows, 24); n++;
XtSetArg (args[n], XmNcolumns, 80); n++;
XtSetArg (args[n], XmNeditable, False); n++;
XtSetArg (args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
text_w = XmCreateScrolledText (main_w, "text_w", args, n);
XtManageChild (text_w);
/* store text_w as user data in "File" menu for file_cb() callback */
XtVaSetValues (menu, XmNuserData, text_w, NULL);
/* Create the command area −− this must be a Command class widget */
file = XmStringCreateLocalized ("Command:");
command_w = XtVaCreateWidget ("command_w", xmCommandWidgetClass, main_w,
XmNpromptString, file,
NULL);
XmStringFree (file);
XtAddCallback (command_w, XmNcommandEnteredCallback, exec_cmd, text_w);
XtManageChild (command_w);
5 The Main Window 5.3 The Command and Message Areas
101
XmMainWindowSetAreas (main_w, menubar, command_w,
NULL, NULL, XtParent (text_w));
XtRealizeWidget (top);
XtAppMainLoop (app);
}
/* execute the command and redirect output to the ScrolledText window */
void
exec_cmd (cmd_widget, client_data, call_data)
Widget cmd_widget; /* the command widget itself, not its Text widget */
XtPointer client_data; /* passed the text_w as client_data */
XtPointer call_data;
{
char *cmd, buf[BUFSIZ];
XmTextPosition pos;
FILE *pp, *popen();
Widget text_w = (Widget) client_data;
XmCommandCallbackStruct *cbs =
(XmCommandCallbackStruct *) call_data;
XmStringGetLtoR (cbs−>value, XmFONTLIST_DEFAULT_TAG, &cmd);
if (!cmd || !*cmd) { /* nothing typed? */
if (cmd)
XtFree (cmd);
return;
}
/* make sure the file is a regular text file and open it */
if (!(pp = popen (cmd, "r")))
perror (cmd);
XtFree (cmd);
if (!pp)
return;
/* put the output of the command in the Text widget by reading
* until EOF (meaning that the command has terminated).
*/
for (pos = 0; fgets (buf, sizeof buf, pp); pos += strlen (buf))
XmTextReplace (text_w, pos, pos, buf);
pclose (pp);
}
This example uses a Command widget for the command area. The output of the program is shown in the figure. The
Command widget provides a command entry area and a command history area. However, you do not necessarily have
to use a Command widget for the command area. A TextField widget can be used instead to provide a simple
command area.
When we created the MainWindow, we set the XmNcommandWindowLocation resource to
XmCOMMAND_BELOW_WORKSPACE, which caused the command area to be placed below the work window.
Although the default value of the resource is XmCOMMAND_ ABOVE_WORKSPACE, the Style Guide recommends that
the command area be positioned beneath the work window, rather than above it. You need to explicitly set the value
of XmN-commandWindowLocation to ensure that the command area is positioned appropriately.
Note that we use the ScrolledWindow that is created by XmCreateScrolledText() for the work window, rather
than the scrolling area provided by the MainWindow. Since XmCreateScrolledText() returns a Text widget,
we are careful to use the parent of the Text widget for the XmNworkWindow resource of the MainWindow. We set
5 The Main Window 5.3 The Command and Message Areas
102
the areas of the MainWindow using XmMainWindowSetAreas(), which is a convenience function that tells the
MainWindow which of its child widgets should be used for its different predefined areas. The routine takes the
following form:
void
XmMainWindowSetAreas (main_w, menubar, cmd_w, h_scroll,
v_scroll, work_w)
Widget main_w;
Widget menubar;
Widget cmd_w;
Widget h_scroll;
Widget v_scroll;
Widget work_w;
Output of cmd_area.c
The function is really a front end for XmScrolledWindowSetAreas(). Basically, both of these functions
manage the appropriate widgets so that they appear in the correct locations in the MainWindow, while making sure
there is enough space for all of them to be visible. Neither function is entirely necessary, though. When you create a
widget as a child of a MainWindow widget, the MainWindow checks the type of the widget you are adding. If the new
widget is a RowColumn that is being used as a MenuBar (XmNrowColumnType is XmMENU_BAR), the
MainWindow automatically uses it for the menu bar. This same check is performed for a Command widget, which is
automatically used as the command area. The MainWindow also provides resources for its different areas that you can
set using XtVaSetValues(). The resources you can use are:
XmNmenuBar
XmNcommandWindow
5 The Main Window 5.3 The Command and Message Areas
103
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.