subwindow had its text modified since the last update, this would give the package an oppor-
tunity to prompt the user for an update. Or you might install a routine that interposes any
request for destruction on a particular object (such as a frame).*
The quit() routine looks like this:
void
quit()
{
if (xv_destroy_safe(frame) == XV_OK)
exit(0);
}
Rather than calling xv_destroy_safe() on all objects, it is only called for the base
frame. Because the base frame is the owner of all the other objects, xv_destroy() and
xv_destroy_safe() descend into the objects’ children and destroys all of them with the
same call.
Use the function xv_destroy_safe() to destroy objects from within the object’s call-
back procedures. xv_destroy_safe() will delay destroying the object until it is safe to
do so (that is, not while in the object’s callback). For example, when a frame is destroyed
from within the frame’s FRAME_DONE_PROC, you need to use xv_destroy_safe() to
ensure that the frame object is removed. (See FRAME_DONE_PROC in the next chapter for a
description of a frame’s “done” callback.)
xv_destroy() may be called at any time without notice. It may result from actions the
user takes with the window manager, from a separate process or from events sent by other
applications.
3.3.4 Using xv_set( ) and xv_get( )
As discussed in the previous chapter, attributes about objects can be set, reset and retrieved
using the calls xv_set() and xv_get(). The definition of these routines are:
Xv_opaque
xv_set(object,
attrs
)
Xv_object object;
<attribute-value list>
attrs
;
Xv_opaque
xv_get(object,
attr
)
Xv_object object;
Attr_attribute attr;
xv_set() is just like xv_create() with respect to the attribute-value parameters. Use
xv_set() to set or change the value of one or more attributes of an object that has already
*Chapter 20, The Notifier, describes how to install destroy interpose functions.
Creating XView
Applications
Creating XView Applications 51
been created. The following code segment uses a single xv_set() call to change three
attributes of a frame:
#include <xview/xview.h>
main()
{
Frame frame;
frame = xv_create(NULL, FRAME, NULL);
...
xv_set(frame,
FRAME_LABEL, "XView Demo",
FRAME_SHOW_LABEL, TRUE,
FRAME_NO_CONFIRM, TRUE,
NULL);
...
xv_main_loop(frame);
}
xv_get() is different from xv_set() in that the value parameter is not passed to the
function—instead, the value is returned from xv_get():
Xv_Window root_win;
Frame frame;
Rect *rect;
/* create the base frame for the application */
frame = xv_create(NULL, FRAME, NULL);
/* get the root window of the base frame of the application */
root_win = (Xv_Window *) xv_get(frame, XV_ROOT);
/* get the dimensions (rectangle) of the root window */
rect = (Rect *) xv_get(root_win, XV_RECT);
Because xv_get() returns the value of the attribute specified, only one attribute of the
object can be retrieved by an xv_get() call. The return value for the function is going to
be an opaque data type, so it must be typecast into the type expected. However, note that the
value
XV_ERROR might be returned in the event that the object passed is not a valid object or
if an attribute does not apply. In this case, the return value should be checked to see if it is
XV_ERROR. One potential problem is that the value of XV_ERROR might happen to be the
same as the expected return value. Fortunately, an error returned from xv_get() is
unlikely in a properly written application.
In many packages, certain properties may be retrieved but not set. For example, you may use
xv_get() for the property
WIN_FRAME to get the window’s frame but you may not use
xv_set() to set the window’s frame. In this case, xv_set returns XV_ERROR. In the more
likely event that the call was successful in setting attributes using xv_set(), then the value
XV_OK will be returned.
For some XView attributes that take strings as values in xv_create() or xv_set(), the
string is copied, but for other attributes, the passed pointer is used directly. Since XView’s
internal memory allocation methods may change in future releases, you should not write code
52 XView Programming Manual
that depends in any way on it. The following example shows the type of code that should be
avoided, since it depends on XView’s internal memory allocation method:
/*
* Set panel label string on panel button
*/
xv_set(panel_button, PANEL_LABEL_STRING, array_ptr, NULL);
/*
* DO NOT attempt the following
*
* Check if the memory pointer for the panel button label
* is the same as array_ptr */
if (array_ptr == xv_get(panel_button, PANEL_LABEL_STRING)) {
...
}
3.3.5 Precedence of Resource Options
In the X Window System, the user can configure the interface according to options available
in specific applications. The user accomplishes this through a resource database that resides
in the X server. XView provides several ways for the programmer to set default values and
to accommodate the user’s specifications for properties such as frame colors, fonts and win-
dow geometry among others (for more information on resources, see Chapter 17, Resources).
There are several ways that properties can be set, including: using xv_set() on an attri-
bute corresponding to the property, using command-line options, using values from the
.Xdefaults file or using the values specified when calling xv_create(). In addition,
XView or the window manager may determine some default values for certain properties.
Among these different ways of setting options, programatically, the following precedence
from highest to lowest is maintained:
1. A call to xv_set().
2. Any command-line options.
3. Values specified in the .Xdefaults file.
4. Values specified or inherited in a call to xv_create().
5. Toolkit or window manager defaults.
NOTE
The precedence above does not apply for locale commmand line options.
See Chapter 22, Internationalization, for more details on locale command-
line options.
Creating XView
Applications
Creating XView Applications 53
3.4 xv_main_loop( ) and the Notifier
Once all the objects have been created, you are ready to have all the windows displayed and
have event processing begin. At this point, the program calls xv_main_loop(). The job
of xv_main_loop() is to start the Notifier. Once the Notifier has started, the program will
begin to receive and process events such as Expose, MapNotify, ConfigureNotify,
KeyPress, and so on. The X server generates these events and sends them to the client.
While it is up to the client to handle all events that the X server sends to it, the Notifier layer
of XView handles much of this work automatically.
The Notifier’s main job is to process these events and dispatch them to the client if it has reg-
istered a callback routine for that event type with the Notifier. Otherwise, the Notifier might
ignore the event. Of course, XView attempts to provide reasonable default actions for all
events that the application typically does not want to deal with. For example, a simple appli-
cation that contains nothing but a command frame (which has nothing but a panel/control
area) might not care to handle resize events if the user resizes the window. XView must
handle this so it can resize the panel and/or reposition the panel items within it.
Those events that the application would be most interested in are things like KeyPress and
ButtonPress events of various types. For events like these, the application should install
callback routines for the Notifier to call if one of those events has taken place.
In the examples shown, the only callback routine installed is the one in the panel item,
quit(). When selected, the Notifier notifies the application by calling the callback routine
associated with the object in which the event took place. In this case, the Notifier calls the
routine quit() and the application has control of the program again. As one might expect,
the Notifier has relinquished control of the program while the application’s callback routine
is being called. The Notifier does no more event processing at all until the callback routine
has returned. However, the programmer can query events from within the callback routine if
necessary.
If the code within the callback routine creates new objects or destroys existing objects, noth-
ing will happen on the display until the callback routine is finished and returns control to the
Notifier.
Just because the Notifier handles the delivery of events to the application, that does not mean
that the application will be notified of all events that might occur. The application is only
notified of the events that it has registered with the Notifier. Events that the client can regis-
ter with the Notifier include CreateWindow, MapWindow, ConfigureWindow,
QueryFont, GetInputFocus, and so on. These are general X events, not XView-
specific events. However, XView has a corresponding event definition for the purpose of
registering events with the Notifier. Event registration is covered in detail in Chapter 20, The
Notifier. Event types and specifications are discussed in Chapter 5, Canvases and Openwin,
and Chapter 6, Handling Input.
When a frame is displayed on the screen, a MapNotify event is generated by the X server
(since the frame is mapped, or displayed, to the screen). However, there has been no callback
routine specified to handle the map event, so the Notifier passes it back to XView, which
handles it internally. This default action, in fact, does nothing special; it simply allows the
frame to be displayed. Further events are generated: expose events, visibility events (for the
54 XView Programming Manual
frames that are covered up by the new frame), enter and leave events when the user moves
the mouse in and out of the frame, motion events, and so on. If none of these events have an
application-defined callback routine associated with them, the Notifier handles them.
Note that when objects such as frames or canvases are created, only the objects themselves
and the associated attributes of those objects are created. What is not created are the objects’
windows. These are not created until after xv_main_loop() is called. This is due to the
fact that one of the events that is generated is the realize event—this indicates that an object
has been realized to the screen and a window has been (or needs to be) generated. The
objects’ packages internally handle the creation of windows at the appropriate time. Since
that does not occur until after the call to xv_main_loop(), there should be no attempts to
render graphics into objects’ windows before then.
Creating XView
Applications
Creating XView Applications 55

Get Volume 7A: XView Programming Manual now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.