1 /* $Header: /home/yav/xpx/RCS/sub.c,v 1.30 1996/04/08 18:21:02 yav Exp $
2  * xpx menu subroutines
3  * written by yav (UHD98984@pcvan.or.jp)
4  */
5 
6 #include <X11/Xlib.h>
7 #include <X11/Xutil.h>
8 
9 #include "headers.h"
10 #include "xpx.h"
11 #include "work.h"
12 #include "icondef.h"
13 #define PUBLIC_SUB_C
14 #include "extern.h"
15 
16 char rcsid_sub[] = "$Id: sub.c,v 1.30 1996/04/08 18:21:02 yav Exp $";
17 
18 #define MENUTBLMAX 64
19 static MENU *menutbl[MENUTBLMAX];
20 
get_drawable_size(dr,wp,hp)21 void get_drawable_size(dr, wp, hp)
22      Drawable dr;
23      int *wp;
24      int *hp;
25 {
26   Window root;
27   int x, y;
28   unsigned int width, height, border, depth;
29 
30   XGetGeometry(dsp, dr, &root, &x, &y, &width, &height, &border, &depth);
31   if (wp != NULL)
32     *wp = width;
33   if (hp != NULL)
34     *hp = height;
35 }
36 
get_top_menu(p)37 MENU *get_top_menu(p)
38      MENU *p;
39 {
40   while (p->n)
41     --p;
42   return p;
43 }
44 
45 #define highlightGC(mode) \
46   (((mode) & MenuModeMaskEnter)?(((mode) & MenuModeMaskOn)?gc1:gc0):\
47    (((mode) & MenuModeMaskOn)?gc0:gc1))
48 
menu_highlight(p)49 void menu_highlight(p)
50      MENU *p;
51 {
52   XDrawRectangle(dsp, p->win, highlightGC(p->mode), 0, 0, p->w-1, p->h-1);
53 }
54 
menuwin_strpos_center(wd,fs,str,xp,yp,lp,ascp,desp,w,h)55 void menuwin_strpos_center(wd, fs, str, xp, yp, lp, ascp, desp, w, h)
56      Window wd;
57      XFontStruct *fs;
58      char *str;
59      int *xp;
60      int *yp;
61      int *lp;
62      int *ascp;
63      int *desp;
64      int w;
65      int h;
66 {
67   int len, tw, dir, asc, des;
68   XCharStruct overall;
69 
70   len = strlen(str);
71   tw = XTextWidth(fs, str, len);
72   XTextExtents(fs, str, 0, &dir, &asc, &des, &overall);
73   if (xp != NULL)
74     *xp = (w-tw)/2;
75   if (yp != NULL)
76     *yp = h - (h-(asc+des))/2 - des;
77   if (lp != NULL)
78     *lp = len;
79   if (ascp != NULL)
80     *ascp = asc;
81   if (desp != NULL)
82     *desp = des;
83 }
84 
85 #define menu_fill_black(menup) \
86   XFillRectangle(dsp,(menup)->win,gc0,0,0,(menup)->w,(menup)->h)
87 
draw_center_string(wd,w,h,fs,gc,str)88 void draw_center_string(wd, w, h, fs, gc, str)
89      Window wd;
90      int w;
91      int h;
92      XFontStruct *fs;
93      GC gc;
94      char *str;
95 {
96   int x, y, len;
97 
98   menuwin_strpos_center(wd, fs, str, &x, &y, &len, NULL, NULL, w, h);
99   XDrawImageString(dsp, wd, gc, x, y, str, len);
100 }
101 
menuwin_center(wd,w,h,str)102 void menuwin_center(wd, w, h, str)
103      Window wd;
104      int w;
105      int h;
106      char *str;
107 {
108   draw_center_string(wd, w, h, fs1, gc0, str);
109 }
110 
erase_cursor(p,str)111 void erase_cursor(p, str)
112      MENU *p;
113      char *str;
114 {
115   int x, y, len, asc, des;
116 
117   menuwin_strpos_center(p->win, fs1, str, &x, &y,
118 			&len, &asc, &des, p->w, p->h);
119   if (len)
120     x += XTextWidth(fs1, str, p->cursor);
121   XClearArea(dsp, p->win, x-2, y-asc-1, 5, asc+3, False);
122 }
123 
draw_cursor(MENU * p,char * str)124 void draw_cursor(
125 #if NeedFunctionPrototypes
126 		 MENU *p, char *str)
127 #else
128      p, str)
129      MENU *p;
130      char *str;
131 #endif
132 {
133   int x, y, len, asc, des;
134   GC gc;
135 
136   menuwin_strpos_center(p->win, fs1, str, &x, &y,
137 			&len, &asc, &des, p->w, p->h);
138   if (len)
139     x += XTextWidth(fs1, str, p->cursor);
140   gc = p->mode & MenuModeMaskOn ? gc1 : gc0;
141   XDrawLine(dsp, p->win, gc, x, y-asc, x, y);
142   XDrawLine(dsp, p->win, gc, x, y, x-2, y+1);
143   XDrawLine(dsp, p->win, gc, x, y, x+2, y+1);
144   XDrawLine(dsp, p->win, gc, x, y-asc, x-2, y-asc-1);
145   XDrawLine(dsp, p->win, gc, x, y-asc, x+2, y-asc-1);
146 }
147 
menu_icon_center(p,icon)148 void menu_icon_center(p, icon)
149      MENU *p;
150      int icon;
151 {
152   if (p->mode & MenuModeMaskOn) {
153     menu_fill_black(p);
154     icon |= ICON_REVERSE;
155   }
156   XCopyArea(dsp, icon_pixmap(icon), p->win, gc0,
157 	    0, 0, icon_width(icon), icon_height(icon),
158 	    (p->w-icon_width(icon))/2, (p->h-icon_height(icon))/2);
159   menu_highlight(p);
160 }
161 
menuev_init()162 void menuev_init()
163 {
164   int i;
165 
166   for (i = 0; i < MENUTBLMAX; i++)
167     menutbl[i] = NULL;
168 }
169 
set_menutbl(menu)170 int set_menutbl(menu)
171      MENU *menu;
172 {
173   int i;
174 
175   for (i = 0; i < MENUTBLMAX; i++) {
176     if (menutbl[i] == NULL) {
177       menutbl[i] = menu;
178       return 0;
179     }
180   }
181   return 1;
182 }
183 
unset_menutbl(menu)184 int unset_menutbl(menu)
185      MENU *menu;
186 {
187   int i;
188 
189   for (i = 0; i < MENUTBLMAX; i++) {
190     if (menutbl[i] == menu) {
191       menutbl[i] = NULL;
192       return 0;
193     }
194   }
195   return 1;
196 }
197 
menuwin_create2(MENU * menu,Window parent,int x0,int y0,int mapsw)198 void menuwin_create2(
199 #if NeedFunctionPrototypes
200 			MENU *menu, Window parent, int x0, int y0, int mapsw)
201 #else
202      menu, parent, x0, y0, mapsw)
203      MENU *menu;
204      Window parent;
205 #endif
206 {
207   MENU *p;
208   XSetWindowAttributes attr;
209   int x, y;
210   int parentw, parenth;
211 
212   get_drawable_size(parent, &parentw, &parenth);
213   for (p = menu; p->n >= 0; p++) {
214     if (p->strlen && p->str == NULL) {
215       p->str = malloc(p->strlen);
216       if (p->str == NULL)
217 	error("menuwin_create: more core!");
218       else
219 	*(p->str) = '\0';
220     }
221     x = (p->gr==EastGravity||p->gr==NorthEastGravity||p->gr==SouthEastGravity)
222       ? parentw - p->w - p->x : p->x;
223     y = (p->gr==SouthGravity||p->gr==SouthEastGravity||p->gr==SouthWestGravity)
224       ? parenth - p->h - p->y : p->y;
225     if (p->gr == CenterGravity) {
226       x = (parentw - p->w) / 2 + p->x;
227       y = (parenth - p->h) / 2 + p->y;
228     }
229     p->win =
230       XCreateSimpleWindow(dsp, parent, x0 + x, y0 + y, p->w, p->h,
231 			  p->mode & MenuModeMaskBorder ? BDW : 0, fg, bg);
232     XSelectInput(dsp, p->win, p->im);
233     if (p->gr) {
234       attr.win_gravity = p->gr;
235       XChangeWindowAttributes(dsp, p->win, CWWinGravity, &attr);
236     }
237     if (mapsw)
238       XMapRaised(dsp, p->win);
239   }
240   set_menutbl(menu);
241 }
242 
menuwin_create(MENU * menu,Window parent,int x0,int y0)243 void menuwin_create(
244 #if NeedFunctionPrototypes
245 		    MENU *menu, Window parent, int x0, int y0)
246 #else
247      menu, parent, x0, y0)
248      MENU *menu;
249      Window parent;
250 #endif
251 {
252   menuwin_create2(menu, parent, x0, y0, 1);
253 }
254 
topmenuwin_create(MENU * menu,int x0,int y0)255 void topmenuwin_create(
256 #if NeedFunctionPrototypes
257 		       MENU *menu, int x0, int y0)
258 #else
259      menu, parent, x0, y0)
260      MENU *menu;
261      Window parent;
262 #endif
263 {
264   menuwin_create2(menu, win, x0, y0, menumode);
265 }
266 
menuwin_destroy(menu)267 void menuwin_destroy(menu)
268      MENU *menu;
269 {
270   MENU *p;
271 
272   for (p = menu; p->n >= 0; p++)
273     XDestroyWindow(dsp, p->win);
274   unset_menutbl(menu);
275 }
276 
menuwin_expose_default(p)277 void menuwin_expose_default(p)
278      MENU *p;
279 {
280   char *s;
281   GC gc;
282 
283   s = p->strfunc ? p->strfunc(p) : p->str;
284   if (s == NULL)
285     return;
286   if (p->mode & MenuModeMaskOn) {
287     menu_fill_black(p);
288     gc = gc1;
289   } else {
290     gc = gc0;
291   }
292   if (p->mode & MenuModeMaskLeft)
293     XDrawImageString(dsp, p->win, gc, 2, p->h-5, s, strlen(s));
294   else
295     draw_center_string(p->win, p->w, p->h, fs1, gc, s);
296   if (p->im & (ButtonPressMask|KeyPressMask))
297     menu_highlight(p);
298   /* if highlight on , display input cursor */
299   if ((p->im & KeyPressMask)&&(p->mode & MenuModeMaskEnter))
300     draw_cursor(p, s);
301 }
302 
redraw_window(w)303 void redraw_window(w)
304      Window w;
305 {
306   XClearArea(dsp, w, 0, 0, 0, 0, True);
307 }
308 
menuev_destroy()309 void menuev_destroy()
310 {
311   int i;
312 
313   for (i = MENUTBLMAX-1; i >= 0; --i) {
314     if (menutbl[i] != NULL)
315       menuwin_destroy(menutbl[i]);
316   }
317 }
318 
menuev_event_sub(p,ev)319 void menuev_event_sub(p, ev)
320      MENU *p;
321      XEvent *ev;
322 {
323   int i;
324   short last_mode;
325   char *s;
326 
327   if (p->event != NULL && p->event(p, ev))
328     return;
329   /* default event operation */
330   last_mode = p->mode;
331   switch(ev->type) {
332   case Expose:
333     if (!ev->xexpose.count)
334       menuwin_expose_default(p);
335     return;
336   case GraphicsExpose:
337     if (!ev->xgraphicsexpose.count)
338       menuwin_expose_default(p);
339     return;
340   case NoExpose:
341     return;
342   case ButtonPress:
343     if (p->im & ButtonPressMask) {
344       if (p->im & ButtonReleaseMask)
345 	p->mode |= MenuModeMaskOn; /* select on */
346       else
347 	p->mode ^= MenuModeMaskOn; /* select alternate */
348     }
349     break;
350   case ButtonRelease:
351     if (p->im & ButtonReleaseMask)
352       p->mode &= ~MenuModeMaskOn; /* select off */
353     break;
354   case EnterNotify:
355     if (p->im & (ButtonPressMask|KeyPressMask)) {
356       p->mode |= MenuModeMaskEnter; /* highlight on */
357       if (!(p->im & KeyPressMask)) {
358 	menu_highlight(p);
359 	return;
360       }
361     }
362     break;
363   case LeaveNotify:
364     if (ev->xcrossing.detail == NotifyInferior)
365       return;
366     if (p->im & (ButtonPressMask|KeyPressMask)) {
367       p->mode &= ~MenuModeMaskEnter; /* highlight off */
368       if (!(p->im & KeyPressMask)) {
369 	menu_highlight(p);
370 	return;
371       }
372     }
373     break;
374   case KeyPress:
375     s = p->strfunc ? p->strfunc(p) : p->str;
376     erase_cursor(p, s);
377     i = edit_string(ev, s, p->strlen, &p->cursor);
378     if (i & 2)
379       redraw_window(p->win);
380     else
381       menuwin_expose_default(p);
382     return;
383   }
384   if (p->mode & ~MenuModeMaskEnter == last_mode & ~MenuModeMaskEnter)
385     menuwin_expose_default(p);
386   else
387     redraw_window(p->win);
388 }
389 
get_event_window(ev)390 Drawable get_event_window(ev)
391      XEvent *ev;
392 {
393   Drawable win;
394 
395   win = 0;
396   switch(ev->type) {
397   case Expose:
398     win = ev->xexpose.window;
399     break;
400   case ButtonPress:
401     win = ev->xbutton.window;
402     break;
403   case ButtonRelease:
404     win = ev->xbutton.window;
405     break;
406   case EnterNotify:
407     win = ev->xcrossing.window;
408     break;
409   case LeaveNotify:
410     win = ev->xcrossing.window;
411     break;
412   case KeyPress:
413     win = ev->xkey.window;
414     break;
415   case GraphicsExpose:
416     win = ev->xgraphicsexpose.drawable;
417     break;
418   case NoExpose:
419     win = ev->xnoexpose.drawable;
420     break;
421   case MotionNotify:
422     win = ev->xmotion.window;
423     break;
424   }
425   return win;
426 }
427 
menuev_event(ev)428 void menuev_event(ev)
429      XEvent *ev;
430 {
431   int i;
432   MENU *p;
433   Drawable win;
434 
435   win = get_event_window(ev);
436   if (!win)
437     return;
438   for (i = 0; i < MENUTBLMAX; i++) {
439     for (p = menutbl[i]; p != NULL && p->n >= 0; p++) {
440       if (p->win == win) {
441 	menuev_event_sub(p, ev);
442 	return;
443       }
444     }
445   }
446 }
447 
gen_default_geometry_string(char * p,int w,int h)448 void gen_default_geometry_string(
449 #if NeedFunctionPrototypes
450 				 char *p, int w, int h)
451 #else
452      p, w, h)
453      char *p;
454      int w;
455      int h;
456 #endif
457 {
458   int rootw, rooth;
459 
460   get_drawable_size(DefaultRootWindow(dsp), &rootw, &rooth);
461   sprintf(p, "%dx%d+%d+%d", w, h, (rootw-w)/2, (rooth-h)/2);
462 }
463 
create_toplevel_window(Window * wd,char * name,char * geomstr,int default_width,int default_height)464 int create_toplevel_window(
465 #if NeedFunctionPrototypes
466 		       Window *wd,
467 		       char *name,
468 		       char *geomstr,
469 		       int default_width,
470 		       int default_height)
471 #else
472      wd, name, geomstr, default_width, default_height)
473      Window *wd;
474      char *name;
475      char *geomstr;
476      int default_width;
477      int default_height;
478 #endif
479 {
480   int i;
481   XSizeHints hint;
482   XWMHints wmhint;
483   char buf[256];
484 
485   gen_default_geometry_string(buf, default_width, default_height);
486   i = XGeometry(dsp, scr, geomstr, buf, border_width, 1, 1, 0, 0,
487 		&(hint.x), &(hint.y), &(hint.width), &(hint.height));
488 #if 0
489   if (i & (XValue|YValue))
490     hint.flags |= PPosition;
491   if (i & (WidthValue|HeightValue))
492     hint.flags |= PSize;
493 #else
494   hint.flags = USPosition|USSize;
495 #endif
496   *wd = XCreateSimpleWindow(dsp, DefaultRootWindow(dsp), hint.x, hint.y,
497 			    hint.width, hint.height,
498 			    border_width, border_color, bg);
499   sprintf(buf, "%s %s", myname, name);
500   XSetStandardProperties(dsp, *wd, buf, buf, None, oargv, oargc, &hint);
501   /* window group hint */
502   wmhint.flags = WindowGroupHint;
503   wmhint.window_group = win;
504   XSetWMHints(dsp, *wd, &wmhint);
505   if (toplevelwc < MAXTOPLEVELWINDOW)
506     toplevelwin[toplevelwc++] = *wd;
507   XSetWindowColormap(dsp, *wd, cmap);
508   return 0;
509 }
510 
511 static int cursor_type = 0;
512 
cursor_free(void)513 void cursor_free(
514 #if NeedFunctionPrototypes
515 		 void
516 #endif
517 		 )
518 {
519   int i;
520 
521   if (cursor_type != 0) {
522     cursor_type = 0;
523     for (i = 0; i < toplevelwc; i++)
524       XUndefineCursor(dsp, toplevelwin[i]);
525     XDefineCursor(dsp, imgwin, curs_cross);
526     XFlush(dsp);
527   }
528 }
529 
cursor_busy(void)530 void cursor_busy(
531 #if NeedFunctionPrototypes
532 		 void
533 #endif
534 		 )
535 {
536   int i;
537 
538   if (cursor_type != 1) {
539     cursor_type = 1;
540     for (i = 0; i < toplevelwc; i++)
541       XDefineCursor(dsp, toplevelwin[i], curs_watch);
542     XDefineCursor(dsp, imgwin, curs_watch);
543     XFlush(dsp);
544   }
545 }
546 
547 /* End of file */
548