1 /*
2 **
3 ** magmenu.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 #include "ac_config.h"
32
33 /*
34 #define MESSAGES
35 */
36 #include "message.h"
37
38 #include <stdlib.h>
39 #include <math.h>
40
41 #include "paths.h"
42 #include INC_X11(Intrinsic.h)
43 #include INC_X11(StringDefs.h)
44 #include INC_XAW(SimpleMenu.h)
45 #include INC_XAW(SmeBSB.h)
46 #include INC_XAW(SmeLine.h)
47 #include INC_XAW(Cardinals.h)
48 #include INC_XAW(Scrollbar.h)
49 #include "Ghostview.h"
50
51 #include "types.h"
52 #include "actions.h"
53 #include "magmenu.h"
54 #include "options.h"
55 #include "main_resources.h"
56 #include "main_globals.h"
57 #include "zoom.h"
58
59 /*##################################################
60 magmenu_freeMagMenuEntries
61 ##################################################*/
62
magmenu_freeMagMenuEntries(entries)63 void magmenu_freeMagMenuEntries(entries)
64 MagMenuEntry *entries;
65 {
66 int i=0;
67 BEGINMESSAGE(magmenu_freeMagMenuEntries)
68 while (entries[i]) {
69 XtFree(entries[i]->name);
70 XtFree((XtPointer)entries[i]);
71 i++;
72 }
73 XtFree((XtPointer)entries);
74 ENDMESSAGE(magmenu_freeMagMenuEntries)
75 }
76
77 /*##################################################
78 magmenu_parseMagMenuEntries
79 ##################################################*/
80
magmenu_mallocMagMenuEntry(void)81 static MagMenuEntry magmenu_mallocMagMenuEntry(void)
82 {
83 MagMenuEntry entry;
84 entry = (MagMenuEntry) XtMalloc(sizeof(MagMenuEntryStruct));
85 memset((void*)entry ,0,sizeof(MagMenuEntryStruct));
86 return entry;
87 }
88
magmenu_parseMagMenuEntries(s)89 MagMenuEntry *magmenu_parseMagMenuEntries(s)
90 char *s;
91 {
92 char *c,*nl;
93 MagMenuEntry *entries,*mentries,entry;
94 int i,n,have_entry=0;
95 float f;
96 char name[100];
97
98 BEGINMESSAGE(magmenu_parseMagMenuEntries)
99 if (!s) s = "";
100 s =options_squeezeMultiline(s);
101 for (n=1,c=s; (c = strchr(c,'\n')); n++, c++);
102 INFIMESSAGE(number of medias,n)
103 mentries = entries = (MagMenuEntry*) XtMalloc((n+2)*sizeof(MagMenuEntry));
104 c=s;
105 if (*s) while (n>0) {
106 nl = strchr(c,'\n');
107 if (nl) *nl='\0';
108 name[0]='\0';
109 if (*c == '#' || *c == '!') i=0;
110 else i=sscanf(c," %[^,] , %f ",name,&f);
111 if (i==2 && f>0) {
112 entry = magmenu_mallocMagMenuEntry();
113 entry->name = XtNewString(name);
114 entry->scale= sqrt(f);
115 have_entry = 1;
116 INFSMESSAGE(found entry,entry->name)
117 FMESSAGE(entry->scale)
118 *entries++ = entry;
119 }
120 n--;
121 if (!nl) break;
122 c=++nl;
123 }
124 if (!have_entry) {
125 entry = magmenu_mallocMagMenuEntry();
126 entry->name = XtNewString(" 2 ");
127 entry->scale= sqrt(2.0);
128 *entries++ = entry;
129 }
130 *entries = (MagMenuEntry) NULL;
131 XtFree(s);
132 ENDMESSAGE(magmenu_parseMagMenuEntries)
133 return(mentries);
134 }
135
136 /*############################################################*/
137 /* magmenu_a_magMenu */
138 /*############################################################*/
139
140 typedef struct
141 {
142 Position locx1,locy1,locx2,locy2;
143 Position oldx,oldy,oldwidth,oldheight;
144 Widget menuwidget;
145 } magMenu_data;
146
147 #define MAG_INIT_0 (1<<0)
148 #define MAG_INIT_1 (1<<1)
149 #define MAG_INIT_2 (1<<2)
150 #define MAG_BEGIN (1<<3)
151 #define MAG_EXTEND (1<<4)
152 #define MAG_CHOOSE (1<<5)
153 #define MAG_SHOW (1<<6)
154 #define MAG_RESET (1<<7)
155 #define MAG_CHECK (1<<8)
156
157 void
magmenu_a_magMenu(w,event,params,num_params)158 magmenu_a_magMenu (w, event, params, num_params)
159 Widget w;
160 XEvent *event;
161 String *params;
162 Cardinal *num_params;
163 {
164 static magMenu_data *d = (magMenu_data *)NULL;
165 static int mode=MAG_INIT_0;
166 GhostviewReturnStruct ret_val;
167 Bool popup_zoom = False;
168 static Widget gvw = NULL;
169
170 BEGINMESSAGE(magmenu_a_magMenu)
171
172 if (!event) {
173 INFMESSAGE(received reset request)
174 if (d) {
175 INFMESSAGE(resetting)
176 if (d->menuwidget) XtDestroyWidget(d->menuwidget);
177 XtFree((char*)d);
178 d = (magMenu_data *)NULL;
179 }
180 mode = MAG_INIT_0;
181 ENDMESSAGE(magmenu_a_magMenu)
182 return;
183 }
184
185 if (*num_params < 1) {
186 INFMESSAGE(no parameter) ENDMESSAGE(magmenu_a_magMenu)
187 return;
188 }
189
190 # define MAG_HAVE(aaa,bbb) (!strcmp(params[0],(aaa)) && mode&(bbb))
191 if MAG_HAVE("begin" , MAG_INIT_0) mode = (MAG_BEGIN | MAG_INIT_1);
192 else if MAG_HAVE("extend" , MAG_INIT_1) mode = (MAG_EXTEND | MAG_INIT_1);
193 else if MAG_HAVE("choose" , MAG_INIT_1) mode = (MAG_CHOOSE | MAG_INIT_2);
194 else if MAG_HAVE("check" , MAG_INIT_2) mode = (MAG_CHECK | MAG_INIT_2);
195 else if MAG_HAVE("show" , MAG_INIT_2) mode = (MAG_SHOW|MAG_RESET | MAG_INIT_2);
196 else if MAG_HAVE("reset" , (MAG_INIT_0|MAG_INIT_1|MAG_INIT_2))
197 mode = (MAG_RESET | MAG_INIT_2);
198 else {
199 INFMESSAGE(no mode) ENDMESSAGE(magmenu_a_magMenu)
200 return;
201 }
202 # undef MAG_HAVE
203
204 if (mode&MAG_BEGIN) {
205 INFMESSAGE(MAG_BEGIN)
206 gvw = w;
207 d = (magMenu_data *) XtMalloc(sizeof(magMenu_data));
208 d->locx1 = event->xbutton.x;
209 d->locy1 = event->xbutton.y;
210 d->menuwidget = NULL;
211 IIMESSAGE(d->locx1,d->locy1)
212 d->oldwidth=d->oldheight=0;
213 ENDMESSAGE(magmenu_a_magMenu)
214 return;
215 }
216
217 if (mode&MAG_EXTEND) {
218 Position x,y;
219 Dimension width,height;
220 INFMESSAGE(MAG_EXTEND)
221 d->locx2=event->xbutton.x;
222 d->locy2=event->xbutton.y;
223 if (d->locx2 > d->locx1) { x=d->locx1; width =(Dimension)(d->locx2-d->locx1); }
224 else { x=d->locx2; width =(Dimension)(d->locx1-d->locx2); }
225 if (d->locy2 > d->locy1) { y=d->locy1; height=(Dimension)(d->locy2-d->locy1); }
226 else { y=d->locy2; height=(Dimension)(d->locy1-d->locy2); }
227
228 if (d->oldwidth && d->oldheight)
229 GhostviewDrawRectangle(gvw,d->oldx,d->oldy,d->oldwidth,d->oldheight);
230 if (width && height)
231 GhostviewDrawRectangle(gvw,x,y,width,height);
232 d->oldx=x; d->oldy=y; d->oldwidth=width; d->oldheight=height;
233 ENDMESSAGE(magmenu_a_magMenu)
234 return;
235 }
236
237 if (mode&MAG_CHOOSE) {
238 Arg args[5];
239 Cardinal n;
240 Widget entry = NULL;
241 String name = "magMenu";
242 int i;
243
244 INFMESSAGE(MAG_CHOOSE)
245 d->menuwidget = XtCreatePopupShell(name, simpleMenuWidgetClass,w,NULL,(Cardinal)0);
246 for (i=0; gv_magmenu_entries[i] ; i++)
247 entry = XtCreateManagedWidget(gv_magmenu_entries[i]->name, smeBSBObjectClass,d->menuwidget,NULL,(Cardinal)0);
248 {
249 int menu_x, menu_y;
250 Dimension menu_width,entry_height,menu_border,menu_height;
251 Dimension screen_width,screen_height;
252 Position button_x, button_y;
253
254 if (!XtIsRealized(d->menuwidget)) XtRealizeWidget(d->menuwidget);
255 n=0;
256 XtSetArg(args[n], XtNheight, &entry_height); ++n;
257 XtGetValues(entry, args, n);
258 n=0;
259 XtSetArg(args[n], XtNwidth, &menu_width); ++n;
260 XtSetArg(args[n], XtNheight, &menu_height); ++n;
261 XtSetArg(args[n], XtNborderWidth, &menu_border); ++n;
262 XtGetValues(d->menuwidget, args, n);
263
264 XtTranslateCoords(w, event->xbutton.x, event->xbutton.y, &button_x, &button_y);
265 menu_x = button_x-menu_width/2 -menu_border;
266 menu_y = button_y-entry_height/2;
267
268 screen_width = WidthOfScreen(XtScreen(d->menuwidget));
269 screen_height = HeightOfScreen(XtScreen(d->menuwidget));
270
271 if( menu_x + menu_width > screen_width && menu_width < screen_width )
272 menu_x = screen_width - menu_width;
273 if( menu_y + menu_height > screen_height && menu_height < screen_height )
274 menu_y = screen_height - menu_height;
275 n=0;
276 XtSetArg(args[n], XtNx, menu_x); n++;
277 XtSetArg(args[n], XtNy, menu_y); n++;
278 XtSetValues(d->menuwidget, args, n);
279 XtPopup(d->menuwidget,XtGrabExclusive);
280 }
281
282 d->locx2=event->xbutton.x;
283 d->locy2=event->xbutton.y;
284 IIMESSAGE(d->locx2,d->locy2)
285 ENDMESSAGE(magmenu_a_magMenu)
286 return;
287 }
288
289 if (mode&MAG_SHOW) {
290 Widget entry = XawSimpleMenuGetActiveEntry(d->menuwidget);
291 INFMESSAGE(MAG_SHOW)
292 if (entry) {
293 Position locx,locy;
294 char *s;
295 int i=0;
296 float scale;
297
298 s = XtName(entry);
299 i=0; while (strcmp(gv_magmenu_entries[i]->name,s)) i++;
300 scale = gv_magmenu_entries[i]->scale;
301
302 locx = (d->locx1+d->locx2)/2;
303 locy = (d->locy1+d->locy2)/2;
304 if (abs(d->locx1-d->locx2)<4 || abs(d->locy1-d->locy2)<4) {
305 int dd=250/scale;
306 d->locx1 = locx-dd; d->locx2 = locx+dd;
307 d->locy1 = locy-dd; d->locy2 = locy+dd;
308 }
309 GhostviewGetBBofArea(gvw,d->locx1,d->locy1,d->locx2,d->locy2,&ret_val);
310 ret_val.xdpi = (ret_val.xdpi/scale);
311 ret_val.ydpi = (ret_val.ydpi/scale);
312 if (ret_val.width && ret_val.height) popup_zoom = True;
313 }
314 }
315
316 if (mode&MAG_CHECK) {
317 INFMESSAGE(MAG_CHECK)
318 if (d->menuwidget) {
319 Arg args[5];
320 Cardinal n;
321 Position ulx,uly,lrx,lry,evx,evy;
322 int rx,ry;
323 Dimension width,height;
324 n=0;
325 XtSetArg(args[n], XtNwidth, &width); n++;
326 XtSetArg(args[n], XtNheight, &height); n++;
327 XtGetValues(d->menuwidget, args, n);
328 XtTranslateCoords(d->menuwidget, 0, 0, &ulx, &uly);
329 XtTranslateCoords(d->menuwidget, (Position)width, (Position)height, &lrx, &lry);
330 IIMESSAGE(ulx,uly)
331 IIMESSAGE(lrx,lry)
332 {
333 Window root, child;
334 int dummyx, dummyy;
335 unsigned int dummymask;
336 XQueryPointer(XtDisplay(w), XtWindow(w), &root, &child, &rx, &ry,
337 &dummyx, &dummyy, &dummymask);
338 }
339 evx = (Position)rx;
340 evy = (Position)ry;
341 IIMESSAGE(evx,evy)
342 if (evx<=ulx || evx >= lrx || evy <= uly || evy >= lry) {
343 INFMESSAGE(pointer outside window)
344 if (d->oldwidth && d->oldheight)
345 GhostviewDrawRectangle(gvw, d->oldx,d->oldy,d->oldwidth,d->oldheight);
346 magmenu_a_magMenu(gvw,(XEvent*)NULL,NULL,NULL);
347 } else {
348 INFMESSAGE(pointer in window)
349 ENDMESSAGE(magmenu_a_magMenu)
350 return;
351 }
352 }
353
354 }
355
356 if (mode&MAG_RESET) {
357 INFMESSAGE(MAG_RESET)
358 if (d) {
359 if (d->oldwidth && d->oldheight)
360 GhostviewDrawRectangle(gvw,d->oldx,d->oldy,d->oldwidth,d->oldheight);
361 }
362 magmenu_a_magMenu(gvw,(XEvent*)NULL,NULL,NULL);
363 }
364
365
366 if (popup_zoom) {
367 INFMESSAGE(popping up zoom window)
368 zoom_createZoom(gvw,(XtPointer)(&ret_val));
369 }
370 gvw = NULL;
371
372 ENDMESSAGE(magmenu_a_magMenu)
373 }
374