1 /* $Header: /home/yav/xpx/RCS/main.c,v 1.62 1996/04/24 23:08:27 yav Exp $
2  * xpx main routine
3  * written by yav (UHD98984@pcvan.or.jp)
4  */
5 
6 #include <X11/Xlib.h>
7 #include <X11/Xutil.h>
8 #include <X11/cursorfont.h>
9 #include <X11/keysym.h>
10 
11 #include "headers.h"
12 #include "xpx.h"
13 #include "work.h"
14 #include "menudef.h"
15 #include "editdef.h"
16 #define PUBLIC_MAIN_C
17 #include "extern.h"
18 
19 #define COLSETX (PALSETX+32)
20 #define COLSETY PALSETY
21 
22 #define INTERNAL_ICONPIXMAP 1
23 
24 /* #define DEFAULT_FONT "8x13" */
25 /* #define DEFAULT_BOLD_FONT "8x13bold" */
26 #define DEFAULT_FONT "-adobe-times-medium-r-normal--14-*"
27 #define DEFAULT_BOLD_FONT "-adobe-times-bold-r-normal--14-*"
28 
29 
30 char rcsid_main[] = "$Id: main.c,v 1.62 1996/04/24 23:08:27 yav Exp $";
31 char windowname[128];
32 static char *str_display = "";
33 static char *str_geometry = "";
34 static char *str_background = "Wheat";
35 static char *str_foreground = "Black";
36 static char *str_border = "Black";
37 static char *str_font = NULL;
38 static char *str_fontbold = NULL;
39 static int use_private_color = True;
40 static int use_private_cmap = False;
41 static char grid_dash_list[2] = {1,1};
42 static Pixmap xpxiconpixmap = None;
43 #ifdef INTERNAL_ICONPIXMAP
44 #include "icon.xbm"
45 #endif
46 
47 #include "cursor0.xbm"
48 #include "cursor1.xbm"
49 
usage()50 void usage()
51 {
52   fprintf(stderr, "* %s %s *\n", myname, xpx_version);
53   fprintf(stderr, "written by yav (UHD98984@pcvan.or.jp)\n");
54   fprintf(stderr, "usage : %s [options] col.kcf rei.cel\n", myname);
55   exit(1);
56 }
57 
filename(name)58 char *filename(name)
59      char *name;
60 {
61   char *p;
62 
63   if (name[0] == '\0')
64     return "*Noname*";
65   p = strrchr(name, '/');
66   if (p != NULL)
67     name = p+1;
68   return name;
69 }
70 
basefilename(name)71 char *basefilename(name)
72      char *name;
73 {
74   char *p;
75 
76   name = filename(name);
77   p = strrchr(name, '.');
78   if (p != NULL)
79     *p = '\0';
80   return name;
81 }
82 
83 
84 #define col8to32(x) (((x)<<24)|((x)<<16)|((x)<<8)|(x))
calcol(col,p)85 void calcol(col, p)
86      XColor *col;
87      COL *p;
88 {
89   col->red = col8to32(p->rgb.red);
90   col->green = col8to32(p->rgb.green);
91   col->blue = col8to32(p->rgb.blue);
92   col->flags = DoRed|DoGreen|DoBlue;
93 }
94 
get_color_sub(i,p)95 int get_color_sub(i, p)
96      int i;
97      COL *p;
98 {
99   XColor col;
100   unsigned long plane_masks[1];
101   int r;
102 
103   r = 0;
104   calcol(&col, p);
105   if (*(coltbl+i) & CM_PRIVATE) {
106     col.pixel = *(pixtbl+i);
107     XStoreColor(dsp, cmap, &col);
108   } else {
109     if (use_private_color &&
110 	XAllocColorCells(dsp, cmap, False,
111 			 plane_masks, 0, &col.pixel, 1)) {
112       XStoreColor(dsp, cmap, &col);
113       *(coltbl+i) = CM_ALLOCED | CM_UPDATING | CM_PRIVATE;
114       alloced_private_color++;
115       alloced_color++;
116     } else if (XAllocColor(dsp, cmap, &col)) {
117       *(coltbl+i) = CM_ALLOCED | CM_UPDATING;
118       alloced_color++;
119     } else {
120       r = 1;			/* alloc error! */
121       col.pixel = bg;
122       missed_color++;
123     }
124     *(pixtbl+i) = col.pixel;
125   }
126   return r;
127 }
128 
get_color(p,n)129 int get_color(p, n)
130      COL *p;
131      int n;
132 {
133   int i;
134 
135   for (i = 0; i < n; i++) {
136     if (get_color_sub(i, p))
137       message("!color %d %d %d cannot allocated!\n",
138 	      p->rgb.red, p->rgb.green, p->rgb.blue);
139     if (i < MAXCOLSET) {
140       XSetForeground(dsp, colgc[i], *(pixtbl+i));
141       update_colmenu(i);
142     }
143     p++;
144   }
145   return i;
146 }
147 
148 /* return number of allocated color */
get_requested_colors()149 int get_requested_colors()
150 {
151   int i, r;
152 
153   r = 0;
154   for (i = 0; i < MAXCOLSET*MAXPALSET; i++) {
155     if (*(coltbl+i) & CM_REQUEST) {
156       if (get_color_sub(i, color_buf+i) == 0)
157 	r++;
158       *(coltbl+i) &= ~CM_REQUEST;
159     }
160   }
161   return r;
162 }
163 
request_color(p)164 int request_color(p)
165      COL *p;
166 {
167   int i;
168 
169   for (i = 0; i < MAXCOLSET*MAXPALSET; i++) {
170     if (!(*(coltbl+i) & (CM_ALLOCED|CM_REQUEST))) {
171       *(coltbl+i) = CM_REQUEST;
172       (color_buf+i)->rgb.red = p->rgb.red;
173       (color_buf+i)->rgb.green = p->rgb.green;
174       (color_buf+i)->rgb.blue = p->rgb.blue;
175       return i;
176     }
177   }
178   return -1;
179 }
180 
request_color2(i,p)181 void request_color2(i, p)
182      int i;
183      COL *p;
184 {
185   *(coltbl+i) = CM_REQUEST;
186   (color_buf+i)->rgb.red = p->rgb.red;
187   (color_buf+i)->rgb.green = p->rgb.green;
188   (color_buf+i)->rgb.blue = p->rgb.blue;
189 }
190 
init_color()191 void init_color()
192 {
193   alloced_color = alloced_private_color = missed_color = 0;
194   bzero(coltbl, MAXPALSET*MAXCOLSET);
195   bzero(colmask, MAXPALSET*MAXCOLSET);
196 }
197 
198 /* free common color cells */
free_color()199 void free_color()
200 {
201   int i;
202 
203   for (i = 0; i < MAXPALSET*MAXCOLSET; i++) {
204     if ((*(coltbl+i) & CM_ALLOCED)&&!(*(coltbl+i) & CM_PRIVATE)) {
205       XFreeColors(dsp, cmap, pixtbl+i, 1, 0);
206       --alloced_color;
207       *(coltbl+i) = 0;
208     }
209   }
210 }
211 
212 /* free common and private color cells */
free_color_all()213 void free_color_all()
214 {
215   int i;
216 
217   for (i = 0; i < MAXPALSET*MAXCOLSET; i++) {
218     if (*(coltbl+i) & CM_ALLOCED) {
219       XFreeColors(dsp, cmap, pixtbl+i, 1, 0);
220       --alloced_color;
221       if (*(coltbl+i) & CM_PRIVATE)
222 	--alloced_private_color;
223       *(coltbl+i) = 0;
224     }
225   }
226 }
227 
init_color_buf()228 void init_color_buf()
229 {
230   int i, j;
231   typedef struct {
232     unsigned char r;
233     unsigned char g;
234     unsigned char b;
235   } RGBDATA;
236   static RGBDATA initdata[16] = {
237     {  0,  0,  0},{  0,  0,255},{255,  0,  0},{255,  0,255},
238     {  0,255,  0},{  0,255,255},{255,255,  0},{127,127,127},
239     { 64, 64, 64},{127,127,255},{255,127,127},{255,127,255},
240     {127,255,127},{127,255,255},{255,255,127},{255,255,255}
241   };
242 #define GRAY(n) {n*17, n*17, n*17}
243   static RGBDATA initdata1[16] = {
244     GRAY(15), GRAY(0), GRAY(1), GRAY(2),
245     GRAY(3), GRAY(4), GRAY(5), GRAY(6),
246     GRAY(7), GRAY(8), GRAY(9), GRAY(10),
247     GRAY(11), GRAY(12), GRAY(13), GRAY(14)
248     };
249   static RGBDATA initdata2[16] = {
250     GRAY(0), GRAY(1), GRAY(2), GRAY(3),
251     GRAY(4), GRAY(5), GRAY(6), GRAY(7),
252     GRAY(8), GRAY(9), GRAY(10), GRAY(11),
253     GRAY(12), GRAY(13), GRAY(14), GRAY(15)
254     };
255 
256   for (i = 0; i < MAXPALSET; i++) {
257     for (j = 0; j < MAXCOLSET; j++) {
258       (color_buf+MAXCOLSET*i+j)->rgb.padding = 0;
259       (color_buf+MAXCOLSET*i+j)->rgb.blue = initdata[j].b;
260       (color_buf+MAXCOLSET*i+j)->rgb.red = initdata[j].r;
261       (color_buf+MAXCOLSET*i+j)->rgb.green = initdata[j].g;
262     }
263   }
264   for (j = 0; j < MAXCOLSET; j++) {
265     (color_buf+MAXCOLSET+j)->rgb.padding = 0;
266     (color_buf+MAXCOLSET+j)->rgb.blue = initdata1[j].b;
267     (color_buf+MAXCOLSET+j)->rgb.red = initdata1[j].r;
268     (color_buf+MAXCOLSET+j)->rgb.green = initdata1[j].g;
269   }
270   for (j = 0; j < MAXCOLSET; j++) {
271     (color_buf+MAXCOLSET*2+j)->rgb.padding = 0;
272     (color_buf+MAXCOLSET*2+j)->rgb.blue = initdata2[j].b;
273     (color_buf+MAXCOLSET*2+j)->rgb.red = initdata2[j].r;
274     (color_buf+MAXCOLSET*2+j)->rgb.green = initdata2[j].g;
275   }
276 #undef GRAY
277 }
278 
alloc_colorbuf()279 int alloc_colorbuf()
280 {
281   color_buf = (COL *)malloc(sizeof(COL)*MAXPALSET*MAXCOLSET);
282   pixtbl = (unsigned long *)malloc(sizeof(unsigned long)*MAXPALSET*MAXCOLSET);
283   coltbl = (char *)malloc(MAXPALSET*MAXCOLSET);
284   colmask = (char *)malloc(MAXPALSET*MAXCOLSET);
285   return (color_buf == NULL || pixtbl == NULL ||
286 	  coltbl == NULL || colmask == NULL);
287 }
288 
key_event(ev)289 void key_event(ev)
290      XEvent *ev;
291 {
292   int i, c;
293   char buf[32];
294   KeySym key;
295   XComposeStatus cs;
296   static struct {KeySym sym; int func;} functbl[] = {
297     {XK_Left,	'4'},
298     {XK_Right,	'6'},
299     {XK_Up,	'8'},
300     {XK_Down,	'2'},
301     {XK_KP_Left,	'4'},
302     {XK_KP_Right,	'6'},
303     {XK_KP_Up,		'8'},
304     {XK_KP_Down,	'2'},
305     {0, 0}
306   };
307 
308   i = XLookupString((XKeyEvent *)ev, buf, sizeof(buf)-1, &key, &cs);
309   buf[i] = '\0';
310   c = buf[0];
311   for (i = 0; functbl[i].func; i++) {
312     if (functbl[i].sym == key) {
313       c = functbl[i].func;
314       break;
315     }
316   }
317   switch(c) {
318   case 'q':
319     menu_stat_change(MENU_QUIT, 2);
320     break;
321   case 'f':
322     menu_stat_change(MENU_FILE, 2);
323     break;
324   case 'i':
325     menu_stat_change(MENU_INFO, 2);
326     break;
327   case 'e':
328     menu_stat_change(MENU_EDIT, 2);
329     break;
330   case 'L'-0x40:
331     redraw_window(imgwin);
332     break;
333   case '-':
334     zoom_out();
335     break;
336   case '+':
337   case '=':
338     zoom_in();
339     break;
340   case '2':
341   case 'j':
342     img_scroll(0, scroll_speed);
343     break;
344   case 'J':
345     img_scroll(0, 1);
346     break;
347   case '8':
348   case 'k':
349     img_scroll(0, -scroll_speed);
350     break;
351   case 'K':
352     img_scroll(0, -1);
353     break;
354   case '6':
355   case 'l':
356     img_scroll(scroll_speed, 0);
357     break;
358   case 'L':
359     img_scroll(1, 0);
360     break;
361   case '4':
362   case 'h':
363     img_scroll(-scroll_speed, 0);
364     break;
365   case 'H':
366     img_scroll(-1, 0);
367     break;
368   case '1':
369     img_scroll(-scroll_speed, scroll_speed);
370     break;
371   case '3':
372     img_scroll(scroll_speed, scroll_speed);
373     break;
374   case '7':
375     img_scroll(-scroll_speed, -scroll_speed);
376     break;
377   case '9':
378     img_scroll(scroll_speed, -scroll_speed);
379     break;
380   case 'o':
381     edit_mode_change(EDIT_PLOT);
382     break;
383   case 'p':
384     edit_mode_change(EDIT_PAINT);
385     break;
386   case 'c':
387     edit_mode_change(EDIT_COPY);
388     break;
389   case 'b':
390     edit_mode_change(EDIT_FILL);
391     break;
392   case 'n':
393     edit_mode_change(EDIT_LINE);
394     break;
395   case 'u':
396     edit_undo();
397     break;
398   case 'm':
399     color_mask_alt_all();
400     break;
401   case '!':
402     map_message_window();
403     break;
404   case '?':
405     message("imgchanged:%d colchanged:%d\n", imgchanged, colchanged);
406     break;
407   case 0x03:			/* ^C */
408     edit_copy_hold();
409     break;
410   case 'V'-0x40:		/* ^V */
411     edit_paste_hold();
412     break;
413   }
414 }
415 
create_icon()416 int create_icon()
417 {
418 #ifdef INTERNAL_ICONPIXMAP
419 #if 1
420   xpxiconpixmap =
421     XCreateBitmapFromData(dsp, DefaultRootWindow(dsp),
422 			  icon_bits, icon_width, icon_height);
423 #else
424   xpxiconpixmap =
425     XCreatePixmapFromBitmapData(dsp, DefaultRootWindow(dsp),
426 				icon_bits, icon_width, icon_height,
427 				BlackPixel(dsp, scr), WhitePixel(dsp, scr),
428 				DefaultDepth(dsp, scr));
429 #endif
430   if (xpxiconpixmap == None) {
431     error("icon pixmap create error!");
432     return 1;
433   }
434 #endif /* INTERNAL_ICONPIXMAP */
435   return create_icon_pixmap();
436 }
437 
free_icon()438 void free_icon()
439 {
440   free_icon_pixmap();
441   if (xpxiconpixmap != None)
442     XFreePixmap(dsp, xpxiconpixmap);
443 }
444 
parse_color(col,name)445 int parse_color(col, name)
446      XColor *col;
447      char *name;
448 {
449   if (!XParseColor(dsp, cmap, name, col)||
450       !XAllocColor(dsp, cmap, col))
451     return error("``%s'' color alloc error!", name);
452   return 0;
453 }
454 
455 
make_cursor()456 void make_cursor()
457 {
458   Pixmap src, mask;
459   XColor cfore, cback;
460 
461   curs_watch = XCreateFontCursor(dsp, XC_watch);
462   XParseColor(dsp, cmap, "black", &cfore);
463   XParseColor(dsp, cmap, "white", &cback);
464   src = XCreateBitmapFromData(dsp, DefaultRootWindow(dsp),
465 			      cursor0_bits, cursor0_width, cursor0_height);
466   mask = XCreateBitmapFromData(dsp, DefaultRootWindow(dsp),
467 			       cursor1_bits, cursor1_width, cursor1_height);
468   curs_cross = XCreatePixmapCursor(dsp, src, mask, &cfore, &cback,
469 				   cursor0_x_hot, cursor0_y_hot);
470 }
471 
initialize()472 void initialize()
473 {
474   int i;
475   XSizeHints hint;
476   XColor col;
477 
478   dsp = XOpenDisplay(str_display);
479   if (!dsp) {
480     error("Cannot open display!");
481     exit(1);
482   }
483   scr = DefaultScreen(dsp);
484   cmap = DefaultColormap(dsp, scr);
485   bg = WhitePixel(dsp, scr);
486   border_color = fg = BlackPixel(dsp, scr);
487   if (parse_color(&col, str_background) == 0)
488     bg = col.pixel;
489   if (parse_color(&col, str_foreground) == 0)
490     fg = col.pixel;
491   if (parse_color(&col, str_border) == 0)
492     border_color = col.pixel;
493   create_icon();
494   hint.flags = 0;
495   i = XGeometry(dsp, scr, str_geometry, "428x368", border_width, 1, 1, 0, 0,
496 		&(hint.x), &(hint.y), &(hint.width), &(hint.height));
497   if (i & (XValue|YValue))
498     hint.flags |= PPosition;
499   if (i & (WidthValue|HeightValue))
500     hint.flags |= PSize;
501   win = XCreateSimpleWindow(dsp, DefaultRootWindow(dsp),
502 			    hint.x, hint.y, hint.width, hint.height,
503 			    border_width, border_color, bg);
504   XSetStandardProperties(dsp, win, windowname, windowname, xpxiconpixmap,
505 			 oargv, oargc, &hint);
506   toplevelwin[toplevelwc++] = win;
507   if (use_private_cmap) {
508     cmap = XCopyColormapAndFree(dsp, cmap);
509     XSetWindowColormap(dsp, win, cmap);
510   }
511   make_cursor();
512   if (str_fontbold == NULL)
513     str_fontbold = str_font == NULL ? DEFAULT_BOLD_FONT : str_font;
514   if (str_font == NULL)
515     str_font = DEFAULT_FONT;
516 
517   fs0 = XLoadQueryFont(dsp, str_fontbold);
518   fs1 = XLoadQueryFont(dsp, str_fontbold);
519 
520   gc0 = XCreateGC(dsp, win, 0, 0);
521   XSetBackground(dsp, gc0, bg);
522   XSetForeground(dsp, gc0, fg);
523   XSetFont(dsp, gc0, fs0->fid);
524 
525   gc1 = XCreateGC(dsp, win, 0, 0);
526   XSetBackground(dsp, gc1, fg);
527   XSetForeground(dsp, gc1, bg);
528   XSetFont(dsp, gc1, fs0->fid);
529 
530   areagc = XCreateGC(dsp, win, 0, 0);
531   XSetBackground(dsp, areagc, bg);
532   XSetForeground(dsp, areagc, fg);
533 
534   grid0gc = XCreateGC(dsp, win, 0, 0);
535   XSetBackground(dsp, grid0gc, bg);
536   XSetForeground(dsp, grid0gc, bg);
537 
538   gridgc = XCreateGC(dsp, win, 0, 0);
539   XSetBackground(dsp, gridgc, bg);
540   XSetForeground(dsp, gridgc, bg);
541   XSetLineAttributes(dsp, gridgc, 0, LineOnOffDash, CapButt, JoinMiter);
542   XSetDashes(dsp, gridgc, 0, grid_dash_list, 2);
543 
544   hatch_pixmap = XCreatePixmapFromBitmapData(dsp, win,
545 					     hatch_bits, 8, 8, fg, bg,
546 					     DefaultDepth(dsp, scr));
547 
548 }
549 
550 #ifdef __STDC__
551 typedef void *VOIDPTR;
552 #else
553 typedef char *VOIDPTR;
554 #endif
555 
556 #define OPT_ABBREV_MASK	0x10
557 #define OPT_FUNC	1
558 #define OPT_SET_INT	2
559 #define OPT_GET_INT	3
560 #define OPT_GET_STR	4
561 
562 typedef struct {
563   char *name;
564   VOIDPTR parm;
565   char type;
566   char setvalue;		/* for OPT_SET_INT */
567 } OPTION;
568 
569 #define OPTTBL(name,type,ptr,val) {name, (VOIDPTR)ptr, type, val}
570 
571 static OPTION opttbl[] = {
572   OPTTBL("-?",		OPT_FUNC,	usage,			0),
573   OPTTBL("-h",		OPT_FUNC,	usage,			0),
574   OPTTBL("-V",		OPT_FUNC,	usage,			0),
575   OPTTBL("-help",	OPT_FUNC,	usage,			0),
576   OPTTBL("-debug",	OPT_SET_INT,	&debug_mode,		True),
577   OPTTBL("-display",	OPT_GET_STR,	&str_display,		0),
578   OPTTBL("-geometry",	OPT_GET_STR,	&str_geometry,		0),
579   OPTTBL("-background",	OPT_GET_STR,	&str_background,	0),
580   OPTTBL("-bg",		OPT_GET_STR,	&str_background,	0),
581   OPTTBL("-foreground",	OPT_GET_STR,	&str_foreground,	0),
582   OPTTBL("-fg",		OPT_GET_STR,	&str_foreground,	0),
583   OPTTBL("-bordercolor",OPT_GET_STR,	&str_border,		0),
584   OPTTBL("-bd",		OPT_GET_STR,	&str_border,		0),
585   OPTTBL("-font",	OPT_GET_STR,	&str_font,		0),
586   OPTTBL("-fn",		OPT_GET_STR,	&str_font,		0),
587   OPTTBL("-fb",		OPT_GET_STR,	&str_fontbold,		0),
588   OPTTBL("-borderwidth",OPT_GET_INT,	&border_width,		0),
589   OPTTBL("-bw",		OPT_GET_INT,	&border_width,		0),
590   OPTTBL("-commoncolor",OPT_SET_INT,	&use_private_color,	False),
591   OPTTBL("-cmap",	OPT_SET_INT,	&use_private_cmap,	True),
592   OPTTBL("-p",		OPT_SET_INT,	&use_private_cmap,	True),
593   OPTTBL("-quickconvert",OPT_SET_INT,	&quick_convert,		True),
594   OPTTBL("-slowconvert",OPT_SET_INT,	&quick_convert,		False),
595   OPTTBL("-backingstore",OPT_GET_INT,	&backingstoremode,	0),
596   OPTTBL("-menu",	OPT_GET_INT,	&menumode,		0),
597   OPTTBL("-menuspeed",	OPT_GET_INT,	&menu_speed,		0),
598   OPTTBL("-zoom",	OPT_GET_INT,	&zoomfactor,		0),
599   OPTTBL("-scrollbar",	OPT_GET_INT,	&scrollbarmode,		0),
600   OPTTBL("-maxw",	OPT_GET_INT,	&imgmaxw,		0),
601   OPTTBL("-maxh",	OPT_GET_INT,	&imgmaxh,		0),
602   OPTTBL("-maxz",	OPT_GET_INT,	&maxzoom,		0),
603   OPTTBL("-scrollspeed",OPT_GET_INT,	&scroll_speed,		0),
604   OPTTBL("-ix",		OPT_GET_INT,	&imgwx,			0),
605   OPTTBL("-iy",		OPT_GET_INT,	&imgwy,			0),
606   OPTTBL(NULL,		0,		NULL,			0)
607 };
608 
parse_option(ac,av)609 int parse_option(ac, av)
610      int *ac;
611      char ***av;
612 {
613   OPTION *p;
614   int i;
615   typedef void (*VOIDFUNCPTR)();
616 
617   for (p = opttbl; p->name != NULL; p++) {
618     if (strcmp(**av, p->name) == 0) {
619       --*ac;
620       ++*av;
621       switch(p->type & ~OPT_ABBREV_MASK) {
622       case OPT_FUNC:
623 	((VOIDFUNCPTR)(p->parm))();
624 	break;
625       case OPT_SET_INT:
626 	*((int *)(p->parm)) = p->setvalue;
627 	break;
628       case OPT_GET_INT:
629 	if (*ac) {
630 	  *((int *)(p->parm)) = strtol(**av, NULL, 0);
631 	  ++*av;
632 	  --*ac;
633 	}
634 	break;
635       case OPT_GET_STR:
636 	if (*ac) {
637 	  *((char **)(p->parm)) = **av;
638 	  ++*av;
639 	  --*ac;
640 	}
641 	break;
642       }
643       return 0;
644     } else if (p->type & OPT_ABBREV_MASK &&
645 	       strncmp(**av, p->name, i = strlen(p->name)) == 0) {
646       switch(p->type & ~OPT_ABBREV_MASK) {
647       case OPT_GET_INT:
648 	*((int *)(p->parm)) = strtol(**av+i, NULL, 0);
649 	break;
650       case OPT_GET_STR:
651 	*((char **)(p->parm)) = **av+i;
652 	break;
653       }
654       ++*av;
655       --*ac;
656       return 0;
657     }
658   }
659   return 1;
660 }
661 
662 
main(argc,argv)663 void main(argc, argv)
664      int argc; char **argv;
665 {
666   XEvent ev;
667   int i;
668   Window double_click_win = 0;
669   Time l, double_click_time;
670   XEvent ahead;
671   Bool ignore_event;
672 
673   oargc = argc;
674   oargv = argv;
675   errname = myname = filename(*argv);
676   strncpy(windowname, myname, sizeof(windowname));
677   strncat(windowname, " @ ", sizeof(windowname));
678   i = strlen(windowname);
679   gethostname(windowname+i, sizeof(windowname)-i);
680   windowname[sizeof(windowname)-1] = '\0';
681   if (read_config())
682     exit(1);
683   argv++;
684   argc--;
685   while (argc > 0) {
686     if (parse_option(&argc, &argv)) {
687       if (**argv == '-') {
688 	error("unknown option ``%s''!", *argv);
689 	usage();
690       }
691       break;
692     }
693   }
694   initialize();
695   if (alloc_colorbuf())
696     exit(1);
697   if (imgwx == -1 && imgwy == -1) {
698     if (!menumode) {
699       imgwx = imgwy = 0;
700     } else {
701       imgwx = 112;		/* 124 */
702       imgwy = 52;		/* 64 */
703     }
704     if (scrollbarmode & 1) {
705       imgwx += IMGSCRLW;
706       imgwy += IMGSCRLW;
707     }
708   }
709   create_img_window();
710   cursor_busy();
711 
712   menuev_init();
713   create_message_window();
714   create_info_window();
715   create_scrlbar_window();
716   create_menu_window(win, MENUX, MENUY);
717   create_colset_window(win, COLSETX, COLSETY);
718   create_palset_window(win, PALSETX, PALSETY);
719   create_filename_window(win, PALSETX, PALSETY-24);
720   create_zoom_window(win, 256, 4);
721   create_grid_window(win, 340, 4);
722   create_cursor_window(win, 256, 30);
723   init_tilemask();
724   create_tile_window(win, 8, 364);
725   create_edit_window();
726   create_file_window();
727   if (image_alloc()||undo_init()) {
728     error("more core!");
729     exit(1);
730   }
731   init_color_buf();
732   init_color();
733   init_image();
734   image_update_all();
735   while (argc--)
736     read_data_file(*argv++);
737   XSelectInput(dsp, win, ExposureMask|StructureNotifyMask|
738 	       ButtonPressMask|KeyPressMask);
739   XMapRaised(dsp, win);
740   while (!sw_quit) {
741     if (XEventsQueued(dsp, QueuedAfterReading) == 0) {
742       XFlush(dsp);
743       cursor_free();
744       imgscrl_background();
745       file_background();
746     }
747     XNextEvent(dsp, &ev);
748     ignore_event = False;
749     switch(ev.type) {
750     case NoExpose:
751       if (ev.xnoexpose.drawable == imgwin)
752 	imgwin_noexpose = True;
753       break;
754     case GraphicsExpose:
755       if (ev.xgraphicsexpose.drawable == imgwin) {
756 	img_expose(ev.xgraphicsexpose.x, ev.xgraphicsexpose.y,
757 		   ev.xgraphicsexpose.width, ev.xgraphicsexpose.height);
758 	if (ev.xgraphicsexpose.count == 0)
759 	  imgwin_noexpose = True;
760       }
761       break;
762     case Expose:
763       if (ev.xexpose.window == imgwin)
764 	img_expose(ev.xexpose.x, ev.xexpose.y,
765 		   ev.xexpose.width, ev.xexpose.height);
766       else
767 	info_expose(&ev);
768       break;
769     case MappingNotify:
770       XRefreshKeyboardMapping((XMappingEvent *)&ev);
771       break;
772     case KeyPress:
773       if (ev.xkey.window == win)
774 	key_event(&ev);
775       break;
776     case ConfigureNotify:
777       if (ev.xconfigure.window == win)
778 	resize_img_window();
779       break;
780     case ButtonPress:
781       if (ev.xbutton.window == double_click_win) {
782 	l = ev.xbutton.time - double_click_time;
783 	if (l & 0x80000000)
784 	  l = ~l + 1;
785 	double_clicked = l < 500;
786       } else {
787 	double_clicked = False;
788       }
789       double_click_win = ev.xbutton.window;
790       double_click_time = ev.xbutton.time;
791       info_press(&ev);
792       break;
793     case EnterNotify:
794       if (XEventsQueued(ev.xcrossing.display, QueuedAfterReading) > 0) {
795 	XPeekEvent(ev.xcrossing.display, &ahead);
796 	if (ahead.type == LeaveNotify &&
797 	    ahead.xcrossing.window == ev.xcrossing.window &&
798 	    ahead.xcrossing.mode == ev.xcrossing.mode &&
799 	    ahead.xcrossing.detail == ev.xcrossing.detail) {
800 	  XNextEvent(ev.xcrossing.display, &ev);
801 	  ignore_event = True;
802 	}
803       }
804     case LeaveNotify:
805       double_click_win = 0;
806       break;
807     }
808     if (!ignore_event) {
809       edit_event(&ev);
810       if (ev.type == MotionNotify &&
811 	  XEventsQueued(ev.xmotion.display, QueuedAfterReading) > 0) {
812 	XPeekEvent(ev.xmotion.display, &ahead);
813 	if (ahead.type == MotionNotify &&
814 	    ahead.xmotion.window == ev.xmotion.window) {
815 	  XNextEvent(ev.xmotion.display, &ev);
816 	}
817       }
818       menuev_event(&ev);
819     }
820   }
821   autosave();
822   update_config_file();
823 #if 1
824   menuev_destroy();
825   close_message_window();
826   close_edit_window();
827   close_info_window();
828   close_file_window();
829   XDestroyWindow(dsp, imgwin);
830   free_color_all();
831   free_icon();
832   XFree((char *)img);
833   XFreeGC(dsp, gc1);
834   XFreeGC(dsp, gc0);
835   XDestroyWindow(dsp, win);
836 #endif
837   XCloseDisplay(dsp);
838   exit(0);
839 }
840 
841 /* End of file */
842