DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T x

⟦8d3703084⟧ TextFile

    Length: 13155 (0x3363)
    Types: TextFile
    Names: »xbitmap4.c«

Derivation

└─⟦8648bda34⟧ Bits:30007244 EUUGD5_II: X11R5
    └─⟦2ca9b63e1⟧ »./contrib-1/contrib-1.00« 
        └─⟦a8392fb20⟧ 
            └─⟦this⟧ »contrib/examples/OReilly/Vol4/ch04/xbitmap4.c« 

TextFile

/*
 * 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);
}