25.10.0.3 The image package declaration
The package is initialized in the following way:
Xv_pkg image_pkg = {
"Image", /* package name */
ATTR_PKG_IMAGE, /* package ID */
sizeof(Image_public), /* size of the public struct */
SERVER_IMAGE, /* subclassed from the server image */
image_init,
image_set,
image_get,
image_destroy,
image_find
};
25.10.1 The Image Initialize Method
The task of the initialize routine for the image class is primarily to initialize the private data
of the image object and to create and/or add to the linked list of the private data types. The
routine is defined as follows:
image_init(owner, image_public, avlist)
Xv_Screen owner;
Image_public *image_public;
Attr_avlist avlist; /* ignored here */
{
Attr_attribute *attrs;
Image_private *image_private = xv_alloc(Image_private);
Image_private *list; /* linked list of image instances */
Xv_Screen screen = owner? owner : xv_default_screen;
if (!image_private || !screen)
return XV_ERROR;
/* link the public to the private and vice-versa */
image_public->private_data = (Xv_opaque)image_private;
image_private->public_self = (Xv_opaque)image_public;
for (attrs = avlist; *attrs; attrs = attr_next(attrs))
if (attrs[0] == SERVER_IMAGE_BITMAP_FILE)
/* you might also want to check that image_private->filename is NULL*/
image_private->filename =
strcpy(malloc(strlen(attrs[1 ])+1), attrs[1 ]);
image_private->next = (Image_private *)NULL;
image_private->screen = screen;
/* get the list of existing images from the screen */
if (list = (Image_private *)xv_get(screen,
XV_KEY_DATA, ATTR_PKG_IMAGE)) {
/* follow list till the end */
while (list->next)
list = list->next;
/* assign new image object to end of list */
614 XView Programming Manual
list->next = image_private;
} else {
/* no image objects on this screen -- create a new list */
xv_set(screen,
XV_KEY_DATA, ATTR_PKG_IMAGE, image_private,
NULL);
}
return XV_OK;
}
The owner for the image object is an Xv_Screen object just as with the Server_image
object. Once the private data is allocated and the public and private structures are linked to
one another, the fields are initialized. The avlist is scanned, checking for SERVER_
IMAGE_BITMAP_FILE
. If the programmer called xv_create(), passing that attribute, then
we need to find out what its value is so we can store it for later retrieval. Remember, we must
do this because the Server_image package does not.
Next, the screen object is queried to see if there have been any other Image objects stored.
The list returned, if any, is the actual linked list of objects. We need this list in order to ap-
pend the new instance to the end of it. If the list does not exist, the instance created here is
set as the head of the list and is stored in the screen object via
XV_KEY_DATA. The package
ID is used as the key identifier and the new instance is used as the head of the list.
25.10.2 The Image Set Method
The only purpose for the Image’s set method is to test to see if the programmer is changing
the image’s pixmap. If so, that would invalidate the value for SERVER_IMAGE_
BITMAP_FILE
, if set. If not set, then nothing is done.
image_set(image_public, avlist)
Image_public *image_public;
Attr_avlist avlist;
{
Attr_attribute *attrs;
Image_private *image_private = IMAGE_PRIVATE(image_public);
/* loop thru attrs looking for anything that would invalidate
* the fact that the filename is set to a valid file. If the
* programmer is assigning a new pixmap or data to this server
* image, the filename that was originally associated with the
* object is no longer valid. Disable for later get/find calls.
*/
if (image_private->filename)
for (attrs = avlist; *attrs; attrs = attr_next(attrs))
if (attrs[0] == SERVER_IMAGE_PIXMAP ||
attrs[0 ] == SERVER_IMAGE_BITS ||
attrs[0 ] == SERVER_IMAGE_X_BITS) {
free(image_private->filename);
image_private->filename = NULL;
}
return (Xv_opaque)XV_OK;
}
XView Internals
XView Internals 615
25.10.3 The Image Get Method
The get routine for the Image package provides the ability to return values for SERVER_
IMAGE_BITMAP_FILE
and XV_SCREEN. The filename is stored in the Image’s private data
structure, so we return this value, if set. The function is as follows:
image_get(image_public, status, attr, args)
Image_public *image_public;
int *status;
Attr_attribute attr;
Attr_avlist args;
{
Image_private *image_private = IMAGE_PRIVATE(image_public);
switch ((int) attr) {
case SERVER_IMAGE_BITMAP_FILE :
return (Xv_opaque)image_private->filename;
case XV_SCREEN :
return (Xv_opaque)image_private->screen;
default :
*status = xv_check_bad_attr(IMAGE, attr);
return (Xv_opaque)XV_OK;
}
}
25.10.4 The Image Destroy Method
When an instance of the Image class is destroyed, the destroy procedure is called with the
status of
DESTROY_CLEANUP. The first parameter to the destroy function is a handle to the
object being destroyed. The task of the destroy function for the Image package is to remove
the item from the list of items attached to the screen object and free it. Once the object has
been freed, all references to the object become invalid. And of course, once the object has
been removed from the screen’s list, then xv_find() will fail to find it.
image_destroy(image_public, status)
Image_public *image_public;
Destroy_status status;
{
Image_private *image_private = IMAGE_PRIVATE(image_public);
Image_private *list; /* linked list of image instances */
Xv_Screen screen = image_private->screen;
if (status == DESTROY_CLEANUP) {
/* get the list of existing images from the screen */
list = (Image_private *)xv_get(screen,
XV_KEY_DATA, ATTR_PKG_IMAGE);
if ((Image)XV_PUBLIC(list) == (Image)image_public)
xv_set(screen,
XV_KEY_DATA, ATTR_PKG_IMAGE, list->next,
NULL);
for ( ; list->next; list = list->next)
if ((Image)XV_PUBLIC(list->next) == (Image)image_public) {
list->next = list->next->next;
616 XView Programming Manual
break;
}
if (list->filename)
free(list->filename);
free(list);
}
return XV_OK;
}
25.10.5 The Image Find Method
The find procedure is the main purpose of the Image package. Its purpose is to find an exist-
ing Image object whose attributes match those specified to the programmer’s call to
xv_find(). If there is more than one matching object, the find routine usually returns the
first one found because it is simpler to implement it that way. However, this is not required
and the object returned may be arbitrary provided that the specified attributes match.
image_find(owner, pkg, avlist)
Xv_Screen owner;
Xv_pkg *pkg;
Attr_avlist avlist; /* ignored here */
{
Image_private *list; /* linked list of image instances */
/* this is what the server image package does */
Xv_Screen screen = owner? owner : xv_default_screen;
Attr_attribute *attrs;
/* consider all the attrs we allow "find" to match on */
int width = -1, height = -1, depth = -1;
Pixmap pixmap = (Pixmap)NULL;
char *filename = NULL;
/* get the list of existing images from the screen */
list = (Image_private *)xv_get(screen,
XV_KEY_DATA, ATTR_PKG_IMAGE);
if (!list)
return NULL;
/* loop thru each attribute requested and save the value
* associated with it. Later, we’ll loop thru the existing
* objects looking for the object that has the same values.
*/
for (attrs = avlist; *attrs; attrs = attr_next(attrs))
switch ((int)attrs[0]) {
case XV_WIDTH :
width = (int)attrs[1];
break;
case XV_HEIGHT :
height = (int)attrs[1 ];
break;
case SERVER_IMAGE_DEPTH :
depth = (int)attrs[1];
break;
XView Internals
XView Internals 617
case SERVER_IMAGE_PIXMAP :
pixmap = (Pixmap)attrs[1 ];
break;
case SERVER_IMAGE_BITMAP_FILE :
filename = (char *)attrs[1 ];
break;
case SERVER_IMAGE_BITS :
case SERVER_IMAGE_X_BITS :
case SERVER_IMAGE_COLORMAP :
case SERVER_IMAGE_SAVE_PIXMAP :
default :
return NULL; /* you can’t "find" for these attrs */
}
/* Now loop thru each object looking for those whose
* value that match those specified above.
*/
for ( ; list; list = list->next) {
/* If it doesn’t match, continue to the next object in
* the list. Repeat for each requested attribute.
*/
if (width > -1 &&
(width != (int)xv_get(XV_PUBLIC(list), XV_WIDTH)))
continue;
if (height > -1 &&
(height != (int)xv_get(XV_PUBLIC(list), XV_HEIGHT)))
continue;
if (depth > -1 && (depth != (int)xv_get(XV_PUBLIC(list),
SERVER_IMAGE_DEPTH)))
continue;
if (pixmap && (pixmap != (Pixmap)xv_get(XV_PUBLIC(list),
SERVER_IMAGE_PIXMAP)))
continue;
if (filename &&
(!list->filename || strcmp(filename, list->filename)))
continue;
/* all matches seemed to be successful, return this object */
return XV_PUBLIC(list);
}
/* nothing found */
return NULL;
}
A find procedure can be implemented in many ways; the one provided above is just one way.
25.10.6 The Image.c Program
Example 25-3 demonstrates one way that the image package can be used. It creates a pixmap
based on the bitmap filename given on the command line (a filename must be given). Then it
uses xv_find() to find the same object first by the same bitmap filename and then again by
using the Pixmap associated with the image.
While the program functionally does very little, it is intended to demonstrate how multiple
server images can be shared in an application via the new Image package.
618 XView Programming Manual
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.