Files
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

785 lines
18 KiB
C

#ifndef lint
static char sccsid[] = "@(#)lifetool.c 1.1 94/10/31 Copyr 1985 Sun Micro";
#endif
/*
* Copyright (c) 1985 by Sun Microsystems Inc.
*/
#include <stdio.h>
#include <sunwindow/cms.h>
#include <suntool/tool_hs.h>
#include <suntool/optionsw.h>
#include <suntool/msgsw.h>
#include <suntool/menu.h>
#include <suntool/panel.h>
#include <suntool/scrollbar.h>
#include "life.h"
#define abs(x) (((x) > 0) ? (x) : -(x))
#ifndef max
#define max(x,y) (((x) > (y)) ? (x) : (y))
#endif
struct timeval tv;
extern struct pixfont *pw_pfsysopen(), *pf_open();
struct pixfont *littlefont;
/* tool and sunwindows-specific data */
static struct tool *tool;
static struct toolsw *msg_tsw, *opt_tsw, *board_tsw;
static struct pixwin *board_pixwin;
static struct msgsubwindow *mswerror;
static int newmessage;/* set when change mswerror */
static int gencnt;
Panel_item mode_item, zoom_item, gen_item;
Panel osw;
Scrollbar leftscroll, upscroll;
static struct pixfont *font;
int doscroll();
static mode_proc(), grid_proc(), speed_proc(), move_proc(),
sigwinched(), board_selected(), board_sighandler(), zoom_proc();
int reset_proc(), quit_proc();
static int clock_selected();
struct pixrect *mem_create();
int spacing; /* distance between 2 lines */
struct pixrect *piecepix;
static short tri_right_dat[] = {
0xC000,0xF000,0xFC00, 0xFE00,0xFC00,0xF000,0xC000,0x0000,
};
mpr_static(tri_right, 16, 8, 1, tri_right_dat);
static short grid_array[] = {
0x2480,0x2480,0xFFE0,0x2480,0x2480,0xFFE0,0x2480,0x2480,
0xFFE0,0x2480,0x2480,0x0000,0x0000,0x0000,0x0000,0x0000
};
mpr_static(grid_pr, 11, 11, 1, grid_array);
int runmode; /* am I in run mode? */
int gridon; /* is grid visible? */
struct timeval nextupdate = {0, 100000};
static short icon_data[256]={
#include <images/life.icon>
};
mpr_static(base_mpr, 64, 64, 1, icon_data);
static struct icon goicon = {64, 64, (struct pixrect *)0,
{0, 0, 64, 64}, &base_mpr,
{0, 0, 0, 0}, 0, (struct pixfont *)0, 0};
char board[NLINES][NLINES];
#define SCROLLWIDTH 18
#define MAXLENGTH 64
extern char
circlearr[MAXLENGTH][MAXLENGTH]; /* where drawcircle puts its ouput */
#define SPACING 15 /* diameter = 12 */
struct rect currect;
int rightedge;
int bottomedge;
int leftoffset;
int upoffset;
int ozoom = SPACING;
int color;
static struct menuitem menu_items[] = {
{MENU_IMAGESTRING, "glider", (char *)GLIDER},
{MENU_IMAGESTRING, "8", (char *)EIGHT},
{MENU_IMAGESTRING, "pulsar", (char *)PULSAR},
{MENU_IMAGESTRING, "gun", (char *)GUN},
{MENU_IMAGESTRING, "escort", (char *)ESCORT},
{MENU_IMAGESTRING, "barber", (char *)BARBER},
{MENU_IMAGESTRING, "puffer", (char *)PUFFER},
{MENU_IMAGESTRING, "hertz", (char *)HERTZ},
{MENU_IMAGESTRING, "tumbler", (char *)TUMBLER},
{MENU_IMAGESTRING, "muchnick", (char *)MUCHNICK},
{MENU_IMAGESTRING, "reset", (char *)RESET},
{MENU_IMAGESTRING, "run", (char *)RUN},
};
static struct menu menu_body = {
MENU_IMAGESTRING, "patterns",
sizeof(menu_items)/sizeof(struct menuitem), menu_items,
NULL, NULL
};
static struct menu *menu_ptr = &menu_body;
char cmsname[CMS_NAMESIZE];
u_char red[CMSIZE];
u_char green[CMSIZE];
u_char blue[CMSIZE];
static char tool_name[] = "Game of Life 2.0";
FILE *debugfp;
main(argc, argv)
char **argv;
{
char **tool_attrs = NULL;
int k;
if (tool_parse_all(&argc, argv, &tool_attrs, tool_name) == -1) {
tool_usage(tool_name);
exit(1);
}
spacing = SPACING;
debugfp = stdout;
/*
* create the tool
*/
tool = tool_make(WIN_NAME_STRIPE, 1,
WIN_BOUNDARY_MGR, 1,
WIN_LABEL, tool_name,
WIN_ATTR_LIST, tool_attrs,
WIN_ICON, &goicon, 0);
if (tool == (struct tool *)NULL) lose("Couldn't create tool");
tool_free_attribute_list(tool_attrs);
/*font = pw_pfsysopen(); */
font = pf_open("/usr/lib/fonts/fixedwidthfonts/screen.r.11");
if (font == (struct pixfont *)NULL)
lose("Couldn't get default font");
littlefont = pf_open("/usr/lib/fonts/fixedwidthfonts/screen.r.7");
if (littlefont == (struct pixfont *)NULL)
lose("Couldn't get little font");
/* create and initialize the message subwindow */
msg_tsw = msgsw_createtoolsubwindow(tool, "", TOOL_SWEXTENDTOEDGE,
(font->pf_defaultsize.y * 3) / 2,
"Left paints", font);
if (msg_tsw == (struct toolsw *)NULL)
lose("Couldn't create message subwindow");
mswerror = (struct msgsubwindow *)msg_tsw->ts_data;
/*
* picking msg_tsw for one second interrupt was an
* arbitrary choice
*/
msg_tsw->ts_io.tio_selected = clock_selected;
msg_tsw->ts_io.tio_timer = &tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
/* create and initialize the option subwindow */
opt_tsw = panel_create(tool,
PANEL_HEIGHT, TOOL_SWEXTENDTOEDGE,
PANEL_FONT, font,
0);
if (opt_tsw == (struct toolsw *)NULL)
lose("Couldn't create option subwindow");
init_options();
/* create and initialize the board subwindow */
board_tsw = tool_createsubwindow(tool, "",
TOOL_SWEXTENDTOEDGE, TOOL_SWEXTENDTOEDGE);
if (board_tsw == (struct toolsw *)NULL)
lose("Couldn't create board subwindow");
win_getsize(board_tsw->ts_windowfd, &currect);
rightedge = (currect.r_width - SCROLLWIDTH)/spacing;
bottomedge = (currect.r_height - SCROLLWIDTH)/spacing;
circle();
init_board();
leftscroll = scrollbar_create(SCROLL_PIXWIN, board_pixwin,
SCROLL_NOTIFY_PROC, doscroll,
SCROLL_BAR_DISPLAY_LEVEL, SCROLL_ALWAYS,
SCROLL_BUBBLE_DISPLAY_LEVEL, SCROLL_ALWAYS,
SCROLL_DIRECTION, SCROLL_HORIZONTAL,
SCROLL_TOP, currect.r_height - SCROLLWIDTH,
SCROLL_LEFT, 0,
SCROLL_WIDTH, currect.r_width - SCROLLWIDTH,
SCROLL_HEIGHT, SCROLLWIDTH,
0);
upscroll = scrollbar_create(SCROLL_PIXWIN, board_pixwin,
SCROLL_NOTIFY_PROC, doscroll,
SCROLL_BAR_DISPLAY_LEVEL, SCROLL_ALWAYS,
SCROLL_BUBBLE_DISPLAY_LEVEL, SCROLL_ALWAYS,
SCROLL_DIRECTION, SCROLL_VERTICAL,
SCROLL_TOP, 0,
SCROLL_LEFT, currect.r_width - SCROLLWIDTH,
SCROLL_WIDTH, SCROLLWIDTH,
SCROLL_HEIGHT, currect.r_height - SCROLLWIDTH,
0);
board_init();
signal(SIGWINCH, sigwinched);
/* install tool */
tool_install(tool);
/* set up color map */
color = amicolor();
if (color) {
sprintf(cmsname, "lifetool%d", getpid());
pw_setcmsname(board_pixwin, cmsname);
red[0] = 255;
blue[0] = 255;
green[0] = 255;
red[CMSIZE-1] = 0;
blue[CMSIZE-1] = 0;
green[CMSIZE-1] = 0;
for(k = 1; k <= CMSIZE-1; k++) {
red[k] = (k-1)*(256/CMSIZE);
green[k] = 0;
blue[k] = 255 - red[k];
}
pw_putcolormap(board_pixwin, 0, CMSIZE, red, green, blue);
}
tool_select(tool, 0);
/* terminate tool */
tool_destroy(tool);
pw_pfsysclose();
exit(0);
}
lose(str)
char *str;
{ fprintf(stderr, str); exit(1);
}
static
sigwinched()
{
tool_sigwinch(tool);
}
static
init_options()
{
osw = (Panel)opt_tsw->ts_data;
/*
* create optsw items
*/
panel_create_item(osw, PANEL_MESSAGE,
PANEL_LABEL_STRING, " ", 0);
panel_create_item(osw, PANEL_TOGGLE,
PANEL_FEEDBACK, PANEL_INVERTED,
PANEL_CHOICE_IMAGES, &grid_pr, 0,
PANEL_NOTIFY_PROC, grid_proc, 0);
panel_create_item(osw, PANEL_MESSAGE,
PANEL_LABEL_STRING, " ", 0);
mode_item = panel_create_item(osw, PANEL_CHOICE,
PANEL_FEEDBACK, PANEL_MARKED,
PANEL_LABEL_STRING, "mode:",
PANEL_MARK_IMAGES, &tri_right,0,
PANEL_NOMARK_IMAGES, 0,
PANEL_VALUE, 1,
PANEL_CHOICE_STRINGS, "run", "step", 0,
PANEL_NOTIFY_PROC, mode_proc, 0);
panel_create_item(osw, PANEL_MESSAGE,
PANEL_LABEL_STRING, " ", 0);
panel_create_item(osw, PANEL_BUTTON,
PANEL_LABEL_IMAGE, panel_button_image(osw,
"reset", 0, littlefont),
PANEL_NOTIFY_PROC, reset_proc, 0);
panel_create_item(osw, PANEL_MESSAGE,
PANEL_LABEL_STRING, " ", 0);
panel_create_item(osw, PANEL_BUTTON,
PANEL_LABEL_IMAGE, panel_button_image(osw,
"quit", 0, littlefont),
PANEL_NOTIFY_PROC, quit_proc, 0);
panel_create_item(osw, PANEL_MESSAGE,
PANEL_LABEL_STRING, " ", 0);
gen_item = panel_create_item(osw, PANEL_MESSAGE,
PANEL_LABEL_STRING, " 0", 0);
panel_create_item(osw, PANEL_MESSAGE,
PANEL_LABEL_STRING, "fast",
PANEL_ITEM_X, PANEL_CU(0),
PANEL_ITEM_Y, PANEL_CU(1), 0);
panel_create_item(osw, PANEL_SLIDER,
PANEL_MIN_VALUE, 0,
PANEL_MAX_VALUE, 200,/* hundredths of a sec */
PANEL_NOTIFY_LEVEL, PANEL_DONE,
PANEL_SHOW_VALUE, FALSE,
PANEL_SHOW_RANGE, FALSE,
PANEL_NOTIFY_PROC, speed_proc, 0);
panel_create_item(osw, PANEL_MESSAGE,
PANEL_LABEL_STRING, "slow", 0);
panel_create_item(osw, PANEL_MESSAGE,
PANEL_LABEL_STRING, " zoom out", 0);
zoom_item = panel_create_item(osw, PANEL_SLIDER,
PANEL_MIN_VALUE, 4, /* minimum that circle() can deal with */
PANEL_MAX_VALUE, 40,
PANEL_VALUE, SPACING,
PANEL_SHOW_VALUE, FALSE,
PANEL_SHOW_RANGE, FALSE,
PANEL_NOTIFY_LEVEL, PANEL_DONE,
PANEL_NOTIFY_PROC, zoom_proc, 0);
panel_create_item(osw, PANEL_MESSAGE,
PANEL_LABEL_STRING, "zoom in", 0);
panel_fit_height(osw);
}
static
init_board()
{
struct inputmask mask;
register int i,j;
for(i = 0; i < rightedge; i++)
for(j = 0; j < bottomedge; j++)
board[i][j] = 0;
board_pixwin = pw_open(board_tsw->ts_windowfd);
if (board_pixwin == (struct pixwin *)NULL)
lose("Couldn't create board pixwin");
board_tsw->ts_io.tio_handlesigwinch = board_sighandler;
board_tsw->ts_io.tio_selected = board_selected;
input_imnull(&mask);
win_setinputcodebit(&mask, MS_LEFT);
win_setinputcodebit(&mask, MS_MIDDLE);
win_setinputcodebit(&mask, MENU_BUT);
win_setinputcodebit(&mask, LOC_MOVE);
win_setinputcodebit(&mask, LOC_MOVEWHILEBUTDOWN);
mask.im_flags |= IM_NEGEVENT;
win_setinputmask(board_tsw->ts_windowfd, &mask,
(struct inputmask *)NULL, WIN_NULLLINK);
}
lock()
{
struct rect rect;
rect = currect;
rect.r_width = rightedge*spacing;
rect.r_height = bottomedge*spacing;
pw_lock(board_pixwin, &rect);
}
unlock()
{
pw_unlock(board_pixwin);
}
static
board_init()
{
register int i,j;
pw_writebackground(board_pixwin, 0, 0, currect.r_width,
currect.r_height, PIX_CLR);
scrollbar_set(leftscroll, SCROLL_TOP, currect.r_height - SCROLLWIDTH,
SCROLL_WIDTH, currect.r_width - SCROLLWIDTH, 0);
scrollbar_set(upscroll, SCROLL_LEFT, currect.r_width - SCROLLWIDTH,
SCROLL_HEIGHT, currect.r_height - SCROLLWIDTH, 0);
leftbubble();
upbubble();
scrollbar_paint_all_clear(board_pixwin);
/*
* should use batchrop here
*/
if (gridon)
drawgrid();
for (i = 0; i < rightedge; i++) {
for (j = 0; j < bottomedge; j++) {
if (board[i][j])
paint_stone(i, j, board[i][j]);
}
}
msgsw_setstring(mswerror, "Left paints, middle erases");
}
drawgrid()
{
int wd, ht, i, j;
wd = rightedge * spacing;
ht = bottomedge * spacing;
lock();
for (j = 0; j <= ht; j+=spacing)
pw_vector(board_pixwin, 0, j, wd, j,
PIX_SRC^PIX_DST, 1);
for (j = 0; j <= wd; j+=spacing)
pw_vector(board_pixwin, j, 0, j, ht,
PIX_SRC^PIX_DST, 1);
unlock();
}
/* respond to damage to board subwindow */
static
board_sighandler(sw)
caddr_t sw;
{
struct rect r;
win_getsize(board_tsw->ts_windowfd, &r);
/*
* resize whole thing if size change, otherwise just
* redraw damaged part
*/
if (r.r_width != currect.r_width || r.r_height != currect.r_height) {
currect.r_width = r.r_width;
currect.r_height = r.r_height;
rightedge = (currect.r_width-SCROLLWIDTH)/spacing;
bottomedge = (currect.r_height-SCROLLWIDTH)/spacing;
refreshboard();
board_init();
}
else {
pw_damaged(board_pixwin);
board_init();
pw_donedamaged(board_pixwin);
}
}
/* get notification from option subwindow */
static
grid_proc(item, value, event)
Panel_item item;
struct inputevent event;
{
gridon ^= 1;
drawgrid();
}
static
mode_proc(item, value, event)
Panel_item item;
struct inputevent event;
{
if (value == 0)
runmode = 1;
else {
runmode = 0;
newgen();
updategen();
}
}
static
speed_proc(item, value, event)
Panel_item item;
int value;
struct inputevent event;
{
nextupdate.tv_sec = value/100;
nextupdate.tv_usec = (value%100)*10000;
}
static
zoom_proc(item, zoom, event)
Panel_item item;
int zoom;
{
spacing = zoom;
rightedge = (currect.r_width-SCROLLWIDTH)/spacing;
bottomedge = (currect.r_height-SCROLLWIDTH)/spacing;
leftoffset += ((currect.r_width/zoom) - (currect.r_width/ozoom))/2;
upoffset += ((currect.r_height/zoom) - (currect.r_height/ozoom))/2;
circle();
refreshboard();
board_init();
ozoom = zoom;
}
quit_proc()
{
exit(0);
}
reset_proc(panel, item)
Panel panel;
Panel_item item;
{
int i,j;
for(i = 0; i < rightedge; i++)
for(j = 0; j < bottomedge; j++)
board[i][j] = 0;
zerolist();
runmode = 0;
gencnt = 0;
ozoom = SPACING;
spacing = SPACING;
rightedge = (currect.r_width-SCROLLWIDTH)/spacing;
bottomedge = (currect.r_height-SCROLLWIDTH)/spacing;
leftoffset = 0;
upoffset = 0;
panel_set_value(mode_item, 1);
panel_set_value(zoom_item, SPACING);
panel_paint(mode_item, PANEL_CLEAR);
panel_paint(zoom_item, PANEL_CLEAR);
panel_set(gen_item, PANEL_LABEL_STRING, " 0", 0);
circle();
refreshboard();
board_init();
}
run_proc()
{
panel_set_value(mode_item, 0);
panel_paint(mode_item, PANEL_CLEAR);
runmode = 1;
}
/*
* respond to user inputs in board area
*/
static
board_selected(sw, ibits, obits, ebits, timer)
caddr_t sw;
int *ibits, *obits, *ebits;
struct timeval **timer;
{
int x, y;
struct inputevent ie;
struct menuitem *mi;
int cur_x, cur_y, entered;
static int erasing, painting;
Scrollbar sb;
if (input_readevent(board_tsw->ts_windowfd, &ie) == -1) {
perror("input_readevent failed");
abort();
}
*ibits = *obits = *ebits = 0;
sb = scrollbar_for_point(board_pixwin, ie.ie_locx, ie.ie_locy,
&entered);
if (sb) {
if (entered) {
if (sb == leftscroll)
leftbubble();
else
upbubble();
}
scrollbar_interpret(board_pixwin, &ie);
return;
}
scrollbar_interpret(board_pixwin, &ie);
if (ie.ie_code == MENU_BUT && win_inputposevent(&ie) &&
(mi = menu_display(&menu_ptr, &ie, board_tsw->ts_windowfd))) {
ie.ie_code = (short) mi->mi_data;
handlemenu(ie);
*ibits = *obits = *ebits = 0;
return;
}
x = ie.ie_locx; y = ie.ie_locy;
cur_x = (x/spacing)*spacing;
cur_y = (y/spacing)*spacing;
if (cur_x > spacing*(rightedge-1) || cur_y > spacing*(bottomedge-1))
return;
if (win_inputnegevent(&ie)) {
erasing = 0;
painting = 0;
return;
}
if (ie.ie_code == MS_MIDDLE ||
(ie.ie_code == LOC_MOVEWHILEBUTDOWN && erasing)) {
erasing = 1;
if (board[cur_x/spacing][cur_y/spacing]== 0)
return;
deletepoint(cur_x/spacing - leftoffset,
cur_y/spacing - upoffset);
erase_stone(cur_x/spacing, cur_y/spacing);
}
else if (ie.ie_code == MS_LEFT ||
(ie.ie_code == LOC_MOVEWHILEBUTDOWN && painting)) {
painting = 1;
addpoint(cur_x/spacing - leftoffset,
cur_y/spacing - upoffset);
paint_stone(cur_x/spacing, cur_y/spacing, INITCOLOR);
}
}
paint_stone(i, j, color)
{
int diameter;
diameter = spacing - 3;
if (color)
pw_write(board_pixwin, i*spacing+2, j*spacing+2, diameter,
diameter, (PIX_COLOR(color)|PIX_SRC), piecepix, 0, 0);
else
pw_write(board_pixwin, i*spacing+2, j*spacing+2, diameter,
diameter, PIX_SRC, piecepix, 0, 0);
board[i][j] = color;
}
erase_stone(i, j)
{
int diameter;
diameter = spacing - 3;
if (color)
pw_write(board_pixwin, i*spacing+2, j*spacing+2,
diameter, diameter,
(PIX_SRC|PIX_COLOR(board[i][j])) ^ PIX_DST,
piecepix, 0, 0);
else
pw_write(board_pixwin, i*spacing+2, j*spacing+2,
diameter, diameter, PIX_SRC ^ PIX_DST, piecepix, 0, 0);
board[i][j] = 0;
}
circle()
{
int i,j, diameter;
diameter = spacing - 3;
if (diameter >= MAXLENGTH) {
fprintf(stderr, "help!\n");
exit(1);
}
drawcircle(diameter, 0, 1);
if (piecepix != NULL)
pr_destroy(piecepix);
piecepix = mem_create(diameter, diameter, 1);
for (j = 0; j < diameter; j++) {
for (i = 0; i < diameter; i++)
pr_put(piecepix, i, j, circlearr[i][j]);
}
}
/*
* 1 sec timer: If in runmode, advance one cycle
*/
static
clock_selected(msgsw, ibits, obits, ebits, timer)
struct msgsubwindow *msgsw;
int *ibits, *obits, *ebits;
struct timeval **timer;
{
if (*timer && ((*timer)->tv_sec == 0) && ((*timer)->tv_usec == 0)
&& *ibits == 0) {
if (runmode) {
newgen();
updategen();
}
tv = nextupdate;
}
*ibits = 0;
*obits = 0;
*ebits = 0;
}
amicolor()
{
struct screen screen;
return (tool->tl_pixwin->pw_pixrect->pr_depth > 1);
}
doscroll(pw, sb, notify_data, offset, length, motion)
struct pixwin *pw;
Scrollbar sb;
char *notify_data;
Scroll_motion motion;
{
int left, right, top, bottom;
int oldleftoffset, oldupoffset;
float x;
switch (motion) {
case SCROLL_FORWARD:
if (offset <= spacing)
return;
if (sb ==leftscroll)
leftoffset -= offset/spacing;
else
upoffset -= offset/spacing;
break;
case SCROLL_BACKWARD:
if (offset <= spacing)
return;
if (sb ==leftscroll)
leftoffset += offset/spacing;
else
upoffset += offset/spacing;
break;
case SCROLL_ABSOLUTE:
box(&left, &right, &top, &bottom);
x = offset/(float)length;
if (sb == leftscroll) {
oldleftoffset = leftoffset;
if ((right - left) > rightedge)
leftoffset = rightedge/2 -
(left + x*(right - left));
else
leftoffset = x*rightedge -
(left + right)/2;
if (oldleftoffset == leftoffset)
return;
}
else {
oldupoffset = upoffset;
if ((bottom - top) > bottomedge)
upoffset = bottomedge/2 -
(top + x*(bottom - left));
else
upoffset = x*bottomedge -
(top + bottom)/2;
if (oldupoffset == upoffset)
return;
}
break;
}
refreshboard();
board_init();
}
/*
* update bubble in left scrollbar
*/
leftbubble()
{
int left, right, top, bottom;
int start;
box(&left, &right, &top, &bottom);
start = max(-leftoffset - left, 0);
start = min(start, right - left);
scrollbar_set(leftscroll,
SCROLL_VIEW_START, start,
SCROLL_VIEW_LENGTH, rightedge,
SCROLL_OBJECT_LENGTH, right - left, 0);
}
upbubble()
{
int left, right, top, bottom;
int start;
box(&left, &right, &top, &bottom);
start = max(-upoffset - top, 0);
start = min(start, bottom - top);
scrollbar_set(upscroll,
SCROLL_VIEW_START, start,
SCROLL_VIEW_LENGTH, bottomedge,
SCROLL_OBJECT_LENGTH, bottom - top, 0);
}
updategen()
{
char buf[7];
gencnt++;
sprintf(buf, "%6d", gencnt);
panel_set(gen_item, PANEL_LABEL_STRING, buf, 0);
}