cell_height += Resrcs.grid + 6 +
Resrcs.label_bitmap * (font−>ascent + font−>descent);
cell_width += Resrcs.grid + 6;
/* if user didn't specify row/column layout figure it out ourselves.
* optimize layout by making it "square".
*/
if (!Resrcs.rows && !Resrcs.cols) {
Resrcs.cols = int_sqrt (total);
Resrcs.rows = (total + Resrcs.cols − 1) / Resrcs.cols;
}
else if (Resrcs.rows)
/* user specified rows −− figure out columns */
Resrcs.cols = (total + Resrcs.rows − 1) / Resrcs.rows;
else
/* user specified cols −− figure out rows */
Resrcs.rows = (total + Resrcs.cols − 1) / Resrcs.cols;
printf ("Creating pixmap area of size %dx%d (%d rows, %d cols)0,
Resrcs.cols * cell_width, Resrcs.rows * cell_height,
Resrcs.rows, Resrcs.cols);
if (!(pixmap = XCreatePixmap (dpy, DefaultRootWindow(dpy),
Resrcs.cols * cell_width, Resrcs.rows * cell_height,
DefaultDepthOfScreen (XtScreen (toplevel)))))
XtError ("Can't Create pixmap.");
if (!(gc = XCreateGC (dpy, pixmap, NULL, 0)))
XtError ("Can't create gc.");
XSetForeground (dpy, gc, Resrcs.bg); /* init GC's foreground to bg */
XFillRectangle (dpy, pixmap, gc, 0, 0,
Resrcs.cols * cell_width, Resrcs.rows * cell_height);
XSetForeground (dpy, gc, Resrcs.fg);
XSetBackground (dpy, gc, Resrcs.bg);
XSetFont (dpy, gc, font−>fid);
if (Resrcs.grid) {
if (Resrcs.grid != 1)
/* Line weight of 1 is faster when left as 0 (the default) */
XSetLineAttributes (dpy, gc, Resrcs.grid, 0, 0, 0);
for (j = 0; j <= Resrcs.rows * cell_height; j += cell_height)
XDrawLine (dpy, pixmap, gc, 0, j, Resrcs.cols * cell_width, j);
for (j = 0; j <= Resrcs.cols * cell_width; j += cell_width)
XDrawLine (dpy, pixmap, gc, j, 0, j, Resrcs.rows * cell_height);
}
/* Draw each of the bitmaps into the big picture */
for (i = 0; i < total; i++) {
int x = cell_width * (i % Resrcs.cols);
int y = cell_height * (i / Resrcs.cols);
if (Resrcs.label_bitmap)
XDrawString (dpy, pixmap, gc,
x + 5 + Resrcs.grid / 2, y + font−>ascent + Resrcs.grid / 2,
list[i].name, list[i].len);
if (DefaultDepthOfScreen (XtScreen (toplevel)) > 1)
XCopyPlane (dpy, list[i].bitmap, pixmap, gc,
0, 0, list[i].width, list[i].height,
x + 5 + Resrcs.grid / 2,
y + font−>ascent + font−>descent + Resrcs.grid / 2, 1L);
else
XCopyArea (dpy, list[i].bitmap, pixmap, gc,
0, 0, list[i].width, list[i].height,
28 Additional Example Programs 28.2 A Bitmap Display Utility
755
x + 5 + Resrcs.grid / 2,
y + font−>ascent + font−>descent + Resrcs.grid / 2);
XFreePixmap (dpy, list[i].bitmap);
XtFree (list[i].name);
}
XtFree (list);
/* Now we get into the Motif stuff */
/* Create automatic Scrolled Window */
scrolled_w = XtVaCreateManagedWidget ("scrolled_w",
xmScrolledWindowWidgetClass, toplevel,
XmNscrollingPolicy, XmAPPLICATION_DEFINED,
XmNvisualPolicy, XmVARIABLE,
XmNshadowThickness, 0,
NULL);
/* Create a drawing area as a child of the ScrolledWindow.
* The DA's size is initialized (arbitrarily) to view_width and
* view_height. The ScrolledWindow will expand to this size.
*/
drawing_a = XtVaCreateManagedWidget ("drawing_a",
xmDrawingAreaWidgetClass, scrolled_w,
XmNwidth, Resrcs.view_width,
XmNheight, Resrcs.view_height,
NULL);
XtAddCallback (drawing_a, XmNexposeCallback, expose_resize, NULL);
XtAddCallback (drawing_a, XmNresizeCallback, expose_resize, NULL);
/* Application−defined ScrolledWindows won't create their own
* ScrollBars. So, we create them ourselves as children of the
* ScrolledWindow widget. The vertical ScrollBar's maximum size is
* the number of rows that exist (in unit values). The horizontal
* ScrollBar's maximum width is represented by the number of columns.
*/
vsb = XtVaCreateManagedWidget ("vsb",
xmScrollBarWidgetClass, scrolled_w,
XmNorientation, XmVERTICAL,
XmNmaximum, Resrcs.rows,
XmNsliderSize, min (Resrcs.view_height / cell_height, Resrcs.rows),
NULL);
if (Resrcs.view_height / cell_height > Resrcs.rows)
sw_voffset = (Resrcs.view_height − Resrcs.rows * cell_height) / 2;
hsb = XtVaCreateManagedWidget ("hsb",
xmScrollBarWidgetClass, scrolled_w,
XmNorientation, XmHORIZONTAL,
XmNmaximum, Resrcs.cols,
XmNsliderSize, min (Resrcs.view_width / cell_width, Resrcs.cols),
NULL);
if (Resrcs.view_width / cell_width > Resrcs.cols)
sw_hoffset = (Resrcs.view_width − Resrcs.cols * cell_width) / 2;
/* Allow the ScrolledWindow to initialize itself accordingly...*/
XmScrolledWindowSetAreas (scrolled_w, hsb, vsb, drawing_a);
XtAddCallback (vsb, XmNvalueChangedCallback, scrolled, XmVERTICAL);
XtAddCallback (hsb, XmNvalueChangedCallback, scrolled, XmHORIZONTAL);
XtAddCallback (vsb, XmNdragCallback, scrolled, XmVERTICAL);
XtAddCallback (hsb, XmNdragCallback, scrolled, XmHORIZONTAL);
XtRealizeWidget (toplevel);
28 Additional Example Programs 28.2 A Bitmap Display Utility
756
XtAppMainLoop (app);
}
/* scrolled() −− react to scrolling actions; cbs−>value is ScrollBar's
* new position.
*/
void
scrolled(scrollbar, client_data, call_data)
Widget scrollbar;
XtPointer client_data;
XtPointer call_data;
{
int orientation = (int) client_data;
XmScrollBarCallbackStruct *cbs =
(XmScrollBarCallbackStruct *) call_data;
if (orientation == XmVERTICAL)
pix_voffset = cbs−>value * cell_height;
else
pix_hoffset = cbs−>value * cell_width;
redraw (XtWindow (drawing_a));
}
/* expose_resize() −− handles both expose and resize (configure) events.
* For XmCR_EXPOSE, just call redraw() and return. For resizing,
* we must calculate the new size of the viewable area and possibly
* reposition the pixmap's display and position offset. Since we
* are also responsible for the ScrollBars, adjust them accordingly.
*/
void
expose_resize(drawing_a, client_data, call_data)
Widget drawing_a;
XtPointer client_data;
XtPointer call_data;
{
XmDrawingAreaCallbackStruct *cbs =
(XmDrawingAreaCallbackStruct *) call_data;
Dimension view_width, view_height, oldw, oldh;
int do_clear = 0;
if (cbs−>reason == XmCR_EXPOSE) {
redraw (cbs−>window);
return;
}
oldw = Resrcs.view_width;
oldh = Resrcs.view_height;
/* Unfortunately, the cbs−>event field is NULL, we have to have
* get the size of the drawing area manually.
*/
XtVaGetValues (drawing_a,
XmNwidth, &Resrcs.view_width,
XmNheight, &Resrcs.view_height,
NULL);
/* Get the size of the viewable area in "units lengths" where
* each unit is the cell size for each dimension. This prevents
* rounding error for the {vert,horiz}_start values later.
*/
view_width = Resrcs.view_width / cell_width;
view_height = Resrcs.view_height / cell_height;
28 Additional Example Programs 28.2 A Bitmap Display Utility
757
/* When the user resizes the frame bigger, expose events are generated,
* so that's not a problem, since the expose handler will repaint the
* whole viewport. However, when the window resizes smaller, then no
* expose event is generated. In this case, the window does not need
* to be redisplayed if the old viewport was smaller than the pixmap.
* (The existing image is still valid−−no redisplay is necessary.)
* The window WILL need to be redisplayed if:
* 1) new view size is larger than pixmap (pixmap needs to be centered).
* 2) new view size is smaller than pixmap, but the OLD view size was
* larger than pixmap.
*/
if ( (int) view_height >= Resrcs.rows) {
/* The height of the viewport is taller than the pixmap, so set
* pix_voffset = 0, so the top origin of the pixmap is shown,
* and the pixmap is centered vertically in viewport.
*/
pix_voffset = 0;
sw_voffset = (Resrcs.view_height − Resrcs.rows * cell_height) / 2;
/* Case 1 above */
do_clear = 1;
/* scrollbar is maximum size */
view_height = Resrcs.rows;
}
else {
/* Pixmap is larger than viewport, so viewport will be completely
* redrawn on the redisplay. (So, we don't need to clear window.)
* Make sure upper side has origin of a cell (bitmap).
*/
pix_voffset = min (pix_voffset,
(Resrcs.rows−view_height) * cell_height);
sw_voffset = 0; /* no centering is done */
/* Case 2 above */
if (oldh > Resrcs.rows * cell_height)
do_clear = 1;
}
XtVaSetValues (vsb,
XmNsliderSize, max (view_height, 1),
XmNvalue, pix_voffset / cell_height,
XmNpageIncrement, max (view_height − 1, 1),
NULL);
/* identical to vertical case above */
if ( (int) view_width >= Resrcs.cols) {
/* The width of the viewport is wider than the pixmap, so set
* pix_hoffset = 0, so the left origin of the pixmap is shown,
* and the pixmap is centered horizontally in viewport.
*/
pix_hoffset = 0;
sw_hoffset = (Resrcs.view_width − Resrcs.cols * cell_width) / 2;
/* Case 1 above */
do_clear = 1;
/* scrollbar is maximum size */
view_width = Resrcs.cols;
}
else {
/* Pixmap is larger than viewport, so viewport will be completely
* redrawn on the redisplay. (So, we don't need to clear window.)
* Make sure left side has origin of a cell (bitmap).
*/
pix_hoffset = min (pix_hoffset,
28 Additional Example Programs 28.2 A Bitmap Display Utility
758

Get Volume 6A: Motif Programming Manual now with O’Reilly online learning.

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