|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T x
Length: 13155 (0x3363) Types: TextFile Names: »xbitmap4.c«
└─⟦8648bda34⟧ Bits:30007244 EUUGD5_II: X11R5 └─⟦2ca9b63e1⟧ »./contrib-1/contrib-1.00« └─⟦a8392fb20⟧ └─⟦this⟧ »contrib/examples/OReilly/Vol4/ch04/xbitmap4.c«
/* * Copyright 1989 O'Reilly and Associates, Inc. * See ../Copyright for complete rights and liability information. */ /* * xbitmap4.c */ #include <X11/Intrinsic.h> #include <X11/StringDefs.h> #include <X11/Xaw/Paned.h> #include <X11/Xaw/Box.h> #include <X11/Xaw/Command.h> #include <stdio.h> /* * The following could be placed in an "xbitmap.h" file. */ #define XtNdebug "debug" #define XtCDebug "Debug" #define XtNpixmapWidthInCells "pixmapWidthInCells" #define XtCPixmapWidthInCells "PixmapWidthInCells" #define XtNpixmapHeightInCells "pixmapHeightInCells" #define XtCPixmapHeightInCells "PixmapHeightInCells" #define XtNcellSizeInPixels "cellSizeInPixels" #define XtCCellSizeInPixels "CellSizeInPixels" #define DRAWN 1 #define UNDRAWN 0 #define DRAW 1 #define UNDRAW 0 #define MAXLINES 1000 #define MINBITMAPWIDTH 2 #define MAXBITMAPWIDTH 1000 #define MINBITMAPHEIGHT 2 #define MAXBITMAPHEIGHT 1000 #define MINCELLSIZE 4 #define MAXCELLSIZE 100 #define SCROLLBARWIDTH 15 Pixmap big_picture; GC draw_gc, undraw_gc; /* for drawing into the big_picture, 1-bit deep */ GC copy_gc; /* for copying from pixmap into window, screen depth */ Widget bitmap; /* this is the drawing surface */ char *cell; /* this is the array for printing output and keeping track of cells drawn */ int cur_x, cur_y; Dimension pixmap_width_in_pixels, pixmap_height_in_pixels; /* data structure for application resources */ typedef struct { Pixel copy_fg; Pixel copy_bg; int pixmap_width_in_cells; int pixmap_height_in_cells; int cell_size_in_pixels; Boolean debug; } AppData, *AppDataPtr; AppData app_data; /* resource list */ static XtResource resources[] = { { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), XtOffsetOf(AppData, copy_fg), XtRString, XtDefaultForeground }, { XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel), XtOffsetOf(AppData, copy_bg), XtRString, XtDefaultBackground }, { XtNpixmapWidthInCells, XtCPixmapWidthInCells, XtRInt, sizeof(int), XtOffsetOf(AppData, pixmap_width_in_cells), XtRImmediate, (XtPointer) 32, }, { XtNpixmapHeightInCells, XtCPixmapHeightInCells, XtRInt, sizeof(int), XtOffsetOf(AppData, pixmap_height_in_cells), XtRImmediate, (XtPointer) 32, }, { XtNcellSizeInPixels, XtCCellSizeInPixels, XtRInt, sizeof(int), XtOffsetOf(AppData, cell_size_in_pixels), XtRImmediate, (XtPointer) 30, }, { XtNdebug, XtCDebug, XtRBoolean, sizeof(Boolean), XtOffsetOf(AppData, debug), XtRImmediate, (XtPointer) FALSE, }, }; /* Command-line options table */ static XrmOptionDescRec options[] = { {"-pw", "*pixmapWidthInCells", XrmoptionSepArg, NULL}, {"-pixmapwidth", "*pixmapWidthInCells", XrmoptionSepArg, NULL}, {"-ph", "*pixmapHeightInCells", XrmoptionSepArg, NULL}, {"-pixmapheight", "*pixmapHeightInCells", XrmoptionSepArg, NULL}, {"-cellsize", "*cellSizeInPixels", XrmoptionSepArg, NULL}, {"-fg", "*foreground", XrmoptionSepArg, NULL}, {"-foreground", "*foreground", XrmoptionSepArg, NULL}, {"-debug", "*debug", XrmoptionNoArg, "True"}, }; /* callback function to print cell array to stdout */ /* ARGSUSED */ static void Printout(w, event, params, num_params) Widget w; XEvent *event; String *params; Cardinal *num_params; { int x, y; putchar('\n'); for (y = 0; y < app_data.pixmap_height_in_cells; y++) { for (x = 0; x < app_data.pixmap_width_in_cells; x++) putchar(cell[x + y * app_data.pixmap_width_in_cells] ? '1' : '0'); putchar('\n'); } putchar('\n'); /* * It wouldn't be hard to write a function to convert from cell format * to one accepted by XWriteBitmapFile, and the reverse to import such files. * This is done in xbitmap3, where it is even easier. */ } static void RedrawPicture(), DrawCell(), UndrawCell(), ToggleCell(), DrawPixmaps(); static void Syntax(argc, argv) int argc; char * argv[]; { int i; static int errs = False; /* first argument is program name - skip that */ for (i = 1; i < argc; i++) { if (!errs++) /* do first time through */ fprintf(stderr, "xbitmap4: command line option not understood:\n"); fprintf(stderr, "option: %s\n", argv[i]); } fprintf(stderr, "xbitmap understands all standard Xt command line options.\n"); fprintf(stderr, "Additional options are as follows:\n"); fprintf(stderr, "Option Valid Range\n"); fprintf(stderr, "-pw MINBITMAPWIDTH to MAXBITMAPWIDTH\n"); fprintf(stderr, "-pixmapwidth MINBITMAPWIDTH to MAXBITMAPWIDTH\n"); fprintf(stderr, "-ph MINBITMAPHEIGHT to MAXBITMAPHEIGHT\n"); fprintf(stderr, "-pixmapheight MINBITMAPHEIGHT to MAXBITMAPHEIGHT\n"); fprintf(stderr, "-cellsize MINCELLSIZE to MAXCELLSIZE\n"); fprintf(stderr, "-fg color name\n"); fprintf(stderr, "-foreground color name\n"); fprintf(stderr, "-debug no value necessary\n"); } main(argc, argv) int argc; char *argv[]; { XtAppContext app_context; Widget topLevel, vpane, buttonbox, quit, output; extern exit(); /* translation table for bitmap core widget */ String trans = "<Expose>: RedrawPicture() \n\ <Btn1Down>: DrawCell() \n\ <Btn2Down>: UndrawCell() \n\ <Btn3Down>: ToggleCell() \n\ <Btn1Motion>: DrawCell() \n\ <Btn2Motion>: UndrawCell() \n\ <Btn3Motion>: ToggleCell()"; static XtActionsRec window_actions[] = { {"RedrawPicture", RedrawPicture}, {"DrawCell", DrawCell}, {"UndrawCell", UndrawCell}, {"ToggleCell", ToggleCell}, }; topLevel = XtVaAppInitialize( &app_context, /* Application context */ "XBitmap4", options, XtNumber(options), &argc, argv, /* command line args */ NULL, /* for missing app-defaults file */ NULL); /* terminate varargs list */ /* XtInitialize leaves program name in args */ if (argc > 1) Syntax(argc, argv); XtGetApplicationResources(topLevel, &app_data, resources, XtNumber(resources), NULL, 0); /* * We must check the application resource values here. * Otherwise, user could supply out of range values and crash program. * Conversion routines do this automatically, so colors are already checked. */ if ((app_data.pixmap_width_in_cells > MAXBITMAPWIDTH) || (app_data.pixmap_width_in_cells < MINBITMAPWIDTH) || (app_data.pixmap_height_in_cells > MAXBITMAPWIDTH) || (app_data.pixmap_height_in_cells < MINBITMAPWIDTH)) { fprintf(stderr, "xbitmap: error in resource settings:\ dimension must be between %d and %d cells\n", MINBITMAPWIDTH, MAXBITMAPWIDTH); exit(1); } if ((app_data.cell_size_in_pixels < MINCELLSIZE) || (app_data.cell_size_in_pixels > MAXCELLSIZE)) { fprintf(stderr, "xbitmap: error in resource settings:\ cell size must be between %d and %d pixels\n", MINCELLSIZE, MAXCELLSIZE); exit(1); } /* begin application code */ set_up_things(topLevel); cell = XtCalloc(app_data.pixmap_width_in_cells * app_data.pixmap_height_in_cells, sizeof(char)); if (app_data.debug) fprintf(stderr, "xbitmap: pixmap dimensions are %d by %d\n", app_data.pixmap_width_in_cells, app_data.pixmap_height_in_cells); vpane = XtVaCreateManagedWidget("vpane", panedWidgetClass, topLevel, XtNwidth, pixmap_width_in_pixels, NULL); buttonbox = XtCreateManagedWidget("buttonbox", boxWidgetClass, vpane, NULL, 0); output = XtCreateManagedWidget("output", commandWidgetClass, buttonbox, NULL, 0); XtAddCallback(output, XtNcallback, Printout, NULL); quit = XtCreateManagedWidget("quit", commandWidgetClass, buttonbox, NULL, 0); XtAddCallback(quit, XtNcallback, exit, NULL); bitmap = XtVaCreateManagedWidget("bitmap", widgetClass, vpane, XtNtranslations, XtParseTranslationTable(trans), XtNwidth, pixmap_width_in_pixels, XtNheight, pixmap_height_in_pixels, NULL); XtAppAddActions(app_context, window_actions, XtNumber(window_actions)); XtRealizeWidget(topLevel); XtAppMainLoop(app_context); } set_up_things(w) Widget w; { XGCValues values; int x, y; XSegment segment[MAXLINES]; int n_horiz_segments, n_vert_segments; pixmap_width_in_pixels = app_data.pixmap_width_in_cells * app_data.cell_size_in_pixels; pixmap_height_in_pixels = app_data.pixmap_height_in_cells * app_data.cell_size_in_pixels; big_picture = XCreatePixmap(XtDisplay(w), RootWindowOfScreen(XtScreen(w)), pixmap_width_in_pixels, pixmap_height_in_pixels, 1); values.foreground = 1; values.background = 0; values.dashes = 1; values.dash_offset = 0; values.line_style = LineOnOffDash; draw_gc = XCreateGC(XtDisplay(w), big_picture, GCForeground | GCBackground | GCDashOffset | GCDashList | GCLineStyle, &values); values.foreground = 0; values.background = 1; undraw_gc = XCreateGC(XtDisplay(w), big_picture, GCForeground | GCBackground | GCDashOffset | GCDashList | GCLineStyle, &values); values.foreground = app_data.copy_fg; values.background = app_data.copy_bg; copy_gc = XCreateGC(XtDisplay(w), RootWindowOfScreen(XtScreen(w)), GCForeground | GCBackground, &values); XFillRectangle(XtDisplay(w), big_picture, undraw_gc, 0, 0, pixmap_width_in_pixels, pixmap_height_in_pixels); /* draw permanent grid into pixmap */ n_horiz_segments = app_data.pixmap_height_in_cells + 1; n_vert_segments = app_data.pixmap_width_in_cells + 1; for (x = 0; x < n_horiz_segments; x += 1) { segment[x].x1 = 0; segment[x].x2 = pixmap_width_in_pixels; segment[x].y1 = app_data.cell_size_in_pixels * x; segment[x].y2 = app_data.cell_size_in_pixels * x; } /* drawn only once into pixmap */ XDrawSegments(XtDisplay(w), big_picture, draw_gc, segment, n_horiz_segments); for (y = 0; y < n_vert_segments; y += 1) { segment[y].x1 = y * app_data.cell_size_in_pixels; segment[y].x2 = y * app_data.cell_size_in_pixels; segment[y].y1 = 0; segment[y].y2 = pixmap_height_in_pixels; } /* drawn only once into pixmap */ XDrawSegments(XtDisplay(w), big_picture, draw_gc, segment, n_vert_segments); } /* ARGSUSED */ static void RedrawPicture(w, event, params, num_params) Widget w; XExposeEvent *event; String *params; Cardinal *num_params; { register int x, y; unsigned int width, height; if (event) { /* drawing because of expose or button press */ x = event->x; y = event->y; width = event->width; height = event->height; } else { /* drawing because of scrolling */ x = 0; y = 0; width = 10000; /* always the whole window! */ height = 10000; } if (DefaultDepthOfScreen(XtScreen(w)) == 1) XCopyArea(XtDisplay(w), big_picture, XtWindow(w), copy_gc, x + cur_x, y + cur_y, width, height, x, y); else XCopyPlane(XtDisplay(w), big_picture, XtWindow(w), copy_gc, x + cur_x, y + cur_y, width, height, x, y, 1); } /* ARGSUSED */ static void DrawCell(w, event, params, num_params) Widget w; XButtonEvent *event; String *params; Cardinal *num_params; { DrawPixmaps(draw_gc, DRAW, w, event); } /* ARGSUSED */ static void UndrawCell(w, event, params, num_params) Widget w; XButtonEvent *event; String *params; Cardinal *num_params; { DrawPixmaps(undraw_gc, UNDRAW, w, event); } /* ARGSUSED */ static void ToggleCell(w, event, params, num_params) Widget w; XButtonEvent *event; String *params; Cardinal *num_params; { static int oldx = -1, oldy = -1; GC gc; int mode; int newx = (cur_x + event->x) / app_data.cell_size_in_pixels; int newy = (cur_y + event->y) / app_data.cell_size_in_pixels; if ((mode = cell[newx + newy * app_data.pixmap_width_in_cells]) == DRAWN) { gc = undraw_gc; mode = UNDRAW; } else { gc = draw_gc; mode = DRAW; } if (oldx != newx || oldy != newy) { oldx = newx; oldy = newy; DrawPixmaps(gc, mode, w, event); } } /* Private Function */ static void DrawPixmaps(gc, mode, w, event) GC gc; int mode; Widget w; XButtonEvent *event; { int newx = (cur_x + event->x) / app_data.cell_size_in_pixels; int newy = (cur_y + event->y) / app_data.cell_size_in_pixels; XExposeEvent fake_event; /* if already done, return */ if (cell[newx + newy * app_data.pixmap_width_in_cells] == mode) return; XFillRectangle(XtDisplay(w), big_picture, gc, app_data.cell_size_in_pixels*newx + 2, app_data.cell_size_in_pixels*newy + 2, (unsigned int)app_data.cell_size_in_pixels - 3, (unsigned int)app_data.cell_size_in_pixels - 3); cell[newx + newy * app_data.pixmap_width_in_cells] = mode; fake_event.x = app_data.cell_size_in_pixels * newx - cur_x; fake_event.y = app_data.cell_size_in_pixels * newy - cur_y; fake_event.width = app_data.cell_size_in_pixels; fake_event.height = app_data.cell_size_in_pixels; RedrawPicture(bitmap, &fake_event); }