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