From: David I. Bell (dbell@pdact.pd.necisa.oz.au)
Date: Tue Mar 16 1993 - 06:31:09 UTC
#!/bin/sh
# this is LIFE.18 (part 18 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file life/file.c continued
#
if touch 2>&1 | fgrep 'amc' > /dev/null
then TOUCH=touch
else TOUCH=true
fi
if test ! -r shar3_seq_.tmp; then
echo "Please unpack part 1 first!"
exit 1
fi
(read Scheck
if test "$Scheck" != 18; then
echo "Please unpack part $Scheck next!"
exit 1
else
exit 0
fi
) < shar3_seq_.tmp || exit 1
echo "x - Continuing file life/file.c"
sed 's/^X//' << 'SHAR_EOF' >> life/file.c &&
X fprintf(fp, "%ldk", obj->o_currow - minrow);
X if (obj->o_currow < minrow)
X fprintf(fp, "%ldj", minrow - obj->o_currow);
X if (obj->o_curcol > mincol)
X fprintf(fp, "%ldh", obj->o_curcol - mincol);
X if (obj->o_curcol < mincol)
X fprintf(fp, "%ldl", mincol - obj->o_curcol);
X fprintf(fp, "@!\n");
X
X curmin = INFINITY;
X curmax = -INFINITY;
X rp = obj->o_firstrow;
X row = minrow;
X
X for (; rp != termrow; rp = rp->r_next) {
X if (stop)
X return;
X
X /*
X * Skip down to the next row with something in it.
X */
X if (rp->r_firstcell == termcell)
X continue;
X if (rp->r_row > (row + maxrows)) { /* skip to right row */
X fprintf(fp, "%ld\n", rp->r_row - row);
X row = rp->r_row;
X }
X while (rp->r_row > row) {
X fputs(".\n", fp);
X row++;
X }
X
X /*
X * Output the current row, compressing if it is too wide.
X */
X col = mincol;
X cp = rp->r_firstcell;
X if ((cp->c_col + maxcols) < rp->r_lastcell->c_col) {
X while (cp != termcell) {
X /*
X * Write all adjacent blanks.
X */
X if (cp->c_col > col + 2) {
X fprintf(fp, "%ld.", cp->c_col - col);
X col = cp->c_col;
X }
X while (cp->c_col > col) {
X fputc('.', fp);
X col++;
X }
X
X /*
X * Write all adjacent cells.
X */
X while ((cp->c_col + 1) == cp->c_next->c_col) {
X cp = cp->c_next;
X }
X if (cp->c_col >= col + 2) {
X fprintf(fp, "%ldO", cp->c_col - col + 1);
X col = cp->c_col + 1;
X }
X while (col <= cp->c_col) {
X fputc('O', fp);
X col++;
X }
X cp = cp->c_next;
X }
X
X fputc('\n', fp);
X row++;
X curmin = INFINITY;
X curmax = -INFINITY;
X continue;
X }
X
X /*
X * Here if the row doesn't need compressing. See if several
X * rows from this one on can all fit in the same range. If
X * so, set things up so they will align themselves nicely.
X */
X if ((cp->c_col < curmin) || (rp->r_lastcell->c_col > curmax)) {
X curmin = cp->c_col;
X curmax = rp->r_lastcell->c_col;
X trp = rp;
X for (; rp != termrow; rp = rp->r_next) {
X if (rp->r_firstcell == termcell)
X continue;
X testmin = rp->r_firstcell->c_col;
X if (testmin > curmin)
X testmin = curmin;
X testmax = rp->r_lastcell->c_col;
X if (testmax < curmax)
X testmax = curmax;
X if ((testmax - testmin) >= maxcols)
X break;
X curmin = testmin;
X curmax = testmax;
X }
X rp = trp;
X }
X
X /*
X * Type the row, with the initial shift if necessary.
X */
X if (curmin != mincol) {
X fprintf(fp, "%ld.", curmin - mincol);
X col = curmin;
X }
X for (cp = rp->r_firstcell; cp != termcell; cp = cp->c_next) {
X while (cp->c_col > col) {
X fputc('.', fp);
X col++;
X }
X fputc('O', fp);
X col++;
X }
X fputc('\n', fp);
X row++;
X }
X}
X
X
X/*
X * Write an object out to a file in xlife format.
X * This is just a list of coordinates.
X */
Xstatic void
Xwritexlife(fp, obj, minrow, maxrow, mincol, maxcol)
X FILE *fp;
X OBJECT *obj;
X COORD minrow;
X COORD maxrow;
X COORD mincol;
X COORD maxcol;
X{
X register ROW *rp;
X register CELL *cp;
X
X fprintf(fp, "#C \"%s\" (cells %ld width %ld height %ld generation %ld)\n",
X obj->o_name, obj->o_count, maxcol - mincol + 1,
X maxrow - minrow + 1, obj->o_gen);
X
X fputs("#R\n", fp);
X
X for (rp = obj->o_firstrow; rp != termrow; rp = rp->r_next) {
X if (stop)
X return;
X
X for (cp = rp->r_firstcell; cp != termcell; cp = cp->c_next)
X fprintf(fp, "%ld %ld\n", cp->c_col - ccol,
X rp->r_row - crow);
X }
X}
X
X
X/*
X * Write an object out to a file in rle format.
X */
Xstatic void
Xwriterle(fp, obj, minrow, maxrow, mincol, maxcol)
X FILE *fp;
X OBJECT *obj;
X COORD minrow;
X COORD maxrow;
X COORD mincol;
X COORD maxcol;
X{
X register ROW *rp;
X register CELL *cp;
X COORD row;
X COORD col;
X VALUE count;
X int pos;
X
X fprintf(fp, "x = %ld, y = %ld\n", maxcol - mincol + 1,
X maxrow - minrow + 1);
X
X row = minrow;
X col = mincol;
X pos = 0;
X
X for (rp = obj->o_firstrow; rp != termrow; rp = rp->r_next) {
X if (stop)
X return;
X
X if (rp->r_firstcell == termcell)
X continue;
X
X if (row != rp->r_row)
X rleitem(fp, &pos, rp->r_row - row, '$');
X row = rp->r_row;
X
X col = mincol;
X
X for (cp = rp->r_firstcell; cp != termcell; cp = cp->c_next) {
X if (cp->c_col != col) {
X rleitem(fp, &pos, cp->c_col - col, 'b');
X col = cp->c_col;
X }
X count = 1;
X while (cp->c_next->c_col == cp->c_col + 1) {
X cp = cp->c_next;
X count++;
X }
X rleitem(fp, &pos, count, 'o');
X col = cp->c_col + 1;
X }
X }
X
X rleitem(fp, &pos, (VALUE) 1, '!');
X fputc('\n', fp);
X}
X
X
X/*
X * Convert the specified count and action character to an rle string,
X * and write it to the specified file. This adds the character count to
X * the specified line position, and if it would exceed RLEMAX, then inserts
X * a newline first. The character position for the line is updated.
X */
Xstatic void
Xrleitem(fp, pos, count, action)
X FILE *fp;
X int *pos;
X VALUE count;
X{
X int len;
X char buf[16];
X
X if (count == 0)
X return;
X
X if (count == 1) {
X buf[0] = action;
X buf[1] = '\0';
X len = 1;
X } else if (count == 2) {
X buf[0] = action;
X buf[1] = action;
X buf[2] = '\0';
X len = 2;
X } else if ((count < 0) || (count > 99)) {
X sprintf(buf, "%ld%c", count, action);
X len = strlen(buf);
X } else if (count < 10) {
X buf[0] = count + '0';
X buf[1] = action;
X buf[2] = '\0';
X len = 2;
X } else {
X buf[0] = (count / 10) + '0';
X buf[1] = (count % 10) + '0';
X buf[2] = action;
X buf[3] = '\0';
X len = 3;
X }
X
X if (*pos + len > RLEMAX) {
X fputc('\n', fp);
X *pos = 0;
X }
X
X fputs(buf, fp);
X *pos += len;
X}
X
X/* END CODE */
SHAR_EOF
echo "File life/file.c is complete" &&
$TOUCH -am 0316122993 life/file.c &&
chmod 0644 life/file.c ||
echo "restore of life/file.c failed"
set `wc -c life/file.c`;Wc_c=$1
if test "$Wc_c" != "12560"; then
echo original size 12560, current size $Wc_c
fi
# ============= life/README ==============
echo "x - extracting life/README (Text)"
sed 's/^X//' << 'SHAR_EOF' > life/README &&
XThis is my own version of a Life program, along with a library of some
Xinteresting Life objects. It was written in C over a period of many years.
XIt runs using either curses or X11. Other output devices should be easy
Xto add.
X
XThis program is not meant to be incredibly fast (use xlife for that:-).
XBut it IS meant to allow the easy editing and viewing of Life objects.
XIt can handle very large Life objects, and handles multiple objects at
Xthe same time.
X
XThe commands are documented in life.doc. The documentation is terse and
Xjumps around a bit, but it does cover all the essential ideas.
X
XThe Makefile will probably need changing to load the X11 libraries correctly
Xfor your machine. Also, you can define one of the values TERMIOS or SGTTY
Xto match your machine (or neither if you just want a standard set of default
Xline editing characters). These are only used in scan.c.
X
XI hope you enjoy playing with this program. Suggestions for improvements
Xare welcome, as are new interesting Life objects.
X
XDavid I. Bell
Xdbell@pdact.pd.necisa.oz.au
SHAR_EOF
$TOUCH -am 0316143293 life/README &&
chmod 0644 life/README ||
echo "restore of life/README failed"
set `wc -c life/README`;Wc_c=$1
if test "$Wc_c" != "1051"; then
echo original size 1051, current size $Wc_c
fi
# ============= life/x11dev.c ==============
echo "x - extracting life/x11dev.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > life/x11dev.c &&
X/*
X * Copyright (c) 1993 David I. Bell
X * Permission is granted to use, distribute, or modify this source,
X * provided that this copyright notice remains intact.
X */
X
X#ifdef X11
X
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/keysym.h>
X#include <X11/StringDefs.h>
X
X#include "life.h"
X
X
X#define WMRESX 20 /* X pixels to reserve for window manager */
X#define WMRESY 30 /* Y pixels to reserve for window manager */
X#define MINSCALE -30 /* minimum scale */
X#define DEFAULTSCALE -8 /* default scale */
X#define GRIDMAG 4 /* magnification when grid can be shown */
X#define TEXTOFF 2 /* pixels for offsetting text from edges */
X
X
Xstatic int gropen();
Xstatic void grclose();
Xstatic void grupdate();
Xstatic void grrefresh();
Xstatic int grinputready();
Xstatic int grreadchar();
Xstatic void grmovecursor();
Xstatic void grshowview();
Xstatic void grshowstatus();
Xstatic void graddstatus();
Xstatic void grshowhelp();
Xstatic void graddhelp();
Xstatic int grassign();
X
X
XDEV x11dev = {
X gropen, grclose, grupdate, grrefresh, grinputready, grreadchar,
X grmovecursor, grshowview, grshowstatus, graddstatus, grshowhelp,
X graddhelp, grassign, 0, 0, 0, 0, MINSCALE, MAXSCALE, DEFAULTSCALE
X};
X
X
X/*
X * Other variables.
X */
Xstatic Display *display; /* display for X */
Xstatic int screen; /* screen number */
Xstatic Window rootwid; /* top level window id */
Xstatic Window mainwid; /* main window id */
Xstatic Window viewwid; /* window id for view of cells */
Xstatic Window statwid; /* window id for status line */
Xstatic GC statgc; /* GC used for status line */
Xstatic GC viewgc; /* GC used for view of cells */
Xstatic GC viewselectgc; /* GC used for view of selected cells */
Xstatic GC viewgridgc; /* GC used for view of grid */
Xstatic GC cursorgc; /* GC used for cursor */
Xstatic XFontStruct *font; /* font for text */
Xstatic Colormap cmap; /* default color map */
Xstatic long black; /* black pixel value */
Xstatic long white; /* white pixel value */
Xstatic long red; /* red pixel value */
Xstatic long blue; /* blue pixel value */
Xstatic long grey; /* grey pixel value */
Xstatic int charheight; /* height of characters */
Xstatic int charascent; /* ascent of characters */
Xstatic int spacewidth; /* width of a space */
Xstatic int statwidth; /* width of status window */
Xstatic int statheight; /* height of status window */
Xstatic int viewwidth; /* width of view window */
Xstatic int viewheight; /* height of view window */
Xstatic int usedstatus; /* space used in status line so far */
Xstatic int cursorx; /* current cursor x location */
Xstatic int cursory; /* current cursor y location */
Xstatic int helpx; /* x position for new help text */
Xstatic int helpy; /* y position for new help text */
Xstatic int helpcol; /* column number for new help text */
Xstatic BOOL cursorshown; /* TRUE if cursor is being shown */
Xstatic BOOL mapped; /* TRUE if main window is mapped */
Xstatic UCHAR *genstr; /* current char of generated string */
Xstatic UCHAR genstrbuf[32]; /* generated string to return */
Xstatic UCHAR assigns[4]; /* macro assignments for buttons */
X
X
Xstatic int doevent();
Xstatic int dokeydown();
Xstatic void doexposure();
Xstatic int dobuttondown();
Xstatic void viewnormal();
Xstatic void viewscale();
Xstatic void drawcursor();
Xstatic void clearrows();
X
X
X/*
X * Open the graphics device.
X */
Xstatic int
Xgropen(dev)
X DEV *dev;
X{
X XColor cellcolor;
X XColor namecolor;
X XSizeHints sizehints;
X XWMHints wmhints;
X
X display = XOpenDisplay(NULL);
X if (display == NULL) {
X fprintf(stderr, "Cannot open graphics\n");
X return -1;
X }
X screen = DefaultScreen(display);
X
X font = XLoadQueryFont(display, "fixed");
X if (font == NULL) {
X fprintf(stderr, "Cannot load \"fixed\" font\n");
X return -1;
X }
X charascent = font->ascent;
X charheight = charascent + font->descent;
X spacewidth = font->max_bounds.width;
X
X /*
X * Allocate colors, defaulting them if they are not available.
X */
X black = BlackPixel(display, screen);
X white = WhitePixel(display, screen);
X cmap = DefaultColormap(display, screen);
X
X red = white;
X blue = black;
X grey = black;
X
X if (XAllocNamedColor(display, cmap, "red", &cellcolor, &namecolor)) {
X if (cellcolor.pixel != black)
X red = cellcolor.pixel;
X }
X
X if (XAllocNamedColor(display, cmap, "blue", &cellcolor, &namecolor)) {
X if (cellcolor.pixel != white)
X blue = cellcolor.pixel;
X }
X
X if (XAllocNamedColor(display, cmap, "grey", &cellcolor, &namecolor)) {
X if (cellcolor.pixel != white)
X grey = cellcolor.pixel;
X }
X
X viewwidth = DisplayWidth(display, screen) - WMRESX;
X statwidth = viewwidth;
X statheight = charheight + TEXTOFF * 2;
X viewheight = DisplayHeight(display, screen) - statheight - WMRESY;
X
X rootwid = RootWindow(display, screen);
X
X mainwid = XCreateSimpleWindow(display, rootwid,
X 0, 0, viewwidth, viewheight + statheight,
X 0, 0, 0);
X
X statwid = XCreateSimpleWindow(display, mainwid,
X 0, 0, viewwidth, statheight,
X 0, 0, grey);
X
X viewwid = XCreateSimpleWindow(display, mainwid,
X 0, statheight, viewwidth, viewheight,
X 0, 0, blue);
X
X XSelectInput(display, mainwid, KeyPressMask | StructureNotifyMask);
X
X XSelectInput(display, statwid, ExposureMask | KeyPressMask);
X
X XSelectInput(display, viewwid, ExposureMask | KeyPressMask |
X ButtonPressMask);
X
X sizehints.flags = PSize | PMinSize | PMaxSize;
X sizehints.width = viewwidth;
X sizehints.min_width = sizehints.width;
X sizehints.max_width = sizehints.width;
X sizehints.height = viewheight + statheight;
X sizehints.min_height = sizehints.height;
X sizehints.max_height = sizehints.height;
X
X XSetStandardProperties(display, mainwid, "life", "life", None,
X (char **) "", 0, &sizehints);
X
X wmhints.flags = InputHint;
X wmhints.input = True;
X
X XSetWMHints(display, mainwid, &wmhints);
X
X XMapWindow(display, mainwid);
X XMapWindow(display, statwid);
X XMapWindow(display, viewwid);
X
X statgc = XCreateGC(display, statwid, 0, NULL);
X viewgc = XCreateGC(display, viewwid, 0, NULL);
X viewgridgc = XCreateGC(display, viewwid, 0, NULL);
X viewselectgc = XCreateGC(display, viewwid, 0, NULL);
X cursorgc = XCreateGC(display, viewwid, 0, NULL);
X
X XSetForeground(display, viewgc, white);
X XSetForeground(display, statgc, blue);
X XSetForeground(display, viewgridgc, (grey != black) ? grey : white);
X XSetForeground(display, viewselectgc, red);
X XSetForeground(display, cursorgc, white ^ blue);
X XSetFunction(display, cursorgc, GXxor);
X XSetFont(display, statgc, font->fid);
X
X dev->rows = viewheight;
X dev->cols = viewwidth;
X dev->textrows = (viewheight - TEXTOFF * 2) / charheight;
X dev->textcols = (viewwidth - TEXTOFF * 2) / spacewidth;
X
X genstr = genstrbuf;
X mapped = FALSE;
X
X return 0;
X}
X
X
Xstatic void
Xgrclose(dev)
X DEV *dev;
X{
X if (display)
X XCloseDisplay(display);
X}
X
X
Xstatic void
Xgrupdate(dev, inputflag)
X DEV *dev;
X{
X XSync(display, False);
X}
X
X
Xstatic void
Xgrrefresh(dev)
X DEV *dev;
X{
X XSync(display, False);
X}
X
X
X/*
X * Read the next character from the terminal, waiting if requested.
X * If not waiting and no character is ready, then EOF is returned.
X * Returns characters from a generated string first, if present.
X */
Xstatic int
Xgrreadchar(dev, wait)
X DEV *dev;
X{
X XEvent event;
X int ch;
X
X if (*genstr)
X return *genstr++;
X
X do {
X if (!wait && (XEventsQueued(display, QueuedAfterFlush) <= 0))
X return EOF;
X XNextEvent(display, &event);
X ch = doevent(&event);
X } while (ch == EOF);
X
X return ch;
X}
X
X
X/*
X * See if input is ready from the terminal.
X */
Xstatic BOOL
Xgrinputready(dev)
X DEV *dev;
X{
X XEvent event;
X
X if (*genstr)
X return TRUE;
X
X while (TRUE) {
X if (XEventsQueued(display, QueuedAfterFlush) <= 0)
X return FALSE;
X XPeekEvent(display, &event);
X if (event.type == KeyPress)
X return TRUE;
X if (event.type == ButtonPress)
X return TRUE;
X XNextEvent(display, &event);
X doevent(&event);
X }
X}
X
X
X/*
X * Assign a macro to be automatically executed by a mouse button.
X * Returns nonzero if the button is illegal.
X */
Xstatic int
Xgrassign(dev, button, macro)
X DEV *dev;
X VALUE button;
X UCHAR macro;
X{
X if ((button <= 0) || (button > 3))
X return -1;
X assigns[button] = macro;
X return 0;
X}
X
X
X/*
X * Move the cursor to the specified location using the specified scale factor.
X * This is easy to do because we use XOR to draw it.
X */
Xstatic void
Xgrmovecursor(dev, sf, row, col)
X DEV *dev;
X SCALE sf;
X COORD row;
X COORD col;
X{
X if (!mapped)
X return;
X if (cursorshown) {
X drawcursor(sf, cursorx, cursory);
X cursorshown = FALSE;
X }
X if ((sf == 0) || (sf == -1))
X sf = 1;
X if (sf < 0) {
X sf = -sf;
X row = row * sf + ((sf - 1) / 2);
X col = col * sf + ((sf - 1) / 2);
X sf = -sf;
X } else {
X row /= sf;
X col /= sf;
X }
X
X cursorx = col;
X cursory = row;
X drawcursor(sf, cursorx, cursory);
X cursorshown = TRUE;
X}
X
X
X/*
X * Draw the cursor at the specified location. If the scale factor is
X * large enough, then the cursor is made larger.
X */
Xstatic void
Xdrawcursor(sf, x, y)
X SCALE sf;
X COORD x;
X COORD y;
X{
X if (sf > -GRIDMAG) {
X XDrawPoint(display, viewwid, cursorgc, x, y);
X return;
X }
X
X XDrawPoint(display, viewwid, cursorgc, x, y);
X XDrawPoint(display, viewwid, cursorgc, x - 1, y);
X XDrawPoint(display, viewwid, cursorgc, x + 1, y);
X XDrawPoint(display, viewwid, cursorgc, x, y - 1);
X XDrawPoint(display, viewwid, cursorgc, x, y + 1);
X}
X
X
X/*
X * Show the view around the current window location.
X */
Xstatic void
Xgrshowview(dev)
X DEV *dev;
X{
X if (!mapped)
X return;
X if (curobj->o_scale > 1)
X viewscale(curobj->o_scale);
X else if (curobj->o_scale >= -1)
X viewnormal(1);
X else
X viewnormal(-curobj->o_scale);
X}
X
X
X/*
X * Update the status line.
X */
Xstatic void
Xgrshowstatus(dev, str)
X DEV *dev;
X char *str;
X{
X int len;
X int width;
X
X if (!mapped)
X return;
X len = strlen(str);
X XClearWindow(display, statwid);
X width = XTextWidth(font, str, len);
X XDrawString(display, statwid, statgc, TEXTOFF, charascent + TEXTOFF, str, len);
X usedstatus = width + TEXTOFF;
X}
X
X
X/*
X * Add to the status line.
X * The assumption is made that this routine is used only for input,
X * and thus the text is ended with an underscore as a prompt.
X */
Xstatic void
Xgraddstatus(dev, str)
X DEV *dev;
X char *str;
X{
X int len;
X static int uswidth;
X
X len = strlen(str);
X if (uswidth == 0)
X uswidth = XTextWidth(font, "_", 1);
X
X XClearArea(display, statwid, usedstatus, 0, uswidth, 0, False);
X XDrawString(display, statwid, statgc, usedstatus, charascent + TEXTOFF,
X str, len);
X usedstatus += XTextWidth(font, str, len);
X XDrawString(display, statwid, statgc, usedstatus, charascent + TEXTOFF,
X "_", 1);
X}
X
X
X/*
X * Begin to show help information.
X * We use the view window for this.
X */
Xstatic void
Xgrshowhelp(dev)
X DEV *dev;
X{
X XClearWindow(display, viewwid);
X helpcol = 0;
X helpx = TEXTOFF;
X helpy = charascent + TEXTOFF;
X}
X
X
X/*
X * Add information to the help display.
X * We must interpret certain control codes.
X */
Xstatic void
Xgraddhelp(dev, str)
X DEV *dev;
X char *str;
X{
X char *cp;
X int len;
X
X cp = str;
X for (;;) {
X while (*cp >= ' ')
X cp++;
X
X len = cp - str;
X if (len > 0) {
X XDrawString(display, viewwid, viewgc, helpx, helpy,
X str, len);
X helpcol += len;
X helpx += XTextWidth(font, str, len);
X }
X
X switch (*cp++) {
X case '\0':
X return;
X
X case '\n':
X helpcol = 0;
X helpx = TEXTOFF;
X helpy += charheight;
X break;
X
X case '\t':
X len = 8 - (helpcol + 1) % 8;
X XDrawString(display, viewwid, viewgc,
X helpx, helpy, " ", len);
X helpcol += len;
X helpx += spacewidth * len;
X break;
X }
X str = cp;
X }
X}
X
X
X/*
X * Handle the specified event.
X * Returns a character generated by the event, or else EOF if
X * the event does not produce a character.
X */
Xstatic int
Xdoevent(event)
X XEvent *event;
X{
X switch (event->type) {
X case Expose:
X mapped = TRUE;
X doexposure(&event->xexpose);
X return NULL_CMD;
X case ButtonPress:
X return dobuttondown(&event->xbutton);
X break;
X case KeyPress:
X return dokeydown(&event->xkey);
X case MapNotify:
X mapped = TRUE;
X break;
X case UnmapNotify:
X mapped = FALSE;
X break;
X }
X return EOF;
X}
X
X
Xstatic void
Xdoexposure(ep)
X XExposeEvent *ep;
X{
X if (ep->window == statwid)
X update |= U_STAT;
X
X if (ep->window == viewwid)
X update |= U_ALL;
X}
X
X
X/*
X * Handle a button down event.
X * This fakes up a string which moves the pointer to the mouse position,
X * and possibly executes a macro.
X */
Xstatic int
Xdobuttondown(bp)
X XButtonEvent *bp;
X{
X char *cp;
X SCALE sf;
X COORD buttonrow;
X COORD buttoncol;
X COUNT deltarow;
X COUNT deltacol;
X
X if (bp->window != viewwid)
X return -1;
X
X sf = curobj->o_scale;
X if (sf >= 0) {
X buttonrow = bp->y * sf;
X buttoncol = bp->x * sf;
X } else {
X buttonrow = bp->y / (-sf);
X buttoncol = bp->x / (-sf);
X }
X
X deltarow = buttonrow - (curobj->o_currow - curobj->o_minrow);
X deltacol = buttoncol - (curobj->o_curcol - curobj->o_mincol);
X
X if (sf > 1) {
X deltarow /= sf;
X deltacol /= sf;
X }
X
X sprintf(genstrbuf, "%ldj%ldl", deltarow, deltacol);
X
X /*
X * If a macro has been assigned to the button, then add the
X * sequence to execute the macro.
X */
X cp = genstrbuf + strlen(genstrbuf);
X if ((bp->button == Button1) && assigns[1]) {
X *cp++ = ESC;
X *cp++ = assigns[1];
X }
X if ((bp->button == Button2) && assigns[2]) {
X *cp++ = ESC;
X *cp++ = assigns[2];
X }
X if ((bp->button == Button3) && assigns[3]) {
X *cp++ = ESC;
X *cp++ = assigns[3];
X }
X *cp = '\0';
X
X genstr = genstrbuf;
X
X return NULL_CMD;
X}
X
X
X/*
X * Return a key typed in our window, or EOF if no such key was typed.
X */
Xstatic int
Xdokeydown(kp)
X XKeyEvent *kp;
X{
X KeySym keysym;
X int len;
X int ch;
X UCHAR buf[12];
X
X len = XLookupString(kp, buf, sizeof(buf), &keysym, NULL);
X if ((len != 1) || IsModifierKey(keysym))
X return EOF;
X
X ch = buf[0];
X if (ch == '\r')
X ch = '\n';
X
X return ch;
X}
X
X
X/*
X * Show the cells around the cursor normally (showing each cell).
X * The specified magnification factor is applied.
X */
Xstatic void
Xviewnormal(mag)
X{
X register ROW *rp; /* current row */
X register CELL *cp; /* current cell */
X COORD row; /* current row number */
X COORD col; /* current column number */
X OBJECT *obj; /* current object */
X COUNT blankrows; /* number of blank rows */
X COORD screenrow; /* row on screen */
X COORD screencol; /* column on screen */
X BOOL cleared; /* TRUE is line has been cleared */
X GC gc; /* GC for points */
X
X obj = curobj;
X rp = obj->o_firstrow;
X row = obj->o_minrow;
X while (row > rp->r_row)
X rp = rp->r_next;
X
X screenrow = 0;
X blankrows = 0;
X seecount = 0;
X
X for (; row <= obj->o_maxrow; row++) {
X if (row != rp->r_row) { /* blank row */
X blankrows++;
X screenrow++;
X continue;
X }
X
X cp = rp->r_firstcell;
X col = obj->o_mincol;
X while (col > cp->c_col)
X cp = cp->c_next;
X
X screencol = 0;
X cleared = FALSE;
X
X for (; col <= obj->o_maxcol; col++) {
X if (col != cp->c_col) { /* blank cell */
X screencol++;
X continue;
X }
X
X if (!cleared) {
X clearrows((screenrow - blankrows) * mag,
X (blankrows + 1) * mag, mag);
X blankrows = 0;
X cleared = TRUE;
X }
X
X gc = viewgc;
X if (cp->c_marks & MARK_SEE)
X gc = viewselectgc;
X
X if (mag == 1) {
X XDrawPoint(display, viewwid, gc, screencol, screenrow);
X } else if (mag == 2) {
X XDrawPoint(display, viewwid, gc, screencol*2, screenrow*2);
X XDrawPoint(display, viewwid, gc, screencol*2+1, screenrow*2);
X XDrawPoint(display, viewwid, gc, screencol*2, screenrow*2+1);
X XDrawPoint(display, viewwid, gc, screencol*2+1, screenrow*2+1);
X } else {
X XFillRectangle(display, viewwid, gc,
X screencol * mag, screenrow * mag,
X mag - 1, mag - 1);
X }
X
X seecount++;
X screencol++;
X cp = cp->c_next;
X }
X
X if (!cleared)
X blankrows++;
X screenrow++;
X rp = rp->r_next;
X }
X
X clearrows((screenrow - blankrows) * mag,
X dev->rows - (screenrow - blankrows) * mag, mag);
X
X cursorshown = FALSE;
X}
X
X
X/*
X * Show the view around the cursor with an arbitrary scale factor.
X * Each pixel then represents one or more live cells in an N by N area.
X * If any of those cells are marked, then the pixel will show it.
X */
Xstatic void
Xviewscale(sf)
X SCALE sf;
X{
X register CELL *cp; /* current cell structure */
X COORD row; /* current row number */
X COORD col; /* current column number */
X int sum; /* number of cells in square */
X OBJECT *obj; /* current object */
X CELL **cpp; /* pointer into cell table */
X CELL **endcpp; /* end of cell table */
X ROW *rp; /* row pointer */
X COUNT blankrows; /* number of blank rows */
X COORD screenrow; /* row on screen */
X COORD screencol; /* column on screen */
X BOOL cleared; /* TRUE is line has been cleared */
X GC gc; /* GC for points */
X CELL *cptab[MAXSCALE]; /* table of rows */
X
X obj = curobj;
X row = obj->o_minrow;
X col = obj->o_mincol;
X endcpp = &cptab[sf];
X seecount = 0;
X screenrow = 0;
X blankrows = 0;
X
X for (rp = curobj->o_firstrow; (rp->r_row < row); rp = rp->r_next)
X ;
X
X while (row <= obj->o_maxrow) {
X /*
X * If there is a large gap to the next row number then
X * the graphics line is empty.
X */
X if (rp->r_row >= (row + sf)) { /* no rows here */
X row += sf;
X blankrows++;
X screenrow++;
X continue;
X }
X
X /*
X * Collect the rows to be searched for one graphics line.
X * Dummy up empty rows if necessary.
X */
X for (cpp = cptab; cpp < endcpp; cpp++) {
X *cpp = termcell;
X if (rp->r_row > row++)
X continue;
X *cpp = rp->r_firstcell;
X rp = rp->r_next;
X }
X
X /*
X * Advance along each row to the next range of columns,
X * adding cells found to get the result for each square.
X */
X screencol = 0;
X cleared = FALSE;
X
X for (col = obj->o_mincol; col <= obj->o_maxcol; col += sf) {
X gc = viewgc;
X sum = 0;
X
X for (cpp = cptab; cpp < endcpp; cpp++) {
X cp = *cpp;
X while (col > cp->c_col)
X cp = cp->c_next;
X
X while ((col + sf) >= cp->c_col) {
X sum++;
X if (cp->c_marks & MARK_SEE)
X gc = viewselectgc;
X cp = cp->c_next;
X }
X *cpp = cp;
X }
X
X if (sum == 0) { /* no cells in square */
X screencol++;
X continue;
X }
X
X if (!cleared) {
X XClearArea(display, viewwid, 0,
X screenrow - blankrows, viewwidth,
X blankrows + 1, False);
X blankrows = 0;
X cleared = TRUE;
X }
X
X XDrawPoint(display, viewwid, gc, screencol, screenrow);
X
X seecount += sum;
X screencol++;
X }
X
X if (!cleared)
X blankrows++;
X screenrow++;
X }
X
X XClearArea(display, viewwid, 0, screenrow - blankrows,
X viewwidth, dev->rows - (screenrow - blankrows), False);
X
X cursorshown = FALSE;
X}
X
X
X/*
X * Clear the specified number of rows on the screen, taking into account
X * the specified magnification factor. If the magnification is large
X * enough and a grid has been specified, then some dots will be drawn
X * in the cleared rows to indicate the position of each cell. The row
X * number and row counts are in pixels.
X */
Xstatic void
Xclearrows(row, rowcount, mag)
X COORD row;
X COUNT rowcount;
X SCALE mag;
X{
X COUNT colcount;
X COORD col;
X COUNT offset;
X
X if ((mag < GRIDMAG) || (gridchar == ' ')) {
X XClearArea(display, viewwid, 0, row,
X viewwidth, rowcount, False);
X return;
X }
X
X /*
X * For each row, clear it and then draw one pixel in the center of
X * each cell of the row. The whole area isn't cleared at once for
X * this case so as to make the graphics look nicer as it is drawn.
X */
X offset = (mag - 1) / 2;
X rowcount /= mag;
X
X while (rowcount-- > 0) {
X XClearArea(display, viewwid, 0, row,
X viewwidth, mag, False);
X col = offset;
X colcount = viewwidth / mag;
X while (colcount-- > 0) {
X XDrawPoint(display, viewwid, viewgridgc, col, row + offset);
X col += mag;
X }
X row += mag;
X }
X}
X
X#endif
X
X/* END CODE */
SHAR_EOF
$TOUCH -am 0316122993 life/x11dev.c &&
chmod 0644 life/x11dev.c ||
echo "restore of life/x11dev.c failed"
set `wc -c life/x11dev.c`;Wc_c=$1
if test "$Wc_c" != "19386"; then
echo original size 19386, current size $Wc_c
fi
rm -f shar3_seq_.tmp
echo "You have unpacked the last part"
exit 0
This archive was generated by hypermail 2.1.7 : Tue Oct 14 2003 - 21:44:08 UTC