/* * Bitmap.c -- an XView object class that displays an arbitrary * pixmap. This is similar to the Logo object, but the programmer * may specify the bitmap to use via the BITMAP_FILE attribute. */ #include "bitmap_impl.h" #include <xview/notify.h> #include <xview/cms.h> #include <X11/Xutil.h> /* declare the "methods" used by the bitmap class. */ static int bitmap_init(), bitmap_destroy(); static Xv_opaque bitmap_set(), bitmap_get(); static void bitmap_repaint(); Xv_pkg bitmap_pkg = { "Bitmap2", /* package name */ ATTR_PKG_BITMAP, /* package ID */ sizeof(Bitmap_public), /* size of the public struct */ WINDOW, /* subclassed from the window package */ bitmap_init, bitmap_set, bitmap_get, bitmap_destroy, NULL /* disable the use of xv_find() */ }; static void bitmap_redraw(bitmap_public, event) Bitmap_public *bitmap_public; Event *event; { Bitmap_private *bitmap_private = BITMAP_PRIVATE(bitmap_public); XEvent *xevent = event_xevent(event); if (bitmap_private->bitmap && xevent->xany.type == Expose && xevent->xexpose.count == 0) { Display *dpy = (Display *)xv_get(bitmap_public, XV_DISPLAY); Window window = (Window)xv_get(bitmap_public, XV_XID); int width = (int)xv_get(bitmap_public, XV_WIDTH); int height = (int)xv_get(bitmap_public, XV_HEIGHT); int x = (width - bitmap_private->width)/2; int y = (height - bitmap_private->height)/2; XCopyPlane(dpy, bitmap_private->bitmap, window, bitmap_private->gc, 0, 0, bitmap_private->width, bitmap_private->height, x, y, 1L); } else if (xevent->xany.type == ConfigureNotify) XClearArea(xv_get(bitmap_public, XV_DISPLAY), xv_get(bitmap_public, XV_XID), 0, 0, xevent->xconfigure.width, xevent->xconfigure.height, True); } /* initialize the bitmap object by creating (alloc) an instance * of it. There are two parts to an object class: a public part * and a private part. Each contains a pointer to the other, so * link the two together and initialize the remaining fields of * the bitmap data structure. Do no initialize the bitmap's GC * because it is dependent on its window's cms and that isn't * assigned to the window till the "set" method. Also, wait till * till the "set" method to initialize the bitmap file specified. */ static int bitmap_init(owner, bitmap_public, avlist) Xv_opaque owner; Bitmap_public *bitmap_public; Attr_avlist avlist; /* ignored here */ { Bitmap_private *bitmap_private = xv_alloc(Bitmap_private); if (!bitmap_private) return XV_ERROR; /* link the public to the private and vice-versa */ bitmap_public->private_data = (Xv_opaque)bitmap_private; bitmap_private->public_self = (Xv_opaque)bitmap_public; /* set up event handlers to get resize and repaint events */ xv_set(bitmap_public, WIN_NOTIFY_SAFE_EVENT_PROC, bitmap_redraw, WIN_NOTIFY_IMMEDIATE_EVENT_PROC, bitmap_redraw, NULL); return XV_OK; } /* bitmap_set() -- the function called to set attributes in a bitmap * object. This function is called when a bitmap is created after * the init routine as well as when the programmer calls xv_set. */ static Xv_opaque bitmap_set(bitmap_public, avlist) Bitmap_public *bitmap_public; Attr_avlist avlist; { Bitmap_private *bitmap_private = BITMAP_PRIVATE(bitmap_public); Attr_attribute *attrs; for (attrs = avlist; *attrs; attrs = attr_next(attrs)) switch ((int) attrs[0]) { case BITMAP_FILE : { int val, x, y; Display *dpy = (Display *)xv_get(bitmap_public, XV_DISPLAY); Window window = (Window)xv_get(bitmap_public, XV_XID); Pixmap old = bitmap_private->bitmap; if (XReadBitmapFile(dpy, window, attrs[1], &bitmap_private->width, &bitmap_private->height, &bitmap_private->bitmap, &x, &y) != BitmapSuccess) { xv_error(bitmap_public, ERROR_STRING, "Unable to load bitmap file", ERROR_PKG, BITMAP, NULL); bitmap_private->bitmap = old; } break; } case BITMAP_PIXMAP : xv_error(bitmap_public, ERROR_CANNOT_SET, attrs[0], ERROR_PKG, BITMAP, NULL); break; case XV_END_CREATE : { /* this stuff *must* be here rather than in the "init" * routine because the CMS is not loaded into the * window object until the "set" routines are called. */ Cms cms = xv_get(bitmap_public, WIN_CMS); XGCValues gcvalues; Display *dpy = (Display *)xv_get(bitmap_public, XV_DISPLAY); gcvalues.foreground = (unsigned long)xv_get(cms, CMS_FOREGROUND_PIXEL); gcvalues.background = (unsigned long)xv_get(cms, CMS_BACKGROUND_PIXEL); gcvalues.graphics_exposures = False; bitmap_private->gc = XCreateGC(dpy, xv_get(bitmap_public, XV_XID), GCForeground|GCBackground|GCGraphicsExposures, &gcvalues); } default : xv_check_bad_attr(BITMAP, attrs[0]); break; } return XV_OK; } static Xv_opaque bitmap_get(bitmap_public, status, attr, args) Bitmap_public *bitmap_public; int *status; Attr_attribute attr; Attr_avlist args; { Bitmap_private *bitmap_private = BITMAP_PRIVATE(bitmap_public); switch ((int) attr) { case BITMAP_PIXMAP : return (Xv_opaque)bitmap_private->bitmap; case BITMAP_FILE : /* can't get this attribute */ default : *status = xv_check_bad_attr(BITMAP, attr); return (Xv_opaque)XV_OK; } } /* destroy method: free the pixmap and the GC before freeing object */ static int bitmap_destroy(bitmap_public, status) Bitmap_public *bitmap_public; Destroy_status status; { Bitmap_private *bitmap_private = BITMAP_PRIVATE(bitmap_public); if (status == DESTROY_CLEANUP) { if (bitmap_private->bitmap) XFreePixmap(xv_get(bitmap_public, XV_DISPLAY), bitmap_private->bitmap); XFreeGC(xv_get(bitmap_public, XV_DISPLAY), bitmap_private->gc); free(bitmap_private); } return XV_OK; }