1 /*
2 **
3 ** miscmenu.c
4 **
5 ** Copyright (C) 1995, 1996, 1997 Johannes Plass
6 ** Copyright (C) 2004 Jose E. Marchesi
7 **
8 ** This program is free software; you can redistribute it and/or modify
9 ** it under the terms of the GNU General Public License as published by
10 ** the Free Software Foundation; either version 3 of the License, or
11 ** (at your option) any later version.
12 **
13 ** This program is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ** GNU General Public License for more details.
17 **
18 ** You should have received a copy of the GNU General Public License
19 ** along with GNU gv; see the file COPYING. If not, write to
20 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 ** Boston, MA 02111-1307, USA.
22 **
23 ** Author: Johannes Plass (plass@thep.physik.uni-mainz.de)
24 ** Department of Physics
25 ** Johannes Gutenberg-University
26 ** Mainz, Germany
27 **
28 ** Jose E. Marchesi (jemarch@gnu.org)
29 ** GNU Project
30 **
31 */
32 #include "ac_config.h"
33
34 /*
35 #define MESSAGES
36 */
37 #include "message.h"
38
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <math.h>
42
43 #include "paths.h"
44 #include INC_X11(Intrinsic.h)
45 #include INC_X11(StringDefs.h)
46 #include INC_XAW(SimpleMenu.h)
47 #include INC_XAW(SmeBSB.h)
48 #include INC_XAW(SmeLine.h)
49 #include INC_XAW(Cardinals.h)
50 #include INC_XAW(Scrollbar.h)
51
52 #include "types.h"
53 #include "actions.h"
54 #include "callbacks.h"
55 #include "miscmenu.h"
56 #include "options.h"
57 #include "main_resources.h"
58 #include "main_globals.h"
59
60 #include <string.h>
61
62 static MiscMenuEntryStruct miscmenu_entries[] = {
63 { "update",cb_checkFile,(XtPointer)CHECK_FILE_DATE,2 },
64 { "redisplay",cb_redisplay,NULL,3 },
65 { "toggle_current" , cb_setPageMark, (XtPointer)(SPM_CURRENT|SPM_TOGGLE),1 },
66 { "toggle_even" , cb_setPageMark, (XtPointer)(SPM_EVEN|SPM_TOGGLE),1 },
67 { "toggle_odd" , cb_setPageMark, (XtPointer)(SPM_ODD|SPM_TOGGLE),1 },
68 { "unmark",cb_setPageMark,(XtPointer)(SPM_ALL|SPM_UNMARK),1 },
69 { "stop",cb_stopInterpreter,NULL,0 },
70 { "print_all", cb_print, (XtPointer)PAGE_MODE_ALL,3 },
71 { "print_marked",cb_print , (XtPointer)(PAGE_MODE_MARKED|PAGE_MODE_CURRENT),1 },
72 { "save_all", cb_save, (XtPointer)PAGE_MODE_ALL, 3 },
73 { "save_marked",cb_save , (XtPointer)(PAGE_MODE_MARKED|PAGE_MODE_CURRENT),1 },
74 { "line",NULL,NULL,0 },
75 { NULL,NULL,NULL,0 }
76 };
77
78 /*##################################################
79 miscmenu_freeMiscMenuEntries
80 ##################################################*/
81
miscmenu_freeMiscMenuEntries(entries)82 void miscmenu_freeMiscMenuEntries(entries)
83 MiscMenuEntry *entries;
84 {
85 int i=0;
86 BEGINMESSAGE(miscmenu_freeMiscMenuEntries)
87 while (entries[i]) {
88 XtFree((XtPointer)entries[i]);
89 i++;
90 }
91 XtFree((XtPointer)entries);
92 ENDMESSAGE(miscmenu_freeMiscMenuEntries)
93 }
94
95 /*##################################################
96 miscmenu_parseMiscMenuEntries
97 ##################################################*/
98
miscmenu_mallocMiscMenuEntry(void)99 static MiscMenuEntry miscmenu_mallocMiscMenuEntry(void)
100 {
101 MiscMenuEntry entry;
102 entry = (MiscMenuEntry) XtMalloc(sizeof(MiscMenuEntryStruct));
103 memset((void*)entry ,0,sizeof(MiscMenuEntryStruct));
104 return entry;
105 }
106
miscmenu_parseMiscMenuEntries(s)107 MiscMenuEntry *miscmenu_parseMiscMenuEntries(s)
108 char *s;
109 {
110 char *c,*nl;
111 MiscMenuEntry *entries,*mentries,entry;
112 int i,j,n,have_entry=0;
113 char name[100];
114
115 BEGINMESSAGE(miscmenu_parseMiscMenuEntries)
116 if (!s) s = "";
117 s =options_squeezeMultiline(s);
118 for (n=1,c=s; (c = strchr(c,'\n')); n++, c++);
119 INFIMESSAGE(number of entries,n)
120 mentries = entries = (MiscMenuEntry*) XtMalloc((n+2)*sizeof(MiscMenuEntry));
121 c=s;
122 if (*s) while (n>0) {
123 nl = strchr(c,'\n');
124 if (nl) *nl='\0';
125 name[0]='\0';
126 if (*c == '#' || *c == '!') i=0;
127 else i=sscanf(c," %99s ",name);
128 if (i==1) {
129 for (j=0; miscmenu_entries[j].name; j++)
130 if (!strcasecmp(miscmenu_entries[j].name,name)) {
131 entry = miscmenu_mallocMiscMenuEntry();
132 *entry = miscmenu_entries[j];
133 have_entry = 1;
134 *entries++ = entry;
135 }
136 }
137 n--;
138 if (!nl) break;
139 c=++nl;
140 }
141 if (!have_entry) {
142 entry = miscmenu_mallocMiscMenuEntry();
143 *entry = miscmenu_entries[0];
144 *entries++ = entry;
145 }
146 *entries = (MiscMenuEntry) NULL;
147 XtFree(s);
148 ENDMESSAGE(miscmenu_parseMiscMenuEntries)
149 return(mentries);
150 }
151
152 /*############################################################*/
153 /* miscmenu_a_miscMenu */
154 /*############################################################*/
155
156 #define MISC_MENU_IDLE (1<<0)
157 #define MISC_MENU_STATE_1 (1<<1)
158 #define MISC_MENU_STATE_2 (1<<2)
159 #define MISC_MENU_INIT (1<<3)
160 #define MISC_MENU_POPUP (1<<4)
161 #define MISC_MENU_RESET (1<<5)
162 #define MISC_MENU_CHECK (1<<6)
163
miscmenu_a_miscMenu(w,event,params,num_params)164 void miscmenu_a_miscMenu(w, event, params, num_params)
165 Widget w;
166 XEvent *event;
167 String *params;
168 Cardinal *num_params;
169 {
170 static int mode = MISC_MENU_IDLE;
171 static Widget gvw = (Widget)NULL;
172 static Widget menuwidget = (Widget)NULL;
173 static int xo=0,yo=0;
174 int x,y;
175
176 BEGINMESSAGE(miscmenu_a_miscMenu)
177
178 if (!event) {
179 INFMESSAGE(received reset request)
180 if (menuwidget) XtDestroyWidget(menuwidget);
181 menuwidget = (Widget)NULL;
182 gvw = (Widget)NULL;
183 mode = MISC_MENU_IDLE;
184 ENDMESSAGE(miscmenu_a_miscMenu)
185 return;
186 }
187
188 if (*num_params < 1) {
189 INFMESSAGE(no parameter)
190 ENDMESSAGE(miscmenu_a_miscMenu)
191 return;
192 }
193
194 # define MISC_MENU_HAVE(aaa,bbb) (!strcmp(params[0],(aaa)) && mode&(bbb))
195 if MISC_MENU_HAVE("init" , MISC_MENU_IDLE) mode = (MISC_MENU_INIT | MISC_MENU_STATE_1);
196 else if MISC_MENU_HAVE("popup" , MISC_MENU_STATE_1) mode = (MISC_MENU_POPUP | MISC_MENU_STATE_2);
197 else if MISC_MENU_HAVE("check" , MISC_MENU_STATE_2) mode = (MISC_MENU_CHECK | MISC_MENU_STATE_2);
198 else if MISC_MENU_HAVE("reset" , (MISC_MENU_IDLE|MISC_MENU_STATE_1|MISC_MENU_STATE_2))
199 mode = (MISC_MENU_RESET | MISC_MENU_STATE_2);
200 else {
201 INFMESSAGE(no mode)
202 ENDMESSAGE(miscmenu_a_miscMenu)
203 return;
204 }
205 # undef MISC_MENU_HAVE
206
207 if (mode & MISC_MENU_INIT) {
208 INFMESSAGE(MISC_MENU_INIT)
209 if (w==page && (event->type == ButtonRelease || event->type == ButtonPress)) {
210 xo = (int) event->xbutton.x_root;
211 yo = (int) event->xbutton.y_root;
212 gvw = w;
213 } else {
214 INFMESSAGE(event not in main window or not a button press or button release)
215 mode = MISC_MENU_IDLE;
216 }
217 ENDMESSAGE(miscmenu_a_miscMenu)
218 return;
219 }
220
221 if (mode & MISC_MENU_POPUP) {
222 Arg args[4];
223 Cardinal n;
224 Widget entry=NULL;
225
226 INFMESSAGE(MISC_MENU_POPUP)
227
228 if (event->type != ButtonRelease && event->type != ButtonPress) {
229 INFMESSAGE(event not a button press or button release)
230 miscmenu_a_miscMenu(gvw,(XEvent*)NULL,NULL,NULL);
231 ENDMESSAGE(miscmenu_a_miscMenu)
232 return;
233 }
234 x = (int) event->xbutton.x_root;
235 y = (int) event->xbutton.y_root;
236 if (abs(x-xo)>1 || abs(y-yo)>1) {
237 INFMESSAGE(succesive events are unrelated)
238 miscmenu_a_miscMenu(gvw,(XEvent*)NULL,NULL,NULL);
239 ENDMESSAGE(miscmenu_a_miscMenu)
240 return;
241 }
242 menuwidget = XtCreatePopupShell("miscMenu", simpleMenuWidgetClass,w,NULL,(Cardinal)0);
243 {
244 int i;
245 MiscMenuEntry e;
246 int menu_x, menu_y;
247 Dimension menu_width,menu_height,entry_height,menu_border;
248 Dimension screen_width,screen_height;
249 Position button_x, button_y;
250 for (i=0; gv_miscmenu_entries[i]; i++) {
251 e = gv_miscmenu_entries[i];
252 SMESSAGE(e->name)
253 if (strcasecmp(e->name,"line")) {
254 entry = XtCreateManagedWidget(e->name, smeBSBObjectClass,menuwidget,NULL,(Cardinal)0);
255 if (e->cb) XtAddCallback(entry,XtNcallback,e->cb,e->client_data);
256 if (e->sensitivity_type) {
257 Boolean b;
258 if (e->sensitivity_type==1) b = (toc_text != NULL);
259 else if (e->sensitivity_type==2) b = (gv_filename != NULL);
260 else b = (gv_psfile != NULL || (gv_gs_arguments && *gv_gs_arguments));
261 XtSetSensitive(entry,b);
262 }
263 } else {
264 XtCreateManagedWidget("line", smeLineObjectClass,menuwidget,NULL,(Cardinal)0);
265 }
266 }
267
268 if (!XtIsRealized(menuwidget)) XtRealizeWidget(menuwidget);
269
270 n=0;
271 XtSetArg(args[n], XtNheight, &entry_height); ++n;
272 XtGetValues(entry, args, n);
273
274 n=0;
275 XtSetArg(args[n], XtNwidth, &menu_width); ++n;
276 XtSetArg(args[n], XtNheight, &menu_height); ++n;
277 XtSetArg(args[n], XtNborderWidth, &menu_border); ++n;
278 XtGetValues(menuwidget, args, n);
279
280 XtTranslateCoords(w, event->xbutton.x, event->xbutton.y, &button_x, &button_y);
281 menu_x = button_x-menu_width/2 -menu_border;
282 menu_y = button_y-entry_height/2;
283
284 screen_width = WidthOfScreen(XtScreen(menuwidget));
285 screen_height = HeightOfScreen(XtScreen(menuwidget));
286
287 if( menu_x + menu_width > screen_width && menu_width < screen_width )
288 menu_x = screen_width - menu_width;
289 if( menu_y + menu_height > screen_height && menu_height < screen_height )
290 menu_y = screen_height - menu_height;
291
292 n=0;
293 XtSetArg(args[n], XtNx, menu_x); n++;
294 XtSetArg(args[n], XtNy, menu_y); n++;
295 XtSetValues(menuwidget, args, n);
296 XtPopup(menuwidget,XtGrabExclusive);
297 }
298 ENDMESSAGE(miscmenu_a_miscMenu)
299 return;
300 }
301
302 if (mode & MISC_MENU_CHECK) {
303 INFMESSAGE(MISC_MENU_CHECK)
304 if (menuwidget) {
305 Arg args[5];
306 Cardinal n;
307 Position ulx,uly,lrx,lry,evx,evy;
308 int rx,ry;
309 Dimension width,height;
310 n=0;
311 XtSetArg(args[n], XtNwidth, &width); n++;
312 XtSetArg(args[n], XtNheight, &height); n++;
313 XtGetValues(menuwidget, args, n);
314 XtTranslateCoords(menuwidget, 0, 0, &ulx, &uly);
315 XtTranslateCoords(menuwidget, (Position)width, (Position)height, &lrx, &lry);
316 IIMESSAGE(ulx,uly)
317 IIMESSAGE(lrx,lry)
318 {
319 Window root, child;
320 int dummyx, dummyy;
321 unsigned int dummymask;
322 XQueryPointer(XtDisplay(w), XtWindow(w), &root, &child, &rx, &ry,
323 &dummyx, &dummyy, &dummymask);
324 }
325 evx = (Position)rx;
326 evy = (Position)ry;
327 IIMESSAGE(evx,evy)
328 if (evx<=ulx || evx >= lrx || evy <= uly || evy >= lry) {
329 INFMESSAGE(pointer outside window)
330 mode = mode | MISC_MENU_RESET;
331 }
332 }
333 }
334
335 if (mode & MISC_MENU_RESET) {
336 INFMESSAGE(MISC_MENU_RESET)
337 miscmenu_a_miscMenu(gvw,(XEvent*)NULL,NULL,NULL);
338 }
339
340 ENDMESSAGE(miscmenu_a_miscMenu)
341 }
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366