1 /*
2  * @(#)main.c	1.2	01/03/85
3  *
4  * Main program for the SUN Gremlin picture editor.
5  *
6  * Many of the routines in SUN Gremlin are direct descendants of
7  * their counterparts in the original Gremlin written for the AED
8  * by Barry Roitblat.
9  *
10  * Mark Opperman (opcode@monet.BERKELEY)
11  *
12  */
13 
14 #include <suntool/tool_hs.h>
15 #include <suntool/fullscreen.h>
16 #include <suntool/menu.h>
17 #include <suntool/wmgr.h>
18 #include <sunwindow/cms.h>
19 #include <sunwindow/win_ioctl.h>
20 #include <sun/fbio.h>
21 #include <sys/file.h>
22 #include <sys/ioctl.h>
23 #include <errno.h>
24 #include "gremlin.h"
25 #include "icondata.h"
26 
27 #define RETAIN TRUE		/* use retained subwindow for pix_sw */
28 
29 #ifdef maybefaster
30 char *_image;
31 int _bytesperline, _maxx, _maxy;
32 #endif
33 
34 /* database imports */
35 
36 extern ELT *DBRead();
37 extern POINT *PTMakePoint();
38 extern FILE *POpen();
39 
40 /* imports from startup.c */
41 
42 extern STERROR;
43 extern STgremlinrc();
44 
45 /* imports from menu.c */
46 
47 extern MNDisplayMenu();
48 extern MNInitMenu();
49 
50 /* graphics imports */
51 
52 extern GRBlankGrid();
53 extern GRCurrentSet();
54 extern GRCurrentSetOn();
55 extern GRDisplayGrid();
56 extern GRFontInit();
57 
58 /* imports from undodb.c */
59 
60 extern UNForget();
61 extern UNELT *unlist;
62 extern UNELT *unback;
63 
64 /* imports from long.c */
65 
66 extern SHOWPOINTS;
67 extern char *Editfile;
68 extern CP();
69 extern LGQuit();
70 extern nop();
71 
72 /* imports from short.c */
73 
74 extern SHCommand();
75 extern SHUpdate();
76 
77 /* imports from C */
78 
79 extern char *malloc();
80 extern char *sprintf();
81 extern char *strcat();
82 extern char *strcpy();
83 
84 /* imports from strings.c */
85 
86 extern char version[];
87 extern char GLibrary[];
88 
89 /* Declaration of Globals */
90 
91 ELT arhead;
92 ELT *cset;
93 ELT *MEN[NUSER];
94 ELT *PICTURE;
95 
96 POINT *BACKPOINT;
97 POINT MENPOINT[NUSER];
98 POINT *POINTLIST;
99 
100 int Artmode = FALSE;
101 int Adjustment = NOADJ;
102 int Alignment = 4;
103 int CBRUSH = 5;
104 int CFONT = 1;
105 int CJUST = 0;
106 int CSIZE = 1;
107 int CSTIPPLE = 1;
108 int GravityOn = FALSE;
109 int Gridon = FALSE;
110 int Gridsize = 32;
111 int Orientation;
112 int SEQ = 0;
113 int CHANGED = FALSE;
114 int SEARCH = TRUE;
115 int SymbolicLines = 0;
116 int newfileformat = 1;			/* 1=sungremlinfile, 0=gremlinfile */
117 int TOOLINSTALLED = 0;
118 int (*lastcommand)();			/* last command's routine pointer */
119 int lasttext = FALSE;			/* TRUE if last command uses text */
120 
121 float PX, PY;				/* user point coordinate */
122 float Lastx, Lasty;			/* last user point coordinate */
123 
124 long timeon_ms = 580;			/* current set flash on period */
125 long timeon_s = 0;
126 long timeoff_ms = 180;			/* current set flash off period */
127 long timeoff_s = 0;
128 
129 int FLASH_READY = 0;			/* TRUE if time to flash current set */
130 int CsetOn = 1;				/* TRUE if current set displayed */
131 static struct itimerval itime;		/* for ALARM signals */
132 static alrm_sighandler();
133 
134 int SUN_XORIGIN = 0;			/* top left corner in gremlin coords */
135 int SUN_YORIGIN = 511;
136 
137 static char SccsId [] = "@(#)main.c	1.2   (Berkeley)      01/03/85";
138 
139 /* imports from menu.c */
140 
141 extern menu_left();
142 extern menu_middle();
143 extern menu_right();
144 extern menu_winexit();
145 extern mouse_move();
146 
147 
148 /* imports from pix.c */
149 
150 extern pix_left();
151 extern pix_middle();
152 extern pix_right();
153 extern pix_winexit();
154 
155 
156 /* imports from suntext.c */
157 
158 extern text_left();
159 extern text_middle();
160 extern text_right();
161 extern text_winexit();
162 extern text_putvalue();
163 extern text_output();
164 extern TxInit();
165 extern TxPutMsg();
166 
167 struct cursor kbd_cursor  =  {
168     4, 8, PIX_SRC^PIX_DST, &kbdcursor_pr
169 };
170 
171 struct cursor main_cursor  =  {
172     0, 0, PIX_SRC^PIX_DST, &uparrow_pr
173 };
174 
175 static struct cursor menu_cursor = {
176     3, 3, PIX_SRC^PIX_DST, &diamond_pr
177 };
178 
179 static struct icon gremlin_icon = {
180     TOOL_ICONWIDTH, TOOL_ICONHEIGHT, NULL,
181     {0, 0, TOOL_ICONWIDTH, TOOL_ICONHEIGHT},
182     &gremlin_icon_pr, {0, 0, 0, 0}, NULL, NULL, 0
183 };
184 
185 /* tool window stuff */
186 
187 #define DEV_FB "/dev/fb"
188 struct tool *tool;
189 struct rect tool_size;
190 int tool_fd;
191 int rootfd;
192 char namestripe[256];
193 static tool_selected();
194 static init_tool();
195 static sigwinched();
196 
197 /* for handling tool manager menu */
198 
199 extern struct menu *wmgr_toolmenu;
200 extern struct menuitem *menu_display();
201 
202 /* text subwindow */
203 
204 struct toolsw *text_sw;
205 struct pixwin *text_pw;
206 struct rect text_size;
207 int text_fd;
208 struct pixfont *text_pf;
209 static init_text();
210 static text_selected();
211 static text_sighandler();
212 
213 /* menu subwindow */
214 
215 struct toolsw *menu_sw;
216 struct pixwin *menu_pw;
217 struct rect menu_size;
218 int menu_fd;
219 static init_menu();
220 static menu_selected();
221 static menu_sighandler();
222 
223 /* pix subwindow */
224 
225 struct toolsw *pix_sw;
226 struct pixwin *pix_pw;
227 struct rect pix_size;
228 int pix_fd;
229 static init_pix();
230 static pix_selected();
231 static pix_sighandler();
232 struct pixrect *cset_pr;
233 struct pixrect *scratch_pr;
234 struct pixrect *retained_pr;
235 
236 /*
237  * This routine prints an error message in the text subwindow.
238  */
error(s)239 error(s)
240 char *s;
241 {
242     TxPutMsg(s);
243 }
244 
245 
main(argc,argv)246 main(argc, argv)
247 int argc;
248 char *argv[];
249 {
250     char *arg, *file, *gremlinrc, *usage;
251 
252     file = "";
253     gremlinrc = "";
254     usage = "usage: gremlin [-o] [-s <.gremlinrc>] [file]\n";
255 
256     while (--argc > 0) {
257 	arg = *++argv;
258 	if (*arg != '-')
259 	    file = arg;
260 	else {
261 	    switch (*++arg) {
262 		case 's':
263 		    if (*++arg == '\0')
264 			if (--argc > 0)
265 			    arg = *++argv;
266 		    if (argc < 0) {
267 			printf("%s", usage);
268 			exit(1);
269 		    }
270 		    gremlinrc = arg;
271 		    break;
272 		case 'o':
273 		    newfileformat = 0;
274 		    break;
275 		default:
276 		    printf("%s", usage);
277 		    exit(1);
278 	    }
279 	}
280     }
281 
282     strcpy(namestripe, version);
283     tool = tool_create(namestripe, TOOL_NAMESTRIPE, (struct rect *) NULL,
284 			&gremlin_icon /*(struct icon *) NULL*/);
285     if (tool == (struct tool *) NULL)
286 	exit(1);
287 
288     text_sw = tool_createsubwindow(tool, "text_sw", TOOL_SWEXTENDTOEDGE,
289 					TEXTSW_HEIGHT);
290 
291     menu_sw = tool_createsubwindow(tool, "menu_sw",
292 					MENUSW_WIDTH, TOOL_SWEXTENDTOEDGE);
293 
294     pix_sw = tool_createsubwindow(tool, "pix_sw", TOOL_SWEXTENDTOEDGE,
295 						TOOL_SWEXTENDTOEDGE);
296 
297     if ((text_sw == (struct toolsw *)NULL) ||
298 		(menu_sw == (struct toolsw *)NULL) ||
299 			(pix_sw == (struct toolsw *)NULL)) {
300 	printf("error creating subwindows\n");
301 	exit(1);
302     }
303 
304     init_tool();
305     init_text();
306     init_menu();
307     init_pix();
308 
309     /* set up gremlin variables */
310     main_init(file, gremlinrc);
311 
312     /* install tool in tree of windows */
313     signal(SIGWINCH, sigwinched);
314     tool_install(tool);
315     TOOLINSTALLED = 1;
316 
317     /* if current set flash off period non-zero, set up SIGALRM */
318     if ((timeoff_ms != 0l) || (timeoff_s != 0l)) {
319 	signal(SIGALRM, alrm_sighandler);
320 	itime.it_interval.tv_sec = itime.it_value.tv_sec = timeon_s;
321 	itime.it_interval.tv_usec = itime.it_value.tv_usec = timeon_ms * 1000;
322 	setitimer(ITIMER_REAL, &itime, (struct itimerval *) NULL);
323     }
324 
325     /* handle input */
326     tool_select(tool, 0);
327 
328     /* cleanup */
329     tool_destroy(tool);
330     exit(0);
331 }
332 
333 
334 /*
335  * Set input mask for the tool border.
336  */
337 static
set_tool_input()338 set_tool_input()
339 {
340     struct inputmask im;
341 
342     input_imnull(&im);
343     win_setinputcodebit(&im, MS_LEFT);
344     win_setinputcodebit(&im, MS_MIDDLE);
345     win_setinputcodebit(&im, MS_RIGHT);
346     win_setinputcodebit(&im, LOC_STILL);
347 
348     win_setinputmask(tool_fd, &im, NULL, WIN_NULLLINK);
349 }
350 
351 
352 static
init_tool()353 init_tool()
354 {
355     tool_fd = tool->tl_windowfd;
356     tool->tl_io.tio_selected = tool_selected;
357 
358     set_tool_input();
359 
360     if ((rootfd = open("/dev/win0", 0)) == -1) {
361 	printf("can't open root window\n");
362 	exit(1);
363     }
364 
365     fix_tool_size();
366 }
367 
368 
369 /*
370  * Set the size of the entire gremlin window.
371  */
fix_tool_size()372 fix_tool_size()
373 {
374     struct rect icon_rect;
375 
376     if (wmgr_iswindowopen(tool_fd))
377 	win_getrect(tool_fd, &tool_size);
378     else
379 	win_getsavedrect(tool_fd, &tool_size);
380 
381     tool_size.r_width = 2 * tool_borderwidth(tool) +
382 			    tool_subwindowspacing(tool) +
383 			    MENUSW_WIDTH + PIXSW_WIDTH;
384     tool_size.r_height = tool_stripeheight(tool) + tool_borderwidth(tool) +
385 			    tool_subwindowspacing(tool) +
386 			    2 +	/* don't know why */
387 			    TEXTSW_HEIGHT + PIXSW_HEIGHT;
388 
389     /* don't allow window to open in lower left corner */
390     if (tool_size.r_left < 100)
391 	tool_size.r_left = 100;
392     if (rect_bottom(&tool_size) >= 700)
393 	tool_size.r_top -= rect_bottom(&tool_size) - 699;
394 
395     /* land icon near upper left corner */
396     icon_rect.r_left = 0;
397     icon_rect.r_top = 64;
398     icon_rect.r_width = 64;
399     icon_rect.r_height = 64;
400 
401     if (wmgr_iswindowopen(tool_fd)) {
402 	win_setrect(tool_fd, &tool_size);
403 	win_setsavedrect(tool_fd, &icon_rect);
404     }
405     else {
406 	win_setrect(tool_fd, &icon_rect);
407 	win_setsavedrect(tool_fd, &tool_size);
408     }
409 }
410 
411 
412 static
init_text()413 init_text()
414 {
415     struct inputmask im;
416 
417     text_fd = text_sw->ts_windowfd;
418     text_pw = pw_open(text_fd);
419 
420     text_sw->ts_io.tio_handlesigwinch = text_sighandler;
421     text_sw->ts_io.tio_selected = text_selected;
422 
423     win_setcursor(text_fd, &kbd_cursor);
424 
425     input_imnull(&im);
426     win_setinputcodebit(&im, MS_LEFT);
427     win_setinputcodebit(&im, MS_MIDDLE);
428     win_setinputcodebit(&im, MS_RIGHT);
429     win_setinputcodebit(&im, LOC_STILL);
430     win_setinputcodebit(&im, LOC_WINEXIT);
431 
432     im.im_flags |= IM_ASCII;
433     win_setinputmask(text_fd, &im, NULL, WIN_NULLLINK);
434 }
435 
436 
437 static
init_menu()438 init_menu()
439 {
440     struct inputmask im;
441 
442     menu_fd = menu_sw->ts_windowfd;
443     menu_pw = pw_open(menu_fd);
444 
445     menu_sw->ts_io.tio_handlesigwinch = menu_sighandler;
446     menu_sw->ts_io.tio_selected = menu_selected;
447 
448     win_setcursor(menu_fd, &menu_cursor);
449 
450     input_imnull(&im);
451     win_setinputcodebit(&im, MS_LEFT);
452     win_setinputcodebit(&im, MS_MIDDLE);
453     win_setinputcodebit(&im, MS_RIGHT);
454     win_setinputcodebit(&im, LOC_MOVE);
455     win_setinputcodebit(&im, LOC_WINEXIT);
456     win_setinputcodebit(&im, LOC_STILL);
457 
458     im.im_flags |= IM_ASCII;
459     win_setinputmask(menu_fd, &im, NULL, WIN_NULLLINK);
460 }
461 
462 
463 static
init_pix()464 init_pix()
465 {
466     struct inputmask im;
467     struct fbtype fb;
468     struct mpr_data *md;
469     int height, width;
470     int fd;
471 
472     pix_fd = pix_sw->ts_windowfd;
473     pix_pw = pw_open(pix_fd);
474 
475     pix_sw->ts_io.tio_handlesigwinch = pix_sighandler;
476     pix_sw->ts_io.tio_selected = pix_selected;
477 
478     win_setcursor(pix_fd, &main_cursor);
479 
480     input_imnull(&im);
481     win_setinputcodebit(&im, MS_LEFT);
482     win_setinputcodebit(&im, MS_MIDDLE);
483     win_setinputcodebit(&im, MS_RIGHT);
484     win_setinputcodebit(&im, LOC_STILL);
485     win_setinputcodebit(&im, LOC_WINEXIT);
486 
487     im.im_flags |= IM_ASCII;
488     win_setinputmask(pix_fd, &im, NULL, WIN_NULLLINK);
489 
490     /* determine screen physical dimensions */
491     if ((fd = open(DEV_FB, 1)) < 0) {		/* must be open for writing */
492 	printf("init_pix: can't open %s\n", DEV_FB);
493 	exit(1);
494     }
495 
496     /* get frame buffer characteristics */
497     if (ioctl(fd, FBIOGTYPE, (char *) &fb) < 0) {
498 	printf("init_pix: ioctl (FBIOGTYPE)\n");
499 	exit(1);
500     }
501     close(fd);
502 
503     /* determine maximum physical size of picture subwindow */
504     height = fb.fb_height - TEXTSW_HEIGHT -
505 			    tool_stripeheight(tool) -
506 			    tool_borderwidth(tool) -
507 			    tool_subwindowspacing(tool);
508     width = fb.fb_width - MENUSW_WIDTH -
509 			    tool_subwindowspacing(tool) -
510 			    tool_borderwidth(tool) * 2;
511 
512     /* create pixrect for retaining image of current set */
513     cset_pr = mem_create(width, height, 1);
514     if (cset_pr == NULL) {
515 	printf("can't create cset_pr\n");
516 	exit(1);
517     }
518 
519     /* create pixrect to do all element drawing in memory (faster) */
520     scratch_pr = mem_create(width, height, 1);
521     if (scratch_pr == NULL) {
522 	printf("can't create scratch_pr\n");
523 	exit(1);
524     }
525 
526 #ifdef RETAIN
527     /* create retained pixrect for picture subwindow */
528     retained_pr = mem_create(width, height, 1);
529     if (retained_pr == (struct pixrect *) NULL) {
530 	printf("can't create retained_pr\n");
531 	exit(1);
532     }
533 
534     /* add retained pixrect to the pix subwindow pixwin */
535     pix_pw->pw_prretained = retained_pr;
536 
537     /*
538      * The pix subwindow width and height MUST be initialized before
539      * any drawing can take place when using a retained pixrect.
540      * The display routine DISScreenAdd() uses these dimensions to
541      * minimize the area of the mem_pixrect (scratch_pr) which must
542      * be cleared prior to drawing an element and is called via
543      * SHUpdate() at the end of main_init().
544      */
545     pix_size.r_width = PIXSW_WIDTH;
546     pix_size.r_height = PIXSW_HEIGHT;
547 #endif
548 
549 #ifdef maybefaster
550     md = (struct mpr_data *) scratch_pr->pr_data;
551     _image = (char *) md->md_image;
552     _bytesperline = md->md_linebytes;
553     _maxx = _bytesperline << 3;
554     _maxy = scratch_pr->pr_size.y;
555 #endif
556 }
557 
558 
559 /*
560  * This routine catches the normal tool manager quit menuitem
561  * and handles it slightly differently if no write has occurred
562  * since the last change to the picture.
563  * WARNING: this routine depends upon menu_display() returning
564  * mi->mi_data = 2 for the QUIT menuitem and
565  * mi->mi_data = 1 for the REDISPLAY menuitem.
566  */
567 static
tool_selected(nullsw,ibits,obits,ebits,timer)568 tool_selected(nullsw, ibits, obits, ebits, timer)
569 caddr_t *nullsw;
570 int *ibits, *obits, *ebits;
571 struct timeval **timer;
572 {
573     struct inputevent ie;
574     struct inputmask im;
575     struct menuitem *mi;
576 
577     if (input_readevent(tool_fd, &ie) < 0) {
578 	printf("error: tool_selected()\n");
579 	return;
580     }
581 
582     switch (ie.ie_code) {
583 	case LOC_STILL:
584 /*	    GRCurrentSetOn();			*/
585 	    break;
586 	case MS_LEFT:
587 	    if (wmgr_iswindowopen(tool_fd))
588 		wmgr_top(tool_fd, rootfd);
589 	    else
590 		wmgr_open(tool_fd, rootfd);
591 	    break;
592 	case MS_MIDDLE:
593 	    wmgr_changerect(tool_fd, tool_fd, &ie, 1, 1);
594 	    break;
595 	case MS_RIGHT:
596 	    /* force mouse button input only for pop-up menu */
597 	    input_imnull(&im);
598 	    win_setinputcodebit(&im, MS_LEFT);
599 	    win_setinputcodebit(&im, MS_MIDDLE);
600 	    win_setinputcodebit(&im, MS_RIGHT);
601 	    win_setinputmask(tool_fd, &im, NULL, WIN_NULLLINK);
602 
603 	    wmgr_setupmenu(tool_fd);
604 	    mi = menu_display(&wmgr_toolmenu, &ie, tool_fd);
605 	    if (mi == (struct menuitem *) NULL)
606 		break;
607 
608 	    if (((int) mi->mi_data == 1)		/* REDISPLAY !! */
609 			    && wmgr_iswindowopen(tool_fd))
610 		SHUpdate();
611 	    else if ((int) mi->mi_data == 2) 		/* QUIT !! */
612 		LGQuit();
613 	    else
614 		wmgr_handletoolmenuitem(wmgr_toolmenu, mi, tool_fd, rootfd);
615 
616 	    set_tool_input();	/* reset tool input */
617 	    break;
618     }
619 
620     *ibits = *obits = *ebits = 0;
621 }
622 
623 
624 static
text_selected(nullsw,ibits,obits,ebits,timer)625 text_selected(nullsw, ibits, obits, ebits, timer)
626 caddr_t *nullsw;
627 int *ibits, *obits, *ebits;
628 struct timeval **timer;
629 {
630     struct inputevent ie;
631 
632     if (input_readevent(text_fd, &ie) < 0) {
633 	printf("error: text_selected()\n");
634 	return;
635     }
636 
637     switch (ie.ie_code) {
638 	case LOC_STILL:
639 	    check_cset();
640 	    break;
641 	case MS_LEFT:
642 	    text_left(&ie);
643 	    break;
644 	case MS_MIDDLE:
645 	    text_middle(&ie);
646 	    break;
647 	case MS_RIGHT:
648 	    text_right(&ie);
649 	    break;
650 	case LOC_WINEXIT:
651 	    text_winexit(&ie);
652 	    break;
653 	default:
654 	    if ((ie.ie_code <= ASCII_LAST) && (ie.ie_code >= ASCII_FIRST))
655 		text_output(ie.ie_code);
656 	    break;
657     }
658 
659     *ibits = *obits = *ebits = 0;
660 }
661 
662 
663 static
menu_selected(nullsw,ibits,obits,ebits,timer)664 menu_selected(nullsw, ibits, obits, ebits, timer)
665 caddr_t *nullsw;
666 int *ibits, *obits, *ebits;
667 struct timeval **timer;
668 {
669     struct inputevent ie;
670     char shcmd[2];
671 
672     if (input_readevent(menu_fd, &ie) < 0) {
673 	printf("error: menu_selected()\n");
674 	return;
675     }
676 
677     switch (ie.ie_code) {
678 	case LOC_MOVE:
679 	    mouse_move(&ie);
680 	    break;
681 	case LOC_STILL:
682 	    check_cset();
683 	    break;
684 	case MS_LEFT:
685 	    menu_left(&ie);
686 	    break;
687 	case MS_MIDDLE:
688 	    menu_middle(&ie);
689 	    break;
690 	case MS_RIGHT:
691 	    menu_right(&ie);
692 	    break;
693 	case LOC_WINEXIT:
694 	    menu_winexit(&ie);
695 	    break;
696 	default:
697 	    if ((ie.ie_code <= ASCII_LAST) && (ie.ie_code >= ASCII_FIRST)) {
698 		if ((shcmd[0] = ie.ie_code) != '.')
699 		    lasttext = FALSE;
700 		shcmd[1] = '\0';
701 		SHCommand(shcmd);
702 	    }
703 	    break;
704     }
705 
706     *ibits = *obits = *ebits = 0;
707 }
708 
709 
710 static
pix_selected(nullsw,ibits,obits,ebits,timer)711 pix_selected(nullsw, ibits, obits, ebits, timer)
712 caddr_t *nullsw;
713 int *ibits, *obits, *ebits;
714 struct timeval **timer;
715 {
716     struct inputevent ie;
717     char shcmd[2];
718 
719     if (input_readevent(pix_fd, &ie) < 0) {
720 	printf("error: pix_selected()\n");
721 	return;
722     }
723 
724     switch (ie.ie_code) {
725 	case LOC_STILL:
726 	    check_cset();
727 	    break;
728 	case MS_LEFT:
729 	    pix_left(&ie);
730 	    break;
731 	case MS_MIDDLE:
732 	    pix_middle(&ie);
733 	    break;
734 	case MS_RIGHT:
735 	    pix_right(&ie);
736 	    break;
737 	case LOC_WINEXIT:
738 	    pix_winexit(&ie);
739 	    break;
740 	default:
741 	    if ((ie.ie_code <= ASCII_LAST) && (ie.ie_code >= ASCII_FIRST)) {
742 		if ((shcmd[0] = ie.ie_code) != '.')
743 		    lasttext = FALSE;
744 		shcmd[1] = '\0';
745 		SHCommand(shcmd);
746 	    }
747 	    break;
748     }
749 
750     *ibits = *obits = *ebits = 0;
751 }
752 
753 
754 static
sigwinched()755 sigwinched()
756 {
757     tool_sigwinch(tool);
758 
759     win_getrect(tool_fd, &tool_size);
760     /*
761     printf("tool: left %d, top %d, width %d, height %d\n", tool_size.r_left,
762 	tool_size.r_top, tool_size.r_width, tool_size.r_height);
763     */
764 }
765 
766 
767 static
text_sighandler()768 text_sighandler()
769 {
770     pw_damaged(text_pw);
771 
772     win_getrect(text_fd, &text_size);
773     pw_writebackground(text_pw, 0, 0, 1024, 1024, PIX_SRC);
774     text_putvalue();
775 
776     pw_donedamaged(text_pw);
777 }
778 
779 
780 static
menu_sighandler()781 menu_sighandler()
782 {
783     pw_damaged(menu_pw);
784 
785     win_getrect(menu_fd, &menu_size);
786     pw_writebackground(menu_pw, 0, 0, 1024, 1024, PIX_SRC);
787     MNDisplayMenu();
788     /*
789     printf("menu: left %d, top %d, width %d, height %d\n", menu_size.r_left,
790 	menu_size.r_top, menu_size.r_width, menu_size.r_height);
791     */
792 
793     pw_donedamaged(menu_pw);
794 }
795 
796 
797 static
pix_sighandler()798 pix_sighandler()
799 {
800     GRCurrentSetOn();	/* make current set on */
801     pw_damaged(pix_pw);
802 
803     if (STERROR) {	/* check for startup error reading .gremlinrc */
804 	TxPutMsg("error in .gremlinrc");
805 	STERROR = 0;
806     }
807 
808     win_getrect(pix_fd, &pix_size);
809 
810 #ifdef RETAIN
811     pw_repairretained(pix_pw);
812 #else
813     SHUpdate();
814 #endif
815 
816     pw_donedamaged(pix_pw);
817 }
818 
819 
820 /*
821  *  One time only start-up initialization.
822  */
main_init(file,gremlinrc)823 main_init(file, gremlinrc)
824 char *file;
825 char *gremlinrc;
826 {
827     FILE *fp;
828     POINT *pos;
829     int i, fd;
830     char *prealname;
831 
832     signal(SIGINT, SIG_IGN);			/* ignore interrupts */
833     TxInit();					/* text subwindow init */
834     MNInitMenu();				/* menu subwindow init */
835     PSetPath(".");				/* file search path */
836     Editfile = malloc(128);			/* current picture name */
837 
838     POINTLIST = PTInit();			/* drawing points */
839     BACKPOINT = PTInit();			/* backup point list */
840 
841     PICTURE = DBInit();				/* picture database */
842     cset = DBInit();				/* current set */
843     for (i=0; i<4; ++i)				/* set buffers */
844 	MEN[i] = DBInit();
845 
846     unlist = unback = NULL;			/* undo pointers */
847     make_arrowhead();				/* for > command */
848     lastcommand = nop;				/* no last command yet */
849 
850     STgremlinrc(gremlinrc);			/* .gremlinrc processing */
851     GRFontInit();	       /* must be called after CSIZE & CFONT set */
852 
853     strcpy(Editfile, file);			/* find edit file */
854     if (*file != '\0') {
855 	fp = POpen(Editfile, &prealname, SEARCH);
856 
857 	if (fp == NULL) {
858 	    strcat(namestripe, file);
859 	    error("creating new file");
860 	}
861 	else {
862 	    fclose(fp);
863 	    strcat(namestripe, prealname);
864 	    PICTURE = DBRead(Editfile, &Orientation, &pos);
865 	    if ((fd = open(prealname, O_WRONLY | O_APPEND)) < 0)
866 		strcat(namestripe, " (read only)");
867 	    else
868 		close(fd);
869 	}
870     }
871     else {
872 	strcat(namestripe, "new file");
873     }
874 
875 #ifdef RETAIN
876     /*
877      * Update pix subwindow now so that the retained pixrect is set before
878      * the first SIGWINCH.
879      */
880     SHUpdate();
881 #endif
882 }  /* end main_init */
883 
884 
885 /*
886  *  Make arrowhead element for later drawing.
887  */
make_arrowhead()888 make_arrowhead()
889 {
890     POINT *pos;
891 
892     pos = PTInit();			/* initialize arrowhead template */
893     (void) PTMakePoint(0.0, 0.0, &pos);
894     (void) PTMakePoint(-5.51, 3.51, &pos);
895     (void) PTMakePoint(-3.51, 0.0, &pos);
896     (void) PTMakePoint(-5.51, -3.51, &pos);
897     (void) PTMakePoint(0.0, 0.0, &pos);
898     arhead.type = VECTOR;
899     arhead.ptlist = pos;
900     arhead.brushf = 0;			/* brush filled in when used */
901     arhead.size = 0;
902     arhead.textpt = malloc(1);
903     *(arhead.textpt) = '\0';
904 }
905 
906 
907 /*
908  * Nothing has happened for a while, so check to see if its time
909  * to flash the current set.  If so, set the SIGALRM timer for the
910  * appropriate period.
911  */
check_cset()912 check_cset()
913 {
914     if (FLASH_READY /*&& wmgr_iswindowopen(tool_fd) */) {
915 	GRCurrentSet();				/* XOR current set */
916 
917 	if (CsetOn) {				/* set off period */
918 	    itime.it_interval.tv_sec =
919 	    itime.it_value.tv_sec = timeon_s;
920 	    itime.it_interval.tv_usec =
921 	    itime.it_value.tv_usec = timeon_ms * 1000;
922 	}
923 	else {					/* set on period */
924 	    itime.it_interval.tv_sec =
925 	    itime.it_value.tv_sec = timeoff_s;
926 	    itime.it_interval.tv_usec =
927 	    itime.it_value.tv_usec = timeoff_ms * 1000;
928 	}
929 
930 	setitimer(ITIMER_REAL, &itime, NULL);
931 	FLASH_READY = 0;
932     }
933 }
934 
935 
936 /*
937  * This routine handles the timer signals indicating that it is time
938  * to flash the current set.  Since the screen may not be in a consistent
939  * state, we simply set the FLASH_READY flag and return.  When a LOC_STILL
940  * input event arrives later, this flag will be checked and the current
941  * set flashed then.
942  */
943 static
alrm_sighandler()944 alrm_sighandler()
945 {
946     FLASH_READY = 1;
947 }
948