The status variable is set to the return value of xv_check_bad_attr() because this is
the same value needed by the internals to XViewthat is, the function that called this get
routine. Recall that the get routine for each package is called until one of them returns
XV_OK in the *status parameter. This is the indicator that the attribute passed applies to
that particular package and that the sequence of calling the packages’ get functions should
cease. Since BITMAP_FILE does apply to the Bitmap package, *status is set to XV_OK.
Thus, when the function returns XV_OK, the get method stops and returns to the programmer.
As an opposite case, consider what happens when an attribute that does not apply to the Bit-
map package is evaluated. Let’s say the programmer called:
int width = (int)xv_get(bitmap, XV_WIDTH);
In this case, the switch would fall through to the default case and call
xv_check_bad_attr(). This time, however, the attribute does not belong to the Bitmap
package (it belongs to the generic package) and an error message is not printed.
xv_check_bad_attr() returns XV_ERROR indicating that the get method should con-
tinue on to the next package in the class hierarchy. Thus, *status is set correctly.
This interface for xv_check_bad_attr() may seem confusing, but if you follow a
simple rule of thumb, it can be made easy. Always have the default case in a switch state-
ment set the status variable to the return value of xv_check_bad_attr(), and always
return XV_OK from the function itself.
There still exists one problem, but there is no way to overcome it in the current XView API.
That is, if the program that called xv_get() ever passes a bad or invalid attribute, the func-
tion returns
XV_OK and it is impossible to determine if that value is a legitimate return value.
Fortunately, this type of error should be worked out before it ever gets to the end user, so ap-
plication developers should pay close attention to the error messages printed to stderr.
25.8.4 Creating a Bitmap Instance
The rest of the implementation for the Bitmap package may be seen in Appendix F, Example
Programs. The destroy method is the same as the logo’s destroy method and there is no find
method for the Bitmap package. In this section, we show a small example program that dem-
onstrates how an application might create an instance from the bitmap package.
Example 25-2. The bitmap.c program
/* bitmap.c -- demonstrate the use of the Bitmap package. */
#include <xview/xview.h>
#include <xview/cms.h>
#include "bitmap.h"
main(argc, argv)
char *argv[ ];
{
Frame frame;
Cms cms;
Bitmap bitmap;
xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL);
XView Internals
XView Internals 609
Example 25-2. The bitmap.c program (continued)
if (argc <= 1)
puts("Specify bitmap filename"), exit(1);
frame = (Frame)xv_create(NULL, FRAME, NULL);
cms = xv_create(NULL, CMS,
CMS_SIZE, 2,
CMS_NAMED_COLORS, "blue", "red", NULL,
NULL);
bitmap = xv_create(frame, BITMAP,
XV_WIDTH, 100,
XV_HEIGHT, 100,
WIN_CMS, cms,
BITMAP_FILE, argv[1 ],
NULL);
window_fit(frame);
xv_main_loop(frame);
}
25.9 The Find Method
One aspect of the XView intrinsics that we have not yet addressed is the method for retriev-
ing handles to objects of a particular class that already have been created. It is not appropri-
ate to do this for the logo object because it is a window-based object. The need for a pro-
grammer to use xv_find() to retrieve an existing object stems from the ability to reuse the
object in more than one instance.
Window-based objects cannot be rendered in more than one location on the screen, so the
find method is not appropriate for packages subclassed from the
WINDOW package. The most
common example of objects that use a find method are those that have no windows associat-
ed with them. Fonts, for example, can be rendered anywhere as they are just handles to a
type of information. Colormap segments can be shared by different windows, so it is pos-
sible to find existing colormap segments and reuse them.
25.9.0.1 To find or not to find
When choosing whether or not you should provide a find method to a package that you are
writing, you should consider whether or not it makes sense to be able to share the same in-
stance of the object in multiple places. If your XView object is application-specific (i.e., it
cannot be used in a general way by “any” application), then you should probably reconsider
whether you should make an XView object or try to implement it using existing XView ob-
jects or other methods.
Allowing the programmer to use xv_find() for a package helps the application keep down
its use of system resources, such as memory. It also aids in performance, since the objects are
shared among the entire application.
610 XView Programming Manual
25.9.1 Conceptual Implementation
When the programmer calls xv_find(), the find method for the package specified (second
parameter) is called. The purpose of this function is to cycle through all the objects that have
been created of the package’s type and find the one that matches the attributes specified. Re-
call that xv_find() may work just like xv_create() (see Chapter 2, The XView Pro-
grammer’s Model).
In order to cycle through a list of objects of a particular package, that list must be created and
updated every time an object is created or destroyed. That is, each time an object is created,
the new object is added to the list, whereas each time an object is destroyed, it is removed
from the list. The next issue is where to store this list.
It cannot reside within the package’s private data since each instance of the object would
have to be updated every time a new instance is created or another destroyed. Instead, we
must choose a central location where the list can be obtained directly by the find and initial-
ize procedures. We could choose a global, but private, variable representing the head of the
list, but this would cause problems for packages that must have separate lists according to
various constraints.
With fonts, for example, each server has unique font IDs and font objects cannot be shared
among different servers. So, a list of font objects that have been created could be attached to
the server object associated with the font. For colormap segments, since they are dependent
upon colormaps, there has to be a separate list of available colormap segments for each avail-
able screen on a server (a cms associated with a color screen won’t work very well with a
cms assigned to a monochrome screen).
For all the XView objects that currently exist and that support xv_find(), you may find a
different choice of implementation. If you design an XView object that is not unique to each
server, you may very well wish not to attach the data to the server object. On the other hand,
if the object depends on the unique qualities of the screen within the server (for which there
can be many), then you may wish to attach the list head to the screen object associated with a
server. Still, your XView object may not even depend on any X- or XView-related informa-
tion in which case you needn’t attach the list to any XView object at all. It may very well be
a global variable that you access directly.
If you decide to follow the methods that some of the existing XView packages use, you may
wish to attach lists to XView objects directly. Chapter 7, Panels, describes these methods,
including XV_KEY_DATA. We can attach a list of objects from a particular package to another
XView object (such as a Xv_Server object) using the attribute XV_KEY_DATA with the
package identifier (ID) as the key* and the head of the list as the data type for the key.
*We don’t have to use the package ID as the key, but since it tends to be distinct from the other package IDs, it is a
good choice.
XView Internals
XView Internals 611
25.9.1.1 Scope of list availability
Wherever you decide to attach the list of your XView objects, remember that the list is re-
stricted to the application. It is impossible for xv_find() to retrieve an instance of an
XView object that was created on a separate application that happens to be running on the
same machine. Also, note that while there is one server that may support many applications
running concurrently, XView creates an instance of a server object on a per-application ba-
sis, so attaching lists to a server or screen object does not imply that the list is available out-
side your application’s context.
25.9.2 Actual Implementation
When the programmer calls xv_find(), XView starts with the package specified and
works its way to the GENERIC package until it calls that package’s find procedure, if avail-
able. If a package returns an object, then XView terminates the calling sequence and returns
the object found. If no object is actually returned, XView may automatically create the ob-
ject by invoking the initialize method just as if the programmer called xv_create() rather
than xv_find(). It will only do this if the attribute XV_AUTO_CREATE is TRUE (the de-
fault). If the programmer sets this attribute to FALSE, then xv_find() returns NULL and the
programmer doesn’t get an object.
Because of the sequence that XView uses to call the find method for classes, package-specif-
ic attributes are considered first, followed by the more generic ones. If the programmer calls
xv_find() and passes only one attribute-value pair, such as XV_WIDTH,100 then if no ob-
jects of the package type requested is found, the more generic (parent) packages’ find meth-
ods are called until one returns an object that happens to have a width of 100 pixels.
25.10 The Image Package
Server images (a front end for Pixmaps), like fonts, can be rendered anywhere on the screen
(in windows, in other server images, and so on), under certain constraints (e.g., window depth
and so on). So it is possible to find and reuse instances of server images. However, the cur-
rent implementation of the server image package does not support a find method. So, we are
going to demonstrate how to implement the find method by creating an extension to the
server image package that does nothing but support the call to xv_find(). The new pack-
age is called Image and does not have any package-specific attributes.
There are three routines that provide the functionality of the find method: the initialize rou-
tine, the destroy routine, and the find routine itself. The initialize routine is responsible for
creating the list or, if it already exists, adding the newly created object to the list. The des-
troy routine is responsible for removing the instance of the object being destroyed from the
list. Lastly, the find routine is responsible for checking the list for matching attribute-value
pairs and returning the matching object.
612 XView Programming Manual
25.10.0.1 The public image header file
The public header file for the image package is fairly simple:
#include <xview/xview.h>
#include <xview/svrimage.h>
extern Xv_pkg image_pkg;
#define IMAGE &image_pkg
typedef Xv_opaque Image;
#define ATTR_PKG_IMAGE ATTR_PKG_UNUSED_FIRST+1
typedef struct {
Xv_server_image parent_data;
Xv_opaque private_data;
} Image_public;
The parent_data field of the public image structure is Xv_server_image because the
image package is subclassed from Server_image.
25.10.0.2 The private image header file
The private header file is equally simple:
#include <stdio.h> /* for BUFSIZ */
#include "image.h"
typedef struct _image {
Xv_object public_self; /* pointer back to self */
char *filename; /* for get/find */
Xv_Screen screen; /* need to retain for list */
struct _image *next; /* linked list for find */
} Image_private;
#define IMAGE_PUBLIC(item) XV_PUBLIC(item)
#define IMAGE_PRIVATE(item) XV_PRIVATE(Image_private, Image_public, item)
The private data structure contains several fields that enable the image package to allow the
find method to work. The filename field is used to save the filename specified as the value
to the SERVER_IMAGE_BITMAP_FILE attribute. Because the server image implementation
does not save this data, the image package does. The next field is used to create a linked
list of these objects to attach to the screen object set in the screen field. This is the list that
the find method uses to find existing objects from a call to xv_find().
XView Internals
XView Internals 613

Get Volume 7A: XView 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.