/* * scroll_cells.c -- scroll a bitmap of cells around in a canvas. * The cells are rectangular areas labeled with numbers which may * represent arbitrary data such as icon images. The cell sizes are * defined to be 64 by 64 aligned in rows and columns. This example * is used to demonstrate how to configure scrollbars to accommodate * arbitrary data within a window. */ #include <stdio.h> #include <X11/X.h> #include <X11/Xlib.h> /* Using Xlib graphics */ #include <xview/xview.h> #include <xview/canvas.h> #include <xview/scrollbar.h> #include <xview/font.h> #include <xview/xv_xrect.h> #define CELL_WIDTH 64 #define CELL_HEIGHT 64 #define CELLS_PER_HOR_PAGE 5 /* when paging w/scrollbar */ #define CELLS_PER_VER_PAGE 5 /* when paging w/scrollbar */ #define CELLS_PER_ROW 8 #define CELLS_PER_COL 16 Pixmap cell_map; /* pixmap copied onto canvas window */ Scrollbar horiz_scrollbar; Scrollbar vert_scrollbar; GC gc; /* General usage GC */ main(argc, argv) int argc; char *argv[]; { Frame frame; Canvas canvas; void repaint_proc(); /* Initialize, create frame and canvas... */ xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL); frame = (Frame)xv_create(XV_NULL, FRAME, FRAME_LABEL, argv[0], FRAME_SHOW_FOOTER, TRUE, NULL); canvas = (Canvas)xv_create(frame, CANVAS, /* make subwindow the size of a "page" */ XV_WIDTH, CELL_WIDTH * CELLS_PER_HOR_PAGE, XV_HEIGHT, CELL_HEIGHT * CELLS_PER_VER_PAGE, /* canvas is much larger than the window */ CANVAS_WIDTH, CELL_WIDTH * CELLS_PER_ROW + 1, CANVAS_HEIGHT, CELL_HEIGHT * CELLS_PER_COL + 1, CANVAS_AUTO_EXPAND, FALSE, CANVAS_AUTO_SHRINK, FALSE, /* don't retain window -- we'll need * to repaint it all the time */ CANVAS_RETAINED, FALSE, /* we're using Xlib graphics calls in repaint_proc() */ CANVAS_X_PAINT_WINDOW, TRUE, CANVAS_REPAINT_PROC, repaint_proc, /* we'll be repainting over exposed areas, * so don't bother clearing */ OPENWIN_AUTO_CLEAR, FALSE, NULL); /* * Create scrollbars attached to the canvas. When user clicks * on cable, page by the page size (PAGE_LENGTH). Scrolling * should move cell by cell, not by one pixel (PIXELS_PER_UNIT). */ vert_scrollbar = xv_create(canvas, SCROLLBAR, SCROLLBAR_DIRECTION, SCROLLBAR_VERTICAL, SCROLLBAR_PIXELS_PER_UNIT, CELL_HEIGHT, SCROLLBAR_OBJECT_LENGTH, CELLS_PER_COL, SCROLLBAR_PAGE_LENGTH, CELLS_PER_VER_PAGE, SCROLLBAR_VIEW_LENGTH, CELLS_PER_VER_PAGE, NULL); horiz_scrollbar = xv_create(canvas, SCROLLBAR, SCROLLBAR_DIRECTION, SCROLLBAR_HORIZONTAL, SCROLLBAR_PIXELS_PER_UNIT, CELL_WIDTH, SCROLLBAR_OBJECT_LENGTH, CELLS_PER_ROW, SCROLLBAR_PAGE_LENGTH, CELLS_PER_HOR_PAGE, SCROLLBAR_VIEW_LENGTH, CELLS_PER_HOR_PAGE, NULL); /* * create pixmap and draw cells into it ... this is the abstraction. * The cell_map is copied into the window via XCopyPlane in the * repaint procedure. */ { short x, y, pt = 0; Xv_Font font; XPoint points[256]; /* keep Xlib calls to a minimum */ XGCValues gcvalues; Display *dpy = (Display *)xv_get(canvas, XV_DISPLAY); font = (Xv_Font)xv_find(frame, FONT, #ifndef __linux__ FONT_NAME, "icon", #else // FONT_NAME, "lucidasanstypewriter-24", #endif // NULL); cell_map = XCreatePixmap(dpy, DefaultRootWindow(dpy), CELLS_PER_ROW * CELL_WIDTH + 1, CELLS_PER_COL * CELL_HEIGHT + 1, 1); /* We only need a 1-bit deep pixmap */ /* Create the gc for the cell_map -- since it is 1-bit deep, * use 0 and 1 for fg/bg values. Also, limit number of * events generated by setting graphics exposures to False. */ gcvalues.graphics_exposures = False; gcvalues.foreground = WhitePixel(dpy,DefaultScreen(dpy)); if (font) gcvalues.font = (Font)xv_get(font, XV_XID); gc = XCreateGC(dpy, cell_map, GCFont|GCForeground|GCBackground|GCGraphicsExposures, &gcvalues); XFillRectangle (dpy, cell_map, gc, 0, 0, CELLS_PER_ROW * CELL_WIDTH + 1, CELLS_PER_COL * CELL_HEIGHT + 1); XSetForeground (dpy, gc, 1L); XSetBackground (dpy, gc, 0L); if (!font) { /* dot every other pixel */ for (x = 0; x <= CELL_WIDTH * CELLS_PER_ROW; x += 2) for (y = 0; y <= CELL_HEIGHT * CELLS_PER_COL; y += 2) { if (x % CELL_WIDTH != 0 && y % CELL_HEIGHT != 0) continue; points[pt].x = x, points[pt].y = y; if (++pt == sizeof points / sizeof points[0]) { XDrawPoints(dpy, cell_map, gc, points, pt, CoordModeOrigin); pt = 0; } } if (pt != sizeof points) /* flush remaining points */ XDrawPoints(dpy, cell_map, gc, points, pt, CoordModeOrigin); } /* Icon font not available. Instead, label each cell * with a string describing the cell's coordinates. */ for (x = 0; x < CELLS_PER_ROW; x++) for (y = 0; y < CELLS_PER_COL; y++) { char buf[8]; if (!font) { sprintf(buf, "%d,%d", x+1, y+1); XDrawString(dpy, cell_map, gc, x * CELL_WIDTH + 5, y * CELL_HEIGHT + 25, buf, strlen(buf)); } else { buf[0] = x + y * CELLS_PER_COL; XDrawString(dpy, cell_map, gc, x * CELL_WIDTH, y * CELL_HEIGHT, buf, 1); } } /* we're now done with the cell_map, so free gc and create * a new one based on the window that will use it. Otherwise, * the GC may not work because of different depths. */ if (font) xv_destroy(font); XFreeGC(dpy, gc); gcvalues.background = WhitePixel(dpy, DefaultScreen(dpy)); gcvalues.foreground = BlackPixel(dpy, DefaultScreen(dpy)); gcvalues.plane_mask = 1L; gc = XCreateGC(dpy, DefaultRootWindow(dpy), GCForeground|GCBackground|GCGraphicsExposures, &gcvalues); } /* shrink frame to minimal size and start notifier */ window_fit(frame); xv_main_loop(frame); } /* * The repaint procedure is called whenever repainting is needed in * a paint window. Since the canvas is not retained, this routine * is going to be called anytime the user scrolls the canvas. The * canvas will handle repainting the portion of the canvas that * was in view and has scrolled onto another viewable portion of * the window. The xrects parameter will cover the new areas that * were not in view before and have just scrolled into view. If * the window resizes or if the window is exposed by other windows * disappearing or cycling through the window tree, then the number * of xrects will be more than one and we'll have to copy the new * areas one by one. Clipping isn't necessary since the areas to * be rendered are set by the xrects value. */ void repaint_proc(canvas, paint_window, dpy, win, xrects) Canvas canvas; Xv_Window paint_window; Display *dpy; Window win; Xv_xrectlist *xrects; { int x, y; x = (int)xv_get(horiz_scrollbar, SCROLLBAR_VIEW_START); y = (int)xv_get(vert_scrollbar, SCROLLBAR_VIEW_START); for (xrects->count--; xrects->count >= 0; xrects->count--) { printf("top-left cell = %d, %d -- %d,%d %d,%d\n", x+1, y+1, xrects->rect_array[xrects->count].x, xrects->rect_array[xrects->count].y, xrects->rect_array[xrects->count].width, xrects->rect_array[xrects->count].height); XCopyPlane(dpy, cell_map, win, gc, xrects->rect_array[xrects->count].x, xrects->rect_array[xrects->count].y, xrects->rect_array[xrects->count].width, xrects->rect_array[xrects->count].height, xrects->rect_array[xrects->count].x, xrects->rect_array[xrects->count].y, 1L); } }