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