117288Sopcode /*
2*17649Sopcode  * @(#)main.c	1.2	01/03/85
317288Sopcode  *
417288Sopcode  * Main program for the SUN Gremlin picture editor.
517288Sopcode  *
617288Sopcode  * Many of the routines in SUN Gremlin are direct descendants of
717288Sopcode  * their counterparts in the original Gremlin written for the AED
817288Sopcode  * by Barry Roitblat.
917288Sopcode  *
1017288Sopcode  * Mark Opperman (opcode@monet.BERKELEY)
1117288Sopcode  *
1217288Sopcode  */
1317288Sopcode 
1417288Sopcode #include <suntool/tool_hs.h>
1517288Sopcode #include <suntool/fullscreen.h>
1617288Sopcode #include <suntool/menu.h>
1717288Sopcode #include <suntool/wmgr.h>
1817288Sopcode #include <sunwindow/cms.h>
1917288Sopcode #include <sunwindow/win_ioctl.h>
2017288Sopcode #include <sun/fbio.h>
2117288Sopcode #include <sys/file.h>
2217288Sopcode #include <sys/ioctl.h>
2317288Sopcode #include <errno.h>
2417288Sopcode #include "gremlin.h"
2517288Sopcode #include "icondata.h"
2617288Sopcode 
2717288Sopcode #define RETAIN TRUE		/* use retained subwindow for pix_sw */
2817288Sopcode 
2917288Sopcode #ifdef maybefaster
3017288Sopcode char *_image;
3117288Sopcode int _bytesperline, _maxx, _maxy;
3217288Sopcode #endif
3317288Sopcode 
3417288Sopcode /* database imports */
3517288Sopcode 
3617288Sopcode extern ELT *DBRead();
3717288Sopcode extern POINT *PTMakePoint();
3817288Sopcode extern FILE *POpen();
3917288Sopcode 
4017288Sopcode /* imports from startup.c */
4117288Sopcode 
4217288Sopcode extern STERROR;
4317288Sopcode extern STgremlinrc();
4417288Sopcode 
4517288Sopcode /* imports from menu.c */
4617288Sopcode 
4717288Sopcode extern MNDisplayMenu();
4817288Sopcode extern MNInitMenu();
4917288Sopcode 
5017288Sopcode /* graphics imports */
5117288Sopcode 
5217288Sopcode extern GRBlankGrid();
5317288Sopcode extern GRCurrentSet();
5417288Sopcode extern GRCurrentSetOn();
5517288Sopcode extern GRDisplayGrid();
5617288Sopcode extern GRFontInit();
5717288Sopcode 
5817288Sopcode /* imports from undodb.c */
5917288Sopcode 
6017288Sopcode extern UNForget();
6117288Sopcode extern UNELT *unlist;
6217288Sopcode extern UNELT *unback;
6317288Sopcode 
6417288Sopcode /* imports from long.c */
6517288Sopcode 
6617288Sopcode extern SHOWPOINTS;
6717288Sopcode extern char *Editfile;
6817288Sopcode extern CP();
6917288Sopcode extern LGQuit();
70*17649Sopcode extern nop();
7117288Sopcode 
7217288Sopcode /* imports from short.c */
7317288Sopcode 
7417288Sopcode extern SHCommand();
7517288Sopcode extern SHUpdate();
7617288Sopcode 
7717288Sopcode /* imports from C */
7817288Sopcode 
7917288Sopcode extern char *malloc();
8017288Sopcode extern char *sprintf();
8117288Sopcode extern char *strcat();
8217288Sopcode extern char *strcpy();
8317288Sopcode 
8417288Sopcode /* imports from strings.c */
8517288Sopcode 
8617288Sopcode extern char version[];
8717288Sopcode extern char GLibrary[];
8817288Sopcode 
8917288Sopcode /* Declaration of Globals */
9017288Sopcode 
9117288Sopcode ELT arhead;
9217288Sopcode ELT *cset;
9317288Sopcode ELT *MEN[NUSER];
9417288Sopcode ELT *PICTURE;
9517288Sopcode 
9617288Sopcode POINT *BACKPOINT;
9717288Sopcode POINT MENPOINT[NUSER];
9817288Sopcode POINT *POINTLIST;
9917288Sopcode 
10017288Sopcode int Artmode = FALSE;
10117288Sopcode int Adjustment = NOADJ;
10217288Sopcode int Alignment = 4;
10317288Sopcode int CBRUSH = 5;
10417288Sopcode int CFONT = 1;
10517288Sopcode int CJUST = 0;
10617288Sopcode int CSIZE = 1;
10717288Sopcode int CSTIPPLE = 1;
10817288Sopcode int GravityOn = FALSE;
10917288Sopcode int Gridon = FALSE;
11017288Sopcode int Gridsize = 32;
11117288Sopcode int Orientation;
11217288Sopcode int SEQ = 0;
11317288Sopcode int CHANGED = FALSE;
11417288Sopcode int SEARCH = TRUE;
11517288Sopcode int SymbolicLines = 0;
116*17649Sopcode int newfileformat = 1;			/* 1=sungremlinfile, 0=gremlinfile */
11717288Sopcode int TOOLINSTALLED = 0;
118*17649Sopcode int (*lastcommand)();			/* last command's routine pointer */
119*17649Sopcode int lasttext = FALSE;			/* TRUE if last command uses text */
12017288Sopcode 
12117288Sopcode float PX, PY;				/* user point coordinate */
12217288Sopcode float Lastx, Lasty;			/* last user point coordinate */
12317288Sopcode 
12417288Sopcode long timeon_ms = 580;			/* current set flash on period */
12517288Sopcode long timeon_s = 0;
12617288Sopcode long timeoff_ms = 180;			/* current set flash off period */
12717288Sopcode long timeoff_s = 0;
12817288Sopcode 
12917288Sopcode int FLASH_READY = 0;			/* TRUE if time to flash current set */
13017288Sopcode int CsetOn = 1;				/* TRUE if current set displayed */
13117288Sopcode static struct itimerval itime;		/* for ALARM signals */
13217288Sopcode static alrm_sighandler();
13317288Sopcode 
13417288Sopcode int SUN_XORIGIN = 0;			/* top left corner in gremlin coords */
13517288Sopcode int SUN_YORIGIN = 511;
13617288Sopcode 
137*17649Sopcode static char SccsId [] = "@(#)main.c	1.2   (Berkeley)      01/03/85";
13817288Sopcode 
13917288Sopcode /* imports from menu.c */
14017288Sopcode 
14117288Sopcode extern menu_left();
14217288Sopcode extern menu_middle();
14317288Sopcode extern menu_right();
14417288Sopcode extern menu_winexit();
14517288Sopcode extern mouse_move();
14617288Sopcode 
14717288Sopcode 
14817288Sopcode /* imports from pix.c */
14917288Sopcode 
15017288Sopcode extern pix_left();
15117288Sopcode extern pix_middle();
15217288Sopcode extern pix_right();
15317288Sopcode extern pix_winexit();
15417288Sopcode 
15517288Sopcode 
15617288Sopcode /* imports from suntext.c */
15717288Sopcode 
15817288Sopcode extern text_left();
15917288Sopcode extern text_middle();
16017288Sopcode extern text_right();
16117288Sopcode extern text_winexit();
16217288Sopcode extern text_putvalue();
16317288Sopcode extern text_output();
16417288Sopcode extern TxInit();
16517288Sopcode extern TxPutMsg();
16617288Sopcode 
16717288Sopcode struct cursor kbd_cursor  =  {
16817288Sopcode     4, 8, PIX_SRC^PIX_DST, &kbdcursor_pr
16917288Sopcode };
17017288Sopcode 
17117288Sopcode struct cursor main_cursor  =  {
17217288Sopcode     0, 0, PIX_SRC^PIX_DST, &uparrow_pr
17317288Sopcode };
17417288Sopcode 
17517288Sopcode static struct cursor menu_cursor = {
17617288Sopcode     3, 3, PIX_SRC^PIX_DST, &diamond_pr
17717288Sopcode };
17817288Sopcode 
179*17649Sopcode static struct icon gremlin_icon = {
180*17649Sopcode     TOOL_ICONWIDTH, TOOL_ICONHEIGHT, NULL,
181*17649Sopcode     {0, 0, TOOL_ICONWIDTH, TOOL_ICONHEIGHT},
182*17649Sopcode     &gremlin_icon_pr, {0, 0, 0, 0}, NULL, NULL, 0
183*17649Sopcode };
184*17649Sopcode 
18517288Sopcode /* tool window stuff */
18617288Sopcode 
18717288Sopcode #define DEV_FB "/dev/fb"
18817288Sopcode struct tool *tool;
18917288Sopcode struct rect tool_size;
19017288Sopcode int tool_fd;
19117288Sopcode int rootfd;
19217288Sopcode char namestripe[256];
19317288Sopcode static tool_selected();
19417288Sopcode static init_tool();
19517288Sopcode static sigwinched();
19617288Sopcode 
19717288Sopcode /* for handling tool manager menu */
19817288Sopcode 
19917288Sopcode extern struct menu *wmgr_toolmenu;
20017288Sopcode extern struct menuitem *menu_display();
20117288Sopcode 
20217288Sopcode /* text subwindow */
20317288Sopcode 
20417288Sopcode struct toolsw *text_sw;
20517288Sopcode struct pixwin *text_pw;
20617288Sopcode struct rect text_size;
20717288Sopcode int text_fd;
20817288Sopcode struct pixfont *text_pf;
20917288Sopcode static init_text();
21017288Sopcode static text_selected();
21117288Sopcode static text_sighandler();
21217288Sopcode 
21317288Sopcode /* menu subwindow */
21417288Sopcode 
21517288Sopcode struct toolsw *menu_sw;
21617288Sopcode struct pixwin *menu_pw;
21717288Sopcode struct rect menu_size;
21817288Sopcode int menu_fd;
21917288Sopcode static init_menu();
22017288Sopcode static menu_selected();
22117288Sopcode static menu_sighandler();
22217288Sopcode 
22317288Sopcode /* pix subwindow */
22417288Sopcode 
22517288Sopcode struct toolsw *pix_sw;
22617288Sopcode struct pixwin *pix_pw;
22717288Sopcode struct rect pix_size;
22817288Sopcode int pix_fd;
22917288Sopcode static init_pix();
23017288Sopcode static pix_selected();
23117288Sopcode static pix_sighandler();
23217288Sopcode struct pixrect *cset_pr;
23317288Sopcode struct pixrect *scratch_pr;
23417288Sopcode struct pixrect *retained_pr;
23517288Sopcode 
23617288Sopcode /*
23717288Sopcode  * This routine prints an error message in the text subwindow.
23817288Sopcode  */
error(s)23917288Sopcode error(s)
24017288Sopcode char *s;
24117288Sopcode {
24217288Sopcode     TxPutMsg(s);
24317288Sopcode }
24417288Sopcode 
24517288Sopcode 
main(argc,argv)24617288Sopcode main(argc, argv)
24717288Sopcode int argc;
24817288Sopcode char *argv[];
24917288Sopcode {
25017288Sopcode     char *arg, *file, *gremlinrc, *usage;
25117288Sopcode 
25217288Sopcode     file = "";
25317288Sopcode     gremlinrc = "";
254*17649Sopcode     usage = "usage: gremlin [-o] [-s <.gremlinrc>] [file]\n";
25517288Sopcode 
25617288Sopcode     while (--argc > 0) {
25717288Sopcode 	arg = *++argv;
25817288Sopcode 	if (*arg != '-')
25917288Sopcode 	    file = arg;
26017288Sopcode 	else {
26117288Sopcode 	    switch (*++arg) {
26217288Sopcode 		case 's':
26317288Sopcode 		    if (*++arg == '\0')
26417288Sopcode 			if (--argc > 0)
26517288Sopcode 			    arg = *++argv;
26617288Sopcode 		    if (argc < 0) {
26717288Sopcode 			printf("%s", usage);
26817288Sopcode 			exit(1);
26917288Sopcode 		    }
27017288Sopcode 		    gremlinrc = arg;
27117288Sopcode 		    break;
272*17649Sopcode 		case 'o':
273*17649Sopcode 		    newfileformat = 0;
27417288Sopcode 		    break;
27517288Sopcode 		default:
27617288Sopcode 		    printf("%s", usage);
27717288Sopcode 		    exit(1);
27817288Sopcode 	    }
27917288Sopcode 	}
28017288Sopcode     }
28117288Sopcode 
28217288Sopcode     strcpy(namestripe, version);
28317288Sopcode     tool = tool_create(namestripe, TOOL_NAMESTRIPE, (struct rect *) NULL,
284*17649Sopcode 			&gremlin_icon /*(struct icon *) NULL*/);
28517288Sopcode     if (tool == (struct tool *) NULL)
28617288Sopcode 	exit(1);
28717288Sopcode 
28817288Sopcode     text_sw = tool_createsubwindow(tool, "text_sw", TOOL_SWEXTENDTOEDGE,
28917288Sopcode 					TEXTSW_HEIGHT);
29017288Sopcode 
29117288Sopcode     menu_sw = tool_createsubwindow(tool, "menu_sw",
29217288Sopcode 					MENUSW_WIDTH, TOOL_SWEXTENDTOEDGE);
29317288Sopcode 
29417288Sopcode     pix_sw = tool_createsubwindow(tool, "pix_sw", TOOL_SWEXTENDTOEDGE,
29517288Sopcode 						TOOL_SWEXTENDTOEDGE);
29617288Sopcode 
29717288Sopcode     if ((text_sw == (struct toolsw *)NULL) ||
29817288Sopcode 		(menu_sw == (struct toolsw *)NULL) ||
29917288Sopcode 			(pix_sw == (struct toolsw *)NULL)) {
30017288Sopcode 	printf("error creating subwindows\n");
30117288Sopcode 	exit(1);
30217288Sopcode     }
30317288Sopcode 
30417288Sopcode     init_tool();
30517288Sopcode     init_text();
30617288Sopcode     init_menu();
30717288Sopcode     init_pix();
30817288Sopcode 
30917288Sopcode     /* set up gremlin variables */
31017288Sopcode     main_init(file, gremlinrc);
31117288Sopcode 
31217288Sopcode     /* install tool in tree of windows */
31317288Sopcode     signal(SIGWINCH, sigwinched);
31417288Sopcode     tool_install(tool);
31517288Sopcode     TOOLINSTALLED = 1;
31617288Sopcode 
31717288Sopcode     /* if current set flash off period non-zero, set up SIGALRM */
31817288Sopcode     if ((timeoff_ms != 0l) || (timeoff_s != 0l)) {
31917288Sopcode 	signal(SIGALRM, alrm_sighandler);
32017288Sopcode 	itime.it_interval.tv_sec = itime.it_value.tv_sec = timeon_s;
32117288Sopcode 	itime.it_interval.tv_usec = itime.it_value.tv_usec = timeon_ms * 1000;
32217288Sopcode 	setitimer(ITIMER_REAL, &itime, (struct itimerval *) NULL);
32317288Sopcode     }
32417288Sopcode 
32517288Sopcode     /* handle input */
32617288Sopcode     tool_select(tool, 0);
32717288Sopcode 
32817288Sopcode     /* cleanup */
32917288Sopcode     tool_destroy(tool);
33017288Sopcode     exit(0);
33117288Sopcode }
33217288Sopcode 
33317288Sopcode 
33417288Sopcode /*
33517288Sopcode  * Set input mask for the tool border.
33617288Sopcode  */
33717288Sopcode static
set_tool_input()33817288Sopcode set_tool_input()
33917288Sopcode {
34017288Sopcode     struct inputmask im;
34117288Sopcode 
34217288Sopcode     input_imnull(&im);
34317288Sopcode     win_setinputcodebit(&im, MS_LEFT);
34417288Sopcode     win_setinputcodebit(&im, MS_MIDDLE);
34517288Sopcode     win_setinputcodebit(&im, MS_RIGHT);
34617288Sopcode     win_setinputcodebit(&im, LOC_STILL);
34717288Sopcode 
34817288Sopcode     win_setinputmask(tool_fd, &im, NULL, WIN_NULLLINK);
34917288Sopcode }
35017288Sopcode 
35117288Sopcode 
35217288Sopcode static
init_tool()35317288Sopcode init_tool()
35417288Sopcode {
35517288Sopcode     tool_fd = tool->tl_windowfd;
35617288Sopcode     tool->tl_io.tio_selected = tool_selected;
35717288Sopcode 
35817288Sopcode     set_tool_input();
35917288Sopcode 
36017288Sopcode     if ((rootfd = open("/dev/win0", 0)) == -1) {
36117288Sopcode 	printf("can't open root window\n");
36217288Sopcode 	exit(1);
36317288Sopcode     }
36417288Sopcode 
36517288Sopcode     fix_tool_size();
36617288Sopcode }
36717288Sopcode 
36817288Sopcode 
36917288Sopcode /*
37017288Sopcode  * Set the size of the entire gremlin window.
37117288Sopcode  */
fix_tool_size()37217288Sopcode fix_tool_size()
37317288Sopcode {
374*17649Sopcode     struct rect icon_rect;
375*17649Sopcode 
37617288Sopcode     if (wmgr_iswindowopen(tool_fd))
37717288Sopcode 	win_getrect(tool_fd, &tool_size);
37817288Sopcode     else
37917288Sopcode 	win_getsavedrect(tool_fd, &tool_size);
38017288Sopcode 
38117288Sopcode     tool_size.r_width = 2 * tool_borderwidth(tool) +
38217288Sopcode 			    tool_subwindowspacing(tool) +
38317288Sopcode 			    MENUSW_WIDTH + PIXSW_WIDTH;
38417288Sopcode     tool_size.r_height = tool_stripeheight(tool) + tool_borderwidth(tool) +
38517288Sopcode 			    tool_subwindowspacing(tool) +
38617288Sopcode 			    2 +	/* don't know why */
38717288Sopcode 			    TEXTSW_HEIGHT + PIXSW_HEIGHT;
38817288Sopcode 
38917288Sopcode     /* don't allow window to open in lower left corner */
39017288Sopcode     if (tool_size.r_left < 100)
39117288Sopcode 	tool_size.r_left = 100;
39217288Sopcode     if (rect_bottom(&tool_size) >= 700)
39317288Sopcode 	tool_size.r_top -= rect_bottom(&tool_size) - 699;
39417288Sopcode 
395*17649Sopcode     /* land icon near upper left corner */
396*17649Sopcode     icon_rect.r_left = 0;
397*17649Sopcode     icon_rect.r_top = 64;
398*17649Sopcode     icon_rect.r_width = 64;
399*17649Sopcode     icon_rect.r_height = 64;
400*17649Sopcode 
401*17649Sopcode     if (wmgr_iswindowopen(tool_fd)) {
40217288Sopcode 	win_setrect(tool_fd, &tool_size);
403*17649Sopcode 	win_setsavedrect(tool_fd, &icon_rect);
404*17649Sopcode     }
405*17649Sopcode     else {
406*17649Sopcode 	win_setrect(tool_fd, &icon_rect);
40717288Sopcode 	win_setsavedrect(tool_fd, &tool_size);
408*17649Sopcode     }
40917288Sopcode }
41017288Sopcode 
41117288Sopcode 
41217288Sopcode static
init_text()41317288Sopcode init_text()
41417288Sopcode {
41517288Sopcode     struct inputmask im;
41617288Sopcode 
41717288Sopcode     text_fd = text_sw->ts_windowfd;
41817288Sopcode     text_pw = pw_open(text_fd);
41917288Sopcode 
42017288Sopcode     text_sw->ts_io.tio_handlesigwinch = text_sighandler;
42117288Sopcode     text_sw->ts_io.tio_selected = text_selected;
42217288Sopcode 
42317288Sopcode     win_setcursor(text_fd, &kbd_cursor);
42417288Sopcode 
42517288Sopcode     input_imnull(&im);
42617288Sopcode     win_setinputcodebit(&im, MS_LEFT);
42717288Sopcode     win_setinputcodebit(&im, MS_MIDDLE);
42817288Sopcode     win_setinputcodebit(&im, MS_RIGHT);
42917288Sopcode     win_setinputcodebit(&im, LOC_STILL);
43017288Sopcode     win_setinputcodebit(&im, LOC_WINEXIT);
43117288Sopcode 
43217288Sopcode     im.im_flags |= IM_ASCII;
43317288Sopcode     win_setinputmask(text_fd, &im, NULL, WIN_NULLLINK);
43417288Sopcode }
43517288Sopcode 
43617288Sopcode 
43717288Sopcode static
init_menu()43817288Sopcode init_menu()
43917288Sopcode {
44017288Sopcode     struct inputmask im;
44117288Sopcode 
44217288Sopcode     menu_fd = menu_sw->ts_windowfd;
44317288Sopcode     menu_pw = pw_open(menu_fd);
44417288Sopcode 
44517288Sopcode     menu_sw->ts_io.tio_handlesigwinch = menu_sighandler;
44617288Sopcode     menu_sw->ts_io.tio_selected = menu_selected;
44717288Sopcode 
44817288Sopcode     win_setcursor(menu_fd, &menu_cursor);
44917288Sopcode 
45017288Sopcode     input_imnull(&im);
45117288Sopcode     win_setinputcodebit(&im, MS_LEFT);
45217288Sopcode     win_setinputcodebit(&im, MS_MIDDLE);
45317288Sopcode     win_setinputcodebit(&im, MS_RIGHT);
45417288Sopcode     win_setinputcodebit(&im, LOC_MOVE);
45517288Sopcode     win_setinputcodebit(&im, LOC_WINEXIT);
45617288Sopcode     win_setinputcodebit(&im, LOC_STILL);
45717288Sopcode 
45817288Sopcode     im.im_flags |= IM_ASCII;
45917288Sopcode     win_setinputmask(menu_fd, &im, NULL, WIN_NULLLINK);
46017288Sopcode }
46117288Sopcode 
46217288Sopcode 
46317288Sopcode static
init_pix()46417288Sopcode init_pix()
46517288Sopcode {
46617288Sopcode     struct inputmask im;
46717288Sopcode     struct fbtype fb;
46817288Sopcode     struct mpr_data *md;
46917288Sopcode     int height, width;
47017288Sopcode     int fd;
47117288Sopcode 
47217288Sopcode     pix_fd = pix_sw->ts_windowfd;
47317288Sopcode     pix_pw = pw_open(pix_fd);
47417288Sopcode 
47517288Sopcode     pix_sw->ts_io.tio_handlesigwinch = pix_sighandler;
47617288Sopcode     pix_sw->ts_io.tio_selected = pix_selected;
47717288Sopcode 
47817288Sopcode     win_setcursor(pix_fd, &main_cursor);
47917288Sopcode 
48017288Sopcode     input_imnull(&im);
48117288Sopcode     win_setinputcodebit(&im, MS_LEFT);
48217288Sopcode     win_setinputcodebit(&im, MS_MIDDLE);
48317288Sopcode     win_setinputcodebit(&im, MS_RIGHT);
48417288Sopcode     win_setinputcodebit(&im, LOC_STILL);
48517288Sopcode     win_setinputcodebit(&im, LOC_WINEXIT);
48617288Sopcode 
48717288Sopcode     im.im_flags |= IM_ASCII;
48817288Sopcode     win_setinputmask(pix_fd, &im, NULL, WIN_NULLLINK);
48917288Sopcode 
49017288Sopcode     /* determine screen physical dimensions */
49117288Sopcode     if ((fd = open(DEV_FB, 1)) < 0) {		/* must be open for writing */
49217288Sopcode 	printf("init_pix: can't open %s\n", DEV_FB);
49317288Sopcode 	exit(1);
49417288Sopcode     }
49517288Sopcode 
49617288Sopcode     /* get frame buffer characteristics */
49717288Sopcode     if (ioctl(fd, FBIOGTYPE, (char *) &fb) < 0) {
49817288Sopcode 	printf("init_pix: ioctl (FBIOGTYPE)\n");
49917288Sopcode 	exit(1);
50017288Sopcode     }
50117288Sopcode     close(fd);
50217288Sopcode 
50317288Sopcode     /* determine maximum physical size of picture subwindow */
50417288Sopcode     height = fb.fb_height - TEXTSW_HEIGHT -
50517288Sopcode 			    tool_stripeheight(tool) -
50617288Sopcode 			    tool_borderwidth(tool) -
50717288Sopcode 			    tool_subwindowspacing(tool);
50817288Sopcode     width = fb.fb_width - MENUSW_WIDTH -
50917288Sopcode 			    tool_subwindowspacing(tool) -
51017288Sopcode 			    tool_borderwidth(tool) * 2;
51117288Sopcode 
51217288Sopcode     /* create pixrect for retaining image of current set */
51317288Sopcode     cset_pr = mem_create(width, height, 1);
51417288Sopcode     if (cset_pr == NULL) {
51517288Sopcode 	printf("can't create cset_pr\n");
51617288Sopcode 	exit(1);
51717288Sopcode     }
51817288Sopcode 
51917288Sopcode     /* create pixrect to do all element drawing in memory (faster) */
52017288Sopcode     scratch_pr = mem_create(width, height, 1);
52117288Sopcode     if (scratch_pr == NULL) {
52217288Sopcode 	printf("can't create scratch_pr\n");
52317288Sopcode 	exit(1);
52417288Sopcode     }
52517288Sopcode 
52617288Sopcode #ifdef RETAIN
52717288Sopcode     /* create retained pixrect for picture subwindow */
52817288Sopcode     retained_pr = mem_create(width, height, 1);
52917288Sopcode     if (retained_pr == (struct pixrect *) NULL) {
53017288Sopcode 	printf("can't create retained_pr\n");
53117288Sopcode 	exit(1);
53217288Sopcode     }
53317288Sopcode 
53417288Sopcode     /* add retained pixrect to the pix subwindow pixwin */
53517288Sopcode     pix_pw->pw_prretained = retained_pr;
53617288Sopcode 
53717288Sopcode     /*
53817288Sopcode      * The pix subwindow width and height MUST be initialized before
53917288Sopcode      * any drawing can take place when using a retained pixrect.
54017288Sopcode      * The display routine DISScreenAdd() uses these dimensions to
54117288Sopcode      * minimize the area of the mem_pixrect (scratch_pr) which must
54217288Sopcode      * be cleared prior to drawing an element and is called via
54317288Sopcode      * SHUpdate() at the end of main_init().
54417288Sopcode      */
54517288Sopcode     pix_size.r_width = PIXSW_WIDTH;
54617288Sopcode     pix_size.r_height = PIXSW_HEIGHT;
54717288Sopcode #endif
54817288Sopcode 
54917288Sopcode #ifdef maybefaster
55017288Sopcode     md = (struct mpr_data *) scratch_pr->pr_data;
55117288Sopcode     _image = (char *) md->md_image;
55217288Sopcode     _bytesperline = md->md_linebytes;
55317288Sopcode     _maxx = _bytesperline << 3;
55417288Sopcode     _maxy = scratch_pr->pr_size.y;
55517288Sopcode #endif
55617288Sopcode }
55717288Sopcode 
55817288Sopcode 
55917288Sopcode /*
56017288Sopcode  * This routine catches the normal tool manager quit menuitem
56117288Sopcode  * and handles it slightly differently if no write has occurred
56217288Sopcode  * since the last change to the picture.
56317288Sopcode  * WARNING: this routine depends upon menu_display() returning
564*17649Sopcode  * mi->mi_data = 2 for the QUIT menuitem and
565*17649Sopcode  * mi->mi_data = 1 for the REDISPLAY menuitem.
56617288Sopcode  */
56717288Sopcode static
tool_selected(nullsw,ibits,obits,ebits,timer)56817288Sopcode tool_selected(nullsw, ibits, obits, ebits, timer)
56917288Sopcode caddr_t *nullsw;
57017288Sopcode int *ibits, *obits, *ebits;
57117288Sopcode struct timeval **timer;
57217288Sopcode {
57317288Sopcode     struct inputevent ie;
57417288Sopcode     struct inputmask im;
57517288Sopcode     struct menuitem *mi;
57617288Sopcode 
57717288Sopcode     if (input_readevent(tool_fd, &ie) < 0) {
57817288Sopcode 	printf("error: tool_selected()\n");
57917288Sopcode 	return;
58017288Sopcode     }
58117288Sopcode 
58217288Sopcode     switch (ie.ie_code) {
58317288Sopcode 	case LOC_STILL:
58417288Sopcode /*	    GRCurrentSetOn();			*/
58517288Sopcode 	    break;
58617288Sopcode 	case MS_LEFT:
58717288Sopcode 	    if (wmgr_iswindowopen(tool_fd))
58817288Sopcode 		wmgr_top(tool_fd, rootfd);
58917288Sopcode 	    else
59017288Sopcode 		wmgr_open(tool_fd, rootfd);
59117288Sopcode 	    break;
59217288Sopcode 	case MS_MIDDLE:
59317288Sopcode 	    wmgr_changerect(tool_fd, tool_fd, &ie, 1, 1);
59417288Sopcode 	    break;
59517288Sopcode 	case MS_RIGHT:
59617288Sopcode 	    /* force mouse button input only for pop-up menu */
59717288Sopcode 	    input_imnull(&im);
59817288Sopcode 	    win_setinputcodebit(&im, MS_LEFT);
59917288Sopcode 	    win_setinputcodebit(&im, MS_MIDDLE);
60017288Sopcode 	    win_setinputcodebit(&im, MS_RIGHT);
60117288Sopcode 	    win_setinputmask(tool_fd, &im, NULL, WIN_NULLLINK);
60217288Sopcode 
60317288Sopcode 	    wmgr_setupmenu(tool_fd);
60417288Sopcode 	    mi = menu_display(&wmgr_toolmenu, &ie, tool_fd);
60517288Sopcode 	    if (mi == (struct menuitem *) NULL)
60617288Sopcode 		break;
60717288Sopcode 
608*17649Sopcode 	    if (((int) mi->mi_data == 1)		/* REDISPLAY !! */
609*17649Sopcode 			    && wmgr_iswindowopen(tool_fd))
610*17649Sopcode 		SHUpdate();
611*17649Sopcode 	    else if ((int) mi->mi_data == 2) 		/* QUIT !! */
612*17649Sopcode 		LGQuit();
61317288Sopcode 	    else
61417288Sopcode 		wmgr_handletoolmenuitem(wmgr_toolmenu, mi, tool_fd, rootfd);
61517288Sopcode 
61617288Sopcode 	    set_tool_input();	/* reset tool input */
61717288Sopcode 	    break;
61817288Sopcode     }
61917288Sopcode 
62017288Sopcode     *ibits = *obits = *ebits = 0;
62117288Sopcode }
62217288Sopcode 
62317288Sopcode 
62417288Sopcode static
text_selected(nullsw,ibits,obits,ebits,timer)62517288Sopcode text_selected(nullsw, ibits, obits, ebits, timer)
62617288Sopcode caddr_t *nullsw;
62717288Sopcode int *ibits, *obits, *ebits;
62817288Sopcode struct timeval **timer;
62917288Sopcode {
63017288Sopcode     struct inputevent ie;
63117288Sopcode 
63217288Sopcode     if (input_readevent(text_fd, &ie) < 0) {
63317288Sopcode 	printf("error: text_selected()\n");
63417288Sopcode 	return;
63517288Sopcode     }
63617288Sopcode 
63717288Sopcode     switch (ie.ie_code) {
63817288Sopcode 	case LOC_STILL:
63917288Sopcode 	    check_cset();
64017288Sopcode 	    break;
64117288Sopcode 	case MS_LEFT:
642*17649Sopcode 	    text_left(&ie);
643*17649Sopcode 	    break;
64417288Sopcode 	case MS_MIDDLE:
645*17649Sopcode 	    text_middle(&ie);
64617288Sopcode 	    break;
64717288Sopcode 	case MS_RIGHT:
64817288Sopcode 	    text_right(&ie);
64917288Sopcode 	    break;
65017288Sopcode 	case LOC_WINEXIT:
65117288Sopcode 	    text_winexit(&ie);
65217288Sopcode 	    break;
65317288Sopcode 	default:
65417288Sopcode 	    if ((ie.ie_code <= ASCII_LAST) && (ie.ie_code >= ASCII_FIRST))
65517288Sopcode 		text_output(ie.ie_code);
65617288Sopcode 	    break;
65717288Sopcode     }
65817288Sopcode 
65917288Sopcode     *ibits = *obits = *ebits = 0;
66017288Sopcode }
66117288Sopcode 
66217288Sopcode 
66317288Sopcode static
menu_selected(nullsw,ibits,obits,ebits,timer)66417288Sopcode menu_selected(nullsw, ibits, obits, ebits, timer)
66517288Sopcode caddr_t *nullsw;
66617288Sopcode int *ibits, *obits, *ebits;
66717288Sopcode struct timeval **timer;
66817288Sopcode {
66917288Sopcode     struct inputevent ie;
67017288Sopcode     char shcmd[2];
67117288Sopcode 
67217288Sopcode     if (input_readevent(menu_fd, &ie) < 0) {
67317288Sopcode 	printf("error: menu_selected()\n");
67417288Sopcode 	return;
67517288Sopcode     }
67617288Sopcode 
67717288Sopcode     switch (ie.ie_code) {
67817288Sopcode 	case LOC_MOVE:
67917288Sopcode 	    mouse_move(&ie);
68017288Sopcode 	    break;
68117288Sopcode 	case LOC_STILL:
68217288Sopcode 	    check_cset();
68317288Sopcode 	    break;
68417288Sopcode 	case MS_LEFT:
68517288Sopcode 	    menu_left(&ie);
68617288Sopcode 	    break;
68717288Sopcode 	case MS_MIDDLE:
68817288Sopcode 	    menu_middle(&ie);
68917288Sopcode 	    break;
69017288Sopcode 	case MS_RIGHT:
69117288Sopcode 	    menu_right(&ie);
69217288Sopcode 	    break;
69317288Sopcode 	case LOC_WINEXIT:
69417288Sopcode 	    menu_winexit(&ie);
69517288Sopcode 	    break;
69617288Sopcode 	default:
69717288Sopcode 	    if ((ie.ie_code <= ASCII_LAST) && (ie.ie_code >= ASCII_FIRST)) {
698*17649Sopcode 		if ((shcmd[0] = ie.ie_code) != '.')
699*17649Sopcode 		    lasttext = FALSE;
70017288Sopcode 		shcmd[1] = '\0';
70117288Sopcode 		SHCommand(shcmd);
70217288Sopcode 	    }
70317288Sopcode 	    break;
70417288Sopcode     }
70517288Sopcode 
70617288Sopcode     *ibits = *obits = *ebits = 0;
70717288Sopcode }
70817288Sopcode 
70917288Sopcode 
71017288Sopcode static
pix_selected(nullsw,ibits,obits,ebits,timer)71117288Sopcode pix_selected(nullsw, ibits, obits, ebits, timer)
71217288Sopcode caddr_t *nullsw;
71317288Sopcode int *ibits, *obits, *ebits;
71417288Sopcode struct timeval **timer;
71517288Sopcode {
71617288Sopcode     struct inputevent ie;
71717288Sopcode     char shcmd[2];
71817288Sopcode 
71917288Sopcode     if (input_readevent(pix_fd, &ie) < 0) {
72017288Sopcode 	printf("error: pix_selected()\n");
72117288Sopcode 	return;
72217288Sopcode     }
72317288Sopcode 
72417288Sopcode     switch (ie.ie_code) {
72517288Sopcode 	case LOC_STILL:
72617288Sopcode 	    check_cset();
72717288Sopcode 	    break;
72817288Sopcode 	case MS_LEFT:
72917288Sopcode 	    pix_left(&ie);
73017288Sopcode 	    break;
73117288Sopcode 	case MS_MIDDLE:
73217288Sopcode 	    pix_middle(&ie);
73317288Sopcode 	    break;
73417288Sopcode 	case MS_RIGHT:
73517288Sopcode 	    pix_right(&ie);
73617288Sopcode 	    break;
73717288Sopcode 	case LOC_WINEXIT:
73817288Sopcode 	    pix_winexit(&ie);
73917288Sopcode 	    break;
74017288Sopcode 	default:
74117288Sopcode 	    if ((ie.ie_code <= ASCII_LAST) && (ie.ie_code >= ASCII_FIRST)) {
742*17649Sopcode 		if ((shcmd[0] = ie.ie_code) != '.')
743*17649Sopcode 		    lasttext = FALSE;
74417288Sopcode 		shcmd[1] = '\0';
74517288Sopcode 		SHCommand(shcmd);
74617288Sopcode 	    }
74717288Sopcode 	    break;
74817288Sopcode     }
74917288Sopcode 
75017288Sopcode     *ibits = *obits = *ebits = 0;
75117288Sopcode }
75217288Sopcode 
75317288Sopcode 
75417288Sopcode static
sigwinched()75517288Sopcode sigwinched()
75617288Sopcode {
75717288Sopcode     tool_sigwinch(tool);
75817288Sopcode 
75917288Sopcode     win_getrect(tool_fd, &tool_size);
76017288Sopcode     /*
76117288Sopcode     printf("tool: left %d, top %d, width %d, height %d\n", tool_size.r_left,
76217288Sopcode 	tool_size.r_top, tool_size.r_width, tool_size.r_height);
76317288Sopcode     */
76417288Sopcode }
76517288Sopcode 
76617288Sopcode 
76717288Sopcode static
text_sighandler()76817288Sopcode text_sighandler()
76917288Sopcode {
77017288Sopcode     pw_damaged(text_pw);
77117288Sopcode 
77217288Sopcode     win_getrect(text_fd, &text_size);
77317288Sopcode     pw_writebackground(text_pw, 0, 0, 1024, 1024, PIX_SRC);
77417288Sopcode     text_putvalue();
77517288Sopcode 
77617288Sopcode     pw_donedamaged(text_pw);
77717288Sopcode }
77817288Sopcode 
77917288Sopcode 
78017288Sopcode static
menu_sighandler()78117288Sopcode menu_sighandler()
78217288Sopcode {
78317288Sopcode     pw_damaged(menu_pw);
78417288Sopcode 
78517288Sopcode     win_getrect(menu_fd, &menu_size);
78617288Sopcode     pw_writebackground(menu_pw, 0, 0, 1024, 1024, PIX_SRC);
78717288Sopcode     MNDisplayMenu();
78817288Sopcode     /*
78917288Sopcode     printf("menu: left %d, top %d, width %d, height %d\n", menu_size.r_left,
79017288Sopcode 	menu_size.r_top, menu_size.r_width, menu_size.r_height);
79117288Sopcode     */
79217288Sopcode 
79317288Sopcode     pw_donedamaged(menu_pw);
79417288Sopcode }
79517288Sopcode 
79617288Sopcode 
79717288Sopcode static
pix_sighandler()79817288Sopcode pix_sighandler()
79917288Sopcode {
80017288Sopcode     GRCurrentSetOn();	/* make current set on */
80117288Sopcode     pw_damaged(pix_pw);
80217288Sopcode 
80317288Sopcode     if (STERROR) {	/* check for startup error reading .gremlinrc */
80417288Sopcode 	TxPutMsg("error in .gremlinrc");
80517288Sopcode 	STERROR = 0;
80617288Sopcode     }
80717288Sopcode 
80817288Sopcode     win_getrect(pix_fd, &pix_size);
80917288Sopcode 
81017288Sopcode #ifdef RETAIN
81117288Sopcode     pw_repairretained(pix_pw);
81217288Sopcode #else
81317288Sopcode     SHUpdate();
81417288Sopcode #endif
81517288Sopcode 
81617288Sopcode     pw_donedamaged(pix_pw);
81717288Sopcode }
81817288Sopcode 
81917288Sopcode 
82017288Sopcode /*
82117288Sopcode  *  One time only start-up initialization.
82217288Sopcode  */
main_init(file,gremlinrc)82317288Sopcode main_init(file, gremlinrc)
82417288Sopcode char *file;
82517288Sopcode char *gremlinrc;
82617288Sopcode {
82717288Sopcode     FILE *fp;
82817288Sopcode     POINT *pos;
82917288Sopcode     int i, fd;
83017288Sopcode     char *prealname;
83117288Sopcode 
83217288Sopcode     signal(SIGINT, SIG_IGN);			/* ignore interrupts */
83317288Sopcode     TxInit();					/* text subwindow init */
83417288Sopcode     MNInitMenu();				/* menu subwindow init */
83517288Sopcode     PSetPath(".");				/* file search path */
83617288Sopcode     Editfile = malloc(128);			/* current picture name */
83717288Sopcode 
83817288Sopcode     POINTLIST = PTInit();			/* drawing points */
83917288Sopcode     BACKPOINT = PTInit();			/* backup point list */
84017288Sopcode 
84117288Sopcode     PICTURE = DBInit();				/* picture database */
84217288Sopcode     cset = DBInit();				/* current set */
84317288Sopcode     for (i=0; i<4; ++i)				/* set buffers */
84417288Sopcode 	MEN[i] = DBInit();
84517288Sopcode 
84617288Sopcode     unlist = unback = NULL;			/* undo pointers */
84717288Sopcode     make_arrowhead();				/* for > command */
848*17649Sopcode     lastcommand = nop;				/* no last command yet */
84917288Sopcode 
85017288Sopcode     STgremlinrc(gremlinrc);			/* .gremlinrc processing */
85117288Sopcode     GRFontInit();	       /* must be called after CSIZE & CFONT set */
85217288Sopcode 
85317288Sopcode     strcpy(Editfile, file);			/* find edit file */
85417288Sopcode     if (*file != '\0') {
85517288Sopcode 	fp = POpen(Editfile, &prealname, SEARCH);
85617288Sopcode 
85717288Sopcode 	if (fp == NULL) {
85817288Sopcode 	    strcat(namestripe, file);
85917288Sopcode 	    error("creating new file");
86017288Sopcode 	}
86117288Sopcode 	else {
86217288Sopcode 	    fclose(fp);
86317288Sopcode 	    strcat(namestripe, prealname);
86417288Sopcode 	    PICTURE = DBRead(Editfile, &Orientation, &pos);
86517288Sopcode 	    if ((fd = open(prealname, O_WRONLY | O_APPEND)) < 0)
86617288Sopcode 		strcat(namestripe, " (read only)");
86717288Sopcode 	    else
86817288Sopcode 		close(fd);
86917288Sopcode 	}
87017288Sopcode     }
87117288Sopcode     else {
87217288Sopcode 	strcat(namestripe, "new file");
87317288Sopcode     }
87417288Sopcode 
87517288Sopcode #ifdef RETAIN
87617288Sopcode     /*
87717288Sopcode      * Update pix subwindow now so that the retained pixrect is set before
87817288Sopcode      * the first SIGWINCH.
87917288Sopcode      */
88017288Sopcode     SHUpdate();
88117288Sopcode #endif
88217288Sopcode }  /* end main_init */
88317288Sopcode 
88417288Sopcode 
88517288Sopcode /*
88617288Sopcode  *  Make arrowhead element for later drawing.
88717288Sopcode  */
make_arrowhead()88817288Sopcode make_arrowhead()
88917288Sopcode {
89017288Sopcode     POINT *pos;
89117288Sopcode 
89217288Sopcode     pos = PTInit();			/* initialize arrowhead template */
89317288Sopcode     (void) PTMakePoint(0.0, 0.0, &pos);
89417288Sopcode     (void) PTMakePoint(-5.51, 3.51, &pos);
89517288Sopcode     (void) PTMakePoint(-3.51, 0.0, &pos);
89617288Sopcode     (void) PTMakePoint(-5.51, -3.51, &pos);
89717288Sopcode     (void) PTMakePoint(0.0, 0.0, &pos);
89817288Sopcode     arhead.type = VECTOR;
89917288Sopcode     arhead.ptlist = pos;
90017288Sopcode     arhead.brushf = 0;			/* brush filled in when used */
90117288Sopcode     arhead.size = 0;
90217288Sopcode     arhead.textpt = malloc(1);
90317288Sopcode     *(arhead.textpt) = '\0';
90417288Sopcode }
90517288Sopcode 
90617288Sopcode 
90717288Sopcode /*
90817288Sopcode  * Nothing has happened for a while, so check to see if its time
90917288Sopcode  * to flash the current set.  If so, set the SIGALRM timer for the
91017288Sopcode  * appropriate period.
91117288Sopcode  */
check_cset()91217288Sopcode check_cset()
91317288Sopcode {
914*17649Sopcode     if (FLASH_READY /*&& wmgr_iswindowopen(tool_fd) */) {
91517288Sopcode 	GRCurrentSet();				/* XOR current set */
91617288Sopcode 
91717288Sopcode 	if (CsetOn) {				/* set off period */
91817288Sopcode 	    itime.it_interval.tv_sec =
91917288Sopcode 	    itime.it_value.tv_sec = timeon_s;
92017288Sopcode 	    itime.it_interval.tv_usec =
92117288Sopcode 	    itime.it_value.tv_usec = timeon_ms * 1000;
92217288Sopcode 	}
92317288Sopcode 	else {					/* set on period */
92417288Sopcode 	    itime.it_interval.tv_sec =
92517288Sopcode 	    itime.it_value.tv_sec = timeoff_s;
92617288Sopcode 	    itime.it_interval.tv_usec =
92717288Sopcode 	    itime.it_value.tv_usec = timeoff_ms * 1000;
92817288Sopcode 	}
92917288Sopcode 
93017288Sopcode 	setitimer(ITIMER_REAL, &itime, NULL);
93117288Sopcode 	FLASH_READY = 0;
93217288Sopcode     }
93317288Sopcode }
93417288Sopcode 
93517288Sopcode 
93617288Sopcode /*
93717288Sopcode  * This routine handles the timer signals indicating that it is time
93817288Sopcode  * to flash the current set.  Since the screen may not be in a consistent
93917288Sopcode  * state, we simply set the FLASH_READY flag and return.  When a LOC_STILL
94017288Sopcode  * input event arrives later, this flag will be checked and the current
94117288Sopcode  * set flashed then.
94217288Sopcode  */
94317288Sopcode static
alrm_sighandler()94417288Sopcode alrm_sighandler()
94517288Sopcode {
94617288Sopcode     FLASH_READY = 1;
94717288Sopcode }
948