1 /* $Header: /home/yav/catty/fkiss/RCS/menu.c,v 1.28 2000/09/28 07:53:23 yav Exp $
2  * fkiss menu bar
3  * written by yav <yav@bigfoot.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 
20 char id_menu[] = "$Id: menu.c,v 1.28 2000/09/28 07:53:23 yav Exp $";
21 
22 #include <X11/Xos.h>
23 #include <X11/Xlib.h>
24 #include <X11/Xutil.h>
25 
26 #include <stdio.h>
27 #include "config.h"
28 #include "headers.h"
29 #include "fkiss.h"
30 #include "work.h"
31 #define PUBLIC_MENU_C
32 #include "extern.h"
33 
34 #if USE_UNAME
35 #include <sys/utsname.h>
36 #endif
37 
38 #define BASE_XMARGIN 3
39 #define BASE_YMARGIN 1
40 
41 #define MNFNC_MAX 3
42 
43 Window aboutwin;
44 Window aboutokwin;
45 static int aboutokw = 32;
46 static int aboutokh;
47 static int aboutokstat;
48 static char str_ok[] = "OK";
49 static char str_setbase[] = "Set";
50 static char str_palbase[] = "Col";
51 static MW *mwfnc;
52 static int fnccnt;
53 static MW *mwset;
54 static MW *mwpal;
55 static char *fncstr[MNFNC_MAX+1] = {"?", "Quit", "Doc", NULL};
56 static Window setbasewin;
57 static Window palbasewin;
58 #define DEFAULT_MNFNCW 48	/* function menu width default */
59 static int mnfnch;		/* function menu height */
60 #define MNFNCBW 1		/* function menu border width */
61 static int mnbsetw0 = 32;
62 static int mnbsetw, mnbseth;
63 #define MNBSETBW 1		/* set menu base border width */
64 static int mnbpalw0 = 32;
65 static int mnbpalw, mnbpalh;
66 #define MNBPALBW 1		/* pal menu base border width */
67 static int mnsetw = 13;		/* set menu width */
68 static int mnseth;
69 #define MNSETBW 0		/* set menu border width */
70 static int mnpalw = 13;		/* pal menu width */
71 static int mnpalh;
72 #define MNPALBW 0		/* pal menu border width */
73 int infow, infoh;
74 #define INFOBW 0
75 static int about_mode = 0;
76 
77 static char *font_defaults[] = {
78   "-adobe-new century schoolbook-medium-r-normal--*-140-*-*-p-*-iso8859-1",
79   "-adobe-times-medium-r-normal--*-140-*-*-p-*-iso8859-1",
80   "8x16",
81   "8x13",
82   NULL};
83 static char *font8_defaults[] = {
84   "rk16",			/* 8x16 Alphabet and Kana */
85   "8x16",			/* 8x16 Alphabet */
86   NULL};
87 static char *font16_defaults[] = {
88   "kanji16",			/* 16x16 Kanji */
89   "neckg16",			/* for NEC EWS4800 */
90   "k14",			/* 14x14 Kanji */
91   NULL};
92 
calc_text_size(str)93 int calc_text_size(str)
94      char *str;
95 {
96   XCharStruct overall;
97   int direction_hint;
98 
99   XTextExtents(fsp, str, strlen(str), &direction_hint,
100 	       &font_ascent, &font_descent, &overall);
101   return overall.rbearing - overall.lbearing;
102 }
103 
load_fs(name,list)104 XFontStruct *load_fs(name, list)
105      char **name;
106      char **list;
107 {
108   XFontStruct *p;
109 
110   do {
111     if (*name != NULL) {
112       p = XLoadQueryFont(dsp, *name);
113       if (p != NULL)
114 	return p;
115       msg("W font ``%s'' not found.\n", *name);
116     }
117     *name = *list++;
118   } while (*name != NULL);
119   return NULL;
120 }
121 
load_font_sub(p,name,list,fromgc,ngc)122 void load_font_sub(p, name, list, fromgc, ngc)
123      XFontStruct **p;
124      char **name;
125      char **list;
126      int fromgc;
127      int ngc;
128 {
129   int i;
130 
131   *p = load_fs(name, list);
132   if (*p == NULL) {
133     msg("W use CG default font.\n");
134   } else {
135     for (i = 0; i < ngc; i++)
136       XSetFont(dsp, sysgc[fromgc+i], (*p)->fid);
137   }
138 }
139 
load_font()140 void load_font()
141 {
142   load_font_sub(&fsp, &str_font, font_defaults, 0, SGC_MAX);
143   if (fsp != NULL)
144     calc_text_size("Sample string");
145   mnh = font_ascent + font_descent + MNFNCBW*2 + 2 + BASE_YMARGIN*2;
146   load_font_sub(&fsp8, &str_font8, font8_defaults, SGC_T8, 1);
147   load_font_sub(&fsp16, &str_font16, font16_defaults, SGC_T16, 1);
148 }
149 
change_menu_status(win,mode)150 void change_menu_status(win, mode)
151      Window win;
152      int mode;
153 {
154   XSetWindowBackground(dsp, win, (mode & 2) ? spx[SPX_FG] : spx[SPX_BT]);
155   XClearArea(dsp, win, 0, 0, 0, 0, True);
156 }
157 
set_menu_window_attributes()158 void set_menu_window_attributes()
159 {
160   XSetWindowAttributes atr;
161 
162   XSetWindowBorder(dsp, mnwin, spx[SPX_FG]);
163   XSetWindowBackground(dsp, mnwin, spx[SPX_MN]);
164   if (spx[SPX_MN] == spx[SPX_BG]) {
165     atr.background_pixmap =
166       XCreatePixmapFromBitmapData(dsp, topwin, (char *)hatch_ptrn, 8, 8,
167 				  spx[SPX_FG], spx[SPX_BG],
168 				  screen_depth);
169     XChangeWindowAttributes(dsp, mnwin, CWBackPixmap, &atr);
170     XFreePixmap(dsp, atr.background_pixmap);
171   }
172   XSetWindowBorder(dsp, aboutwin, spx[SPX_FG]);
173   if (iconp != None) {
174     atr.background_pixmap =
175       XCreatePixmap(dsp, aboutwin, iconw*2, iconh*2, screen_depth);
176     XFillRectangle(dsp, atr.background_pixmap, sysgc[SGC_IN1],
177 		   0, 0, iconw*2, iconh*2);
178     XCopyPlane(dsp, iconp, atr.background_pixmap, sysgc[SGC_IN0],
179 	       0, 0, iconw, iconh, 0, 0, 1);
180     XCopyPlane(dsp, iconp, atr.background_pixmap, sysgc[SGC_IN0],
181 	       0, 0, iconh, iconh, iconw, iconh, 1);
182     XChangeWindowAttributes(dsp, aboutwin, CWBackPixmap, &atr);
183     XFreePixmap(dsp, atr.background_pixmap);
184   }
185 }
186 
create_menuwins(x,y,w,h,b,mask)187 Window create_menuwins(x, y, w, h, b, mask)
188      int x;
189      int y;
190      int w;
191      int h;
192      int b;
193      long mask;
194 {
195   Window win;
196 
197   win = XCreateSimpleWindow(dsp, mnwin, x, y, w, h, b, spx[SPX_FG], spx[SPX_BT]);
198   XSelectInput(dsp, win, mask);
199   return win;
200 }
201 
create_button_window(x,y,w,h,b)202 Window create_button_window(x, y, w, h, b)
203      int x;
204      int y;
205      int w;
206      int h;
207      int b;
208 {
209   return create_menuwins(x, y, w, h, b,
210 			 OwnerGrabButtonMask|
211 			 ExposureMask|ButtonPressMask|ButtonReleaseMask|
212 			 EnterWindowMask|LeaveWindowMask);
213 }
214 
calc_menu_width(str)215 int calc_menu_width(str)
216      char *str;
217 {
218   int i;
219 
220   i = calc_text_size(str);
221   return i + i/3 + 2;
222 }
223 
calc_menu_geometry()224 void calc_menu_geometry()
225 {
226   int i, x;
227 
228   mnfnch = mnh - MNFNCBW*2 - BASE_YMARGIN*2;
229   for (i = 0; i < fnccnt; i++) {
230     if (fsp != NULL)
231       (mwfnc+i)->w = calc_menu_width(fncstr[i]);
232     else
233       (mwfnc+i)->w = DEFAULT_MNFNCW;
234     if ((mwfnc+i)->w < mnfnch)
235       (mwfnc+i)->w = mnfnch;
236   }
237   if (fsp != NULL) {
238     aboutokw = calc_menu_width(str_ok);
239     mnbsetw0 = calc_menu_width(str_setbase);
240     mnbpalw0 = calc_menu_width(str_palbase);
241   }
242   mnbsetw = mnbsetw0 + (mnsetw + MNSETBW*2)*setcnt;
243   mnbseth = mnh - MNBSETBW*2 - BASE_YMARGIN*2;
244   mnbpalw = mnbpalw0 + (mnpalw + MNPALBW*2)*palcnt;
245   mnbpalh = mnh - MNBPALBW*2 - BASE_YMARGIN*2;
246   mnseth = mnbseth - MNSETBW*2;
247   mnpalh = mnbseth - MNPALBW*2;
248   infoh = mnh - INFOBW*2 - BASE_YMARGIN*2;
249   x = BASE_XMARGIN;
250   for (i = 0; i < fnccnt; i++)
251     x += (mwfnc+i)->w + MNFNCBW*2 + BASE_XMARGIN;
252   x += mnbsetw + MNBSETBW*2 + BASE_XMARGIN;
253   x += mnbpalw + MNBPALBW*2 + BASE_XMARGIN;
254   infow = mnw - (x + INFOBW*2 + BASE_XMARGIN);
255   if (infow < 1)
256     infow = 1;
257 }
258 
menu_resize()259 void menu_resize()
260 {
261   calc_menu_geometry();
262   XResizeWindow(dsp, infowin, infow, infoh);
263 }
264 
alloc_mw(n)265 MW *alloc_mw(n)
266      int n;
267 {
268   int i;
269   MW *p;
270 
271   p = (MW *)ks_malloc(sizeof(MW)*(n+1));
272   bzero((char *)p, sizeof(MW)*(n+1));
273   for (i = 0; i < n; i++)
274     (p+i)->n = i;
275   (p+i)->n = -1;		/* End mark */
276   return p;
277 }
278 
create_set_menu()279 void create_set_menu()
280 {
281   int i, x, y;
282   XSetWindowAttributes atr;
283 
284   for (fnccnt = 0; fncstr[fnccnt] != NULL; fnccnt++)
285     ;
286   mwfnc = alloc_mw(fnccnt);
287   calc_menu_geometry();
288   x = BASE_XMARGIN;
289   y = BASE_YMARGIN;
290   for (i = 0; i < fnccnt; i++) {
291     (mwfnc+i)->win = create_button_window(x, y, (mwfnc+i)->w, mnfnch, MNFNCBW);
292     x += (mwfnc+i)->w + MNFNCBW*2 + BASE_XMARGIN;
293   }
294   setbasewin = create_menuwins(x, y, mnbsetw, mnbseth, MNBSETBW, ExposureMask);
295   mwset = alloc_mw(setcnt);
296   for (i = 0; i < setcnt; i++)
297     if (active_set[i])
298       (mwset+i)->win =
299 	create_button_window(x + MNBSETBW + mnbsetw0 + (mnsetw+MNSETBW*2)*i,
300 			     MNBSETBW + y,
301 			     mnsetw, mnseth, MNSETBW);
302   x += mnbsetw + MNBSETBW*2 + BASE_XMARGIN;
303   palbasewin = create_menuwins(x, y, mnbpalw, mnbpalh, MNBPALBW, ExposureMask);
304   mwpal = alloc_mw(palcnt);
305   for (i = 0; i < palcnt; i++)
306     (mwpal+i)->win =
307       create_button_window(x + MNBPALBW + mnbpalw0 + (mnpalw+MNPALBW*2)*i,
308 			   MNBPALBW + y,
309 			   mnpalw, mnpalh, MNPALBW);
310   x += mnbpalw + MNBPALBW*2 + BASE_XMARGIN;
311   XMapRaised(dsp, mnwin);
312   XMapSubwindows(dsp, mnwin);
313   infowin = XCreateSimpleWindow(dsp, mnwin, x, y,
314 				infow, infoh, INFOBW,
315 				spx[SPX_FG], spx[SPX_MN]);
316   XSelectInput(dsp, infowin, ExposureMask);
317   /* About ok menu open */
318   aboutokh = font_ascent + font_descent + 2;
319   aboutokstat = 0;
320   aboutokwin = XCreateSimpleWindow(dsp, aboutwin,
321 				   vieww-(aboutokw+MNFNCBW*2+1),
322 				   viewh-(aboutokh+MNFNCBW*2+1),
323 				   aboutokw, aboutokh, MNFNCBW,
324 				   spx[SPX_FG], spx[SPX_BT]);
325   XSelectInput(dsp, aboutokwin,
326 	       OwnerGrabButtonMask|
327 	       ExposureMask|ButtonPressMask|ButtonReleaseMask|
328 	       EnterWindowMask|LeaveWindowMask);
329   atr.win_gravity = SouthEastGravity;
330   XChangeWindowAttributes(dsp, aboutokwin, CWWinGravity, &atr);
331   XMapSubwindows(dsp, aboutwin);
332 }
333 
which_winlist(win,p)334 int which_winlist(win, p)
335      Window win;
336      MW *p;
337 {
338   while (p->n >= 0) {
339     if (win == p->win)
340       break;
341     p++;
342   }
343   return p->n;
344 }
345 
draw_menu_string(win,mode,w,h,leftm,topm,str)346 void draw_menu_string(win, mode, w, h, leftm, topm, str)
347      Window win;
348      int mode;
349      int w;
350      int h;
351      int leftm;
352      int topm;
353      char *str;
354 {
355   GC gc;
356 
357   gc = ((mode & 2) ? sysgc[SGC_BT1] : sysgc[SGC_BT0]);
358   XDrawString(dsp, win, gc, leftm, topm + font_ascent, str, strlen(str));
359   if (mode & 1)
360     XDrawRectangle(dsp, win, gc, 0, 0, w-1, h-1);
361 }
362 
draw_button(win,mode,w,h,str)363 void draw_button(win, mode, w, h, str)
364      Window win;
365      int mode;
366      int w;
367      int h;
368      char *str;
369 {
370   int strwidth;
371 
372   strwidth = calc_text_size(str);
373   draw_menu_string(win, mode, w, h,
374 		   (w - strwidth)/2, (h - (font_ascent+font_descent))/2, str);
375 }
376 
377 #define TAB_STOP_WIDTH	8
378 
379 /* convert tab to spaces */
expand(dst,src,len)380 void expand(dst, src, len)
381      unsigned char *dst;	/* destination buffer to store */
382      unsigned char *src;	/* source string */
383      int len;			/* dst size */
384 {
385   int i, pos;
386 
387   pos = 0;			/* initial column 0 */
388   while (*src) {
389     if (len <= 1)
390       break;			/* no space to store, abort */
391     switch(*src) {
392     case '\t':
393       i = TAB_STOP_WIDTH - (pos % TAB_STOP_WIDTH);
394       while (i--) {
395 	*dst++ = ' ';
396 	pos++;
397 	if (--len <= 1)
398 	  break;		/* no space to store, abort */
399       }
400       break;
401     case '\033':
402       pos -= 3;
403       /* FALL THROUGH */
404     default:
405       *dst++ = *src;
406       pos++;
407       --len;
408       break;
409     }
410     src++;
411   }
412   *dst = '\0';
413 }
414 
415 #define FONT8_WIDTH 8
416 #define FONT16_WIDTH 16
417 
dup_char2b(dst,src,len)418 void dup_char2b(dst, src, len)
419      XChar2b *dst;
420      unsigned char *src;
421      int len;
422 {
423   while (len--) {
424     dst->byte1 = *src++;
425     dst->byte2 = *src++;
426     dst++;
427   }
428 }
429 
430 #define DRAWSTR_MAX 1024
431 
draw_str16(d,x,y,str,len,kanji)432 int draw_str16(d, x, y, str, len, kanji)
433      Drawable d;		/* target window or pixmap (None:NOT draw) */
434      int x, y;			/* position */
435      unsigned char *str;	/* drawing string */
436      int len;			/* byte count */
437      int kanji;			/* kanji flag */
438 {
439   XChar2b buf[DRAWSTR_MAX];
440 
441   if (kanji) {
442     len /= 2;
443     if (len > DRAWSTR_MAX)
444       len = DRAWSTR_MAX;
445     dup_char2b(buf, str, len);
446     if (d != None) {
447       if (spx[SPX_BG2] == spx[SPX_FG])
448 	XDrawImageString16(dsp, d, sysgc[SGC_T16], x, y, buf, len);
449       else
450 	XDrawString16(dsp, d, sysgc[SGC_T16], x, y, buf, len);
451     }
452     len *= FONT16_WIDTH;
453   } else {
454     if (d != None) {
455       if (spx[SPX_BG2] == spx[SPX_FG])
456 	XDrawImageString(dsp, d, sysgc[SGC_T8], x, y, (char *)str, len);
457       else
458 	XDrawString(dsp, d, sysgc[SGC_T8], x, y, (char *)str, len);
459     }
460     len *= FONT8_WIDTH;
461   }
462   return len;			/* string width (pixel) */
463 }
464 
465 /* draw ASCII English and Shift-JIS coed Japanese text
466  * output to specified drawable
467  * but, if None drawable is specified, strings is NOT draw.
468  */
draw_string(d,x,y,str)469 int draw_string(d, x, y, str)
470      Drawable d;		/* target drawable (None: NOT draw) */
471      int x, y;			/* position */
472      char *str;			/* drawing string */
473 {
474   unsigned char c, c2;
475   unsigned short code;
476   Bool inkanji;
477   int buffered_count;
478   int i, w;
479   unsigned char *p;
480   unsigned char buf[DRAWSTR_MAX];
481   unsigned char buf2[DRAWSTR_MAX];
482 
483   expand(buf, (unsigned char *)str, sizeof(buf));
484   buffered_count = w = 0;
485   inkanji = False;
486   p = buf;
487   while ((c = *p++) != '\0') {
488     c2 = *p;
489     if (is_sjis_1st(c) && is_sjis_2nd(c2)) {
490       if (!inkanji) {
491 	/* flush ASCII text */
492 	i = draw_str16(d, x, y, buf2, buffered_count, 0);
493 	w += i;
494 	x += i;
495 	buffered_count = 0;
496       }
497       code = (c << 8) + c2;
498       code = ysjis2jis(code);
499       buf2[buffered_count++] = code >> 8;
500       buf2[buffered_count++] = code;
501       p++;
502       inkanji = True;
503     } else {
504       if (inkanji) {
505 	/* flush Japanese KANJI text */
506 	i = draw_str16(d, x, y, buf2, buffered_count, 1);
507 	w += i;
508 	x += i;
509 	buffered_count = 0;
510       }
511       buf2[buffered_count++] = c;
512       inkanji = False;
513     }
514   }
515   if (buffered_count) {
516     i = draw_str16(d, x, y, buf2, buffered_count, inkanji);
517     w += i;
518   }
519   return w;			/* string width (pixel) */
520 }
521 
draw_data_comment()522 void draw_data_comment()
523 {
524   int i, y;
525 
526   y = 0;
527   for (i = 0; i < cnf_comment_cnt; i++) {
528     y += 16;			/* add font ascent */
529     draw_string(aboutwin, 0, y, *(cnf_comment+i));
530     y += 0;			/* font descent + line margin */
531   }
532 }
533 
534 #define ABOUT_LINE_MARGIN 2
535 
draw_about_line(y,str)536 void draw_about_line(y, str)
537      int *y;
538      char *str;
539 {
540   int i, x;
541 
542   x = (vieww - calc_text_size(str))/2;
543   i = strlen(str);
544   *y += font_ascent;
545   if (spx[SPX_BG2] == spx[SPX_FG])
546     XDrawImageString(dsp, aboutwin, sysgc[SGC_GEN], x, *y, str, i);
547   else
548     XDrawString(dsp, aboutwin, sysgc[SGC_GEN], x, *y, str, i);
549   *y += font_descent+ABOUT_LINE_MARGIN;
550 }
551 
552 #if USE_UNAME
get_client_info()553 char *get_client_info()
554 {
555   char buf[1024];
556   static char *r = NULL;
557   struct utsname kernel_name;
558 
559   if (r == NULL) {
560     uname(&kernel_name);
561     sprintf(buf, "Client: %s (%s %s %s)",
562 	    kernel_name.nodename,
563 	    kernel_name.sysname,
564 	    kernel_name.release,
565 	    kernel_name.machine);
566     r = ks_strdup(buf);
567   }
568   return r;
569 }
570 #else  /* USE_UNAME */
pipe_exec(cmd,buf,len)571 char *pipe_exec(cmd, buf, len)
572      char *cmd;
573      char *buf;
574      int len;
575 {
576   char *p;
577   FILE *fp;
578 
579   p = NULL;
580   fp = popen(cmd, "r");
581   if (fp != NULL) {
582     if (fgets(buf, len, fp) != NULL) {
583       cut_crlf(buf);
584       p = buf;
585     }
586     pclose(fp);
587   }
588   return p;
589 }
590 
get_client_info()591 char *get_client_info()
592 {
593   char *p;
594   char *s;
595   char buf[1024];
596   char buf1[256];
597   char buf2[256];
598   static char *r = NULL;
599   static char unknown_name[] = "(unknown)";
600 
601   if (r == NULL) {
602     p = pipe_exec("uname -n", buf1, sizeof(buf1));
603     if (p == NULL)
604       p = getenv("HOSTNAME");
605     if (p == NULL)
606       p = getenv("HOST");
607     if (p == NULL)
608       p = unknown_name;
609     s = pipe_exec("uname -smr", buf2, sizeof(buf2));
610     if (s == NULL)
611       s = getenv("HOSTTYPE");
612     if (s == NULL)
613       s = unknown_name;
614     sprintf(buf, "Client: %s (%s)", p, s);
615     r = ks_strdup(buf);
616   }
617   return r;
618 }
619 #endif  /* USE_UNAME */
620 
621 /* call after display connection is opened! */
get_server_info()622 char *get_server_info()
623 {
624   char buf[1024];
625   static char *r = NULL;
626 
627   if (r == NULL) {
628     sprintf(buf, "Server: %s (%s)", DisplayString(dsp), ServerVendor(dsp));
629     r = ks_strdup(buf);
630   }
631   return r;
632 }
633 
get_visual_info()634 char *get_visual_info()
635 {
636   int i;
637   char *p;
638   char buf[1024];
639   static char *r = NULL;
640   static struct {
641     int class;
642     char *name;
643   } vistbl[] = {
644     {StaticGray,	"StaticGray"},
645     {GrayScale,		"GrayScale"},
646     {StaticColor,	"StaticColor"},
647     {PseudoColor,	"PseudoColor"},
648     {TrueColor,		"TrueColor"},
649     {DirectColor,	"DirectColor"},
650     {-1,		NULL}
651   };
652 
653   if (r == NULL) {
654     p = "(unknown)";
655     for (i = 0; vistbl[i].name != NULL; i++) {
656       if (vis->class == vistbl[i].class) {
657 	p = vistbl[i].name;
658 	break;
659       }
660     }
661     if (vis->class == TrueColor || vis->class == DirectColor) {
662       sprintf(buf, "Visual: %s (depth %d, R:%08lx, G:%08lx, B:%08lx)",
663 	      p, screen_depth,
664 	      vis->red_mask, vis->green_mask, vis->blue_mask);
665     } else {
666       sprintf(buf, "Visual: %s (depth %d)", p, screen_depth);
667     }
668     r = ks_strdup(buf);
669   }
670   return r;
671 }
672 
673 /* call after read_cells */
get_cell_info()674 char *get_cell_info()
675 {
676   char buf[1024];
677   static char *r = NULL;
678 
679   if (r == NULL) {
680     sprintf(buf, "Total %d cells, %d objects, %d marks",
681 	    celcnt, objcnt2, objcnt);
682     r = ks_strdup(buf);
683   }
684   return r;
685 }
686 
draw_aboutwin()687 void draw_aboutwin()
688 {
689   int i, y;
690   char buf[1024];
691 
692   if (about_mode == 1) {
693     draw_data_comment();
694     return;
695   }
696   y = (viewh - ((font_ascent + font_descent + ABOUT_LINE_MARGIN) * (12+arcfilecnt)))/3;
697   draw_about_line(&y, str_fullname);
698   sprintf(buf, "Version %s", str_version);
699   draw_about_line(&y, buf);
700   sprintf(buf, "written by %s", str_author);
701   draw_about_line(&y, buf);
702   draw_about_line(&y, get_client_info());
703   draw_about_line(&y, get_server_info());
704   draw_about_line(&y, get_visual_info());
705   draw_about_line(&y, "");
706   for (i = 0; i < arcfilecnt; i++) {
707     sprintf(buf, "Archive %d: %s", i+1, *(arcfilelist+i));
708     draw_about_line(&y, buf);
709   }
710   sprintf(buf, "Configuration file: %s", conf_file);
711   draw_about_line(&y, buf);
712   sprintf(buf, "Size: %dx%d (%dx%d)", imgw, imgh, imgw0, imgh0);
713   draw_about_line(&y, buf);
714   sprintf(buf, "View port: %dx%d%+d%+d",
715 	  vieww, viewh, -imgx-imgbw, -imgy-imgbw);
716   draw_about_line(&y, buf);
717   draw_about_line(&y, get_cell_info());
718   sprintf(buf, "Motion compress: %d", motion_compress);
719   draw_about_line(&y, buf);
720   sprintf(buf, "%s%s", infostr0, infostr);
721   draw_about_line(&y, buf);
722 }
723 
change_menu_func(i)724 void change_menu_func(i)
725      int i;
726 {
727   int s;
728 
729   s = (mwfnc+i)->st;
730   switch(i) {
731   case 0:			/* About */
732     if (++about_mode > 2)
733       about_mode = 0;
734     if (about_mode) {
735       XMapRaised(dsp, aboutwin);
736       XClearArea(dsp, aboutwin, 0, 0, 0, 0, True);
737       s |= 2;
738     } else {
739       XUnmapWindow(dsp, aboutwin);
740       s &= ~2;
741     }
742     break;
743   case 1:			/* Quit */
744     s ^= 2;
745     quit_flag = !quit_flag;
746     break;
747   case 2:			/* Doc */
748     /* Quick and darty hack! Not smart, Sorry */
749     s |= 2;
750     change_menu_status((mwfnc+i)->win, (mwfnc+i)->st = s);
751     browse_document();
752     s = 0;
753     break;
754   }
755   change_menu_status((mwfnc+i)->win, (mwfnc+i)->st = s);
756 }
757 
expose_menu(p)758 void expose_menu(p)
759      XExposeEvent *p;
760 {
761   int i;
762   Window win;
763   char buf[16];
764 
765   if (p->count)
766     return;
767   win = p->window;
768   if (win == aboutwin) {
769     draw_aboutwin();
770   } else if (win == aboutokwin) {
771     draw_button(win, aboutokstat, aboutokw, aboutokh, str_ok);
772   } else if (win == infowin) {
773     draw_button(win, 0, infow, infoh, infostr);
774   } else if (win == setbasewin) {
775     draw_button(win, 0, mnbsetw0, mnbseth, str_setbase);
776   } else if (win == palbasewin) {
777     draw_button(win, 0, mnbpalw0, mnbpalh, str_palbase);
778   } else {
779     i = which_winlist(win, mwfnc);
780     if (i >= 0)
781       draw_button((mwfnc+i)->win, (mwfnc+i)->st, (mwfnc+i)->w, mnfnch, fncstr[i]);
782     i = which_winlist(win, mwset);
783     if (i >= 0) {
784       sprintf(buf, "%d", i);
785       draw_button(win, (mwset+i)->st | (i == cset ? 2 : 0),
786 		  mnsetw, mnseth, buf);
787     }
788     i = which_winlist(win, mwpal);
789     if (i >= 0) {
790       sprintf(buf, "%d", i);
791       draw_button(win, (mwpal+i)->st | (i == cpal ? 2 : 0),
792 		  mnpalw, mnpalh, buf);
793     }
794   }
795 }
796 
797 /* Press or Release mouse buttons */
press_menu(p)798 void press_menu(p)
799      XButtonEvent *p;
800 {
801   int i;
802   Window win;
803 
804   win = p->window;
805   if (win == aboutokwin) {
806     if (p->type == ButtonRelease && (aboutokstat & 1)) {
807       change_menu_func(0);
808     }
809   }
810   i = which_winlist(win, mwfnc);
811   switch (i) {
812   case 0:
813   case 1:
814     if (p->type == ButtonRelease)
815       change_menu_func(i);
816     break;
817   case 2:
818     if (p->type == ButtonPress)
819       change_menu_func(i);
820     break;
821   }
822   if (p->type == ButtonRelease) {
823     i = which_winlist(win, mwset);
824     if (i >= 0)
825       change_setpal(i, -1);
826     i = which_winlist(win, mwpal);
827     if (i >= 0)
828       change_setpal(-1, i);
829   }
830 }
831 
enter_mw(win,p)832 int enter_mw(win, p)
833      Window win;
834      MW *p;
835 {
836   int i;
837 
838   i = which_winlist(win, p);
839   if (i >= 0)
840     change_menu_status(win, (p+i)->st |= 1);
841   return i;
842 }
843 
enter_menu(p)844 void enter_menu(p)
845      XCrossingEvent *p;
846 {
847   Window win;
848 
849   win = p->window;
850   if (win == aboutokwin)
851     change_menu_status(win, aboutokstat |= 1);
852   enter_mw(win, mwfnc);
853   enter_mw(win, mwset);
854   enter_mw(win, mwpal);
855 }
856 
leave_mw(win,p)857 int leave_mw(win, p)
858      Window win;
859      MW *p;
860 {
861   int i;
862 
863   i = which_winlist(win, p);
864   if (i >= 0)
865     change_menu_status(win, (p+i)->st &= ~1);
866   return i;
867 }
868 
leave_menu(p)869 void leave_menu(p)
870      XCrossingEvent *p;
871 {
872   Window win;
873 
874   win = p->window;
875   if (win == aboutokwin)
876     change_menu_status(win, aboutokstat &= ~1);
877   leave_mw(win, mwfnc);
878   leave_mw(win, mwset);
879   leave_mw(win, mwpal);
880 }
881 
menu_setpal_change()882 void menu_setpal_change()
883 {
884   int i;
885 
886   for (i = 0; i < setcnt; i++) {
887     if (active_set[i]) {
888       if (i == cset) {
889 	change_menu_status((mwset+i)->win, (mwset+i)->st |= 2);
890       } else {
891 	if ((mwset+i)->st & 2)
892 	  change_menu_status((mwset+i)->win, (mwset+i)->st &= ~2);
893       }
894     }
895   }
896   for (i = 0; i < palcnt; i++) {
897     if (i == cpal) {
898       change_menu_status((mwpal+i)->win, (mwpal+i)->st |= 2);
899     } else {
900       if ((mwpal+i)->st & 2)
901 	change_menu_status((mwpal+i)->win, (mwpal+i)->st &= ~2);
902     }
903   }
904 }
905 
906 /* End of file */
907