1 /*
2 **
3 ** actions.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 ** Authors:   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 #include "message.h"
34 
35 #include "config.h"
36 
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40 #include <math.h>
41 
42 #include <inttypes.h>
43 
44 #include "paths.h"
45 #include INC_X11(Intrinsic.h)
46 #include INC_X11(StringDefs.h)
47 #include INC_XAW(Cardinals.h)
48 #include INC_XAW(SimpleMenu.h)
49 #include INC_XAW(SmeBSB.h)
50 #include INC_XAW(SmeLine.h)
51 #include INC_XAW(Scrollbar.h)
52 #include INC_XAW(MenuButton.h)
53 #include INC_X11(IntrinsicP.h)
54 #include "Aaa.h"
55 #include "Clip.h"
56 #include "Ghostview.h"
57 #include "MButton.h"
58 #include "Vlist.h"
59 
60 #include "types.h"
61 #include "actions.h"
62 #include "callbacks.h"
63 #include "ps.h"
64 #include "doc_misc.h"
65 #include "dialog.h"  /* include the popup headers for action_delete_window */
66 #include "note.h"
67 #include "info.h"
68 #include "main_resources.h"
69 #include "main_globals.h"
70 #include "misc.h"
71 #include "options.h"
72 #include "version.h"
73 
74 /*##################################################################*/
75 /* action_shellConfigureNotify */
76 /*##################################################################*/
77 
78 void
action_shellConfigureNotify(Widget w,XEvent * event,String * params _GL_UNUSED,Cardinal * num_params _GL_UNUSED)79 action_shellConfigureNotify(Widget w, XEvent *event, String *params _GL_UNUSED, Cardinal *num_params _GL_UNUSED)
80 {
81   static int width=0,height=0;
82   int new_width=0,new_height=0;
83 
84   BEGINMESSAGE(action_shellConfigureNotify)
85   if (w==toplevel && event->type == ConfigureNotify) {
86      new_width = ((XConfigureEvent*)event)->width;
87      new_height = ((XConfigureEvent*)event)->height;
88      IIMESSAGE(new_width,new_height)
89   }
90   if (new_width && new_height) {
91     if (gv_scales[gv_scale]->scale <= 0 && !app_res.auto_resize)
92     {
93        misc_savePagePosition();
94        show_page(REQUEST_NEW_SCALE,NULL);
95        misc_resetPagePosition();
96     }
97     if (width != new_width || height != new_height) {
98        misc_setPageMarker(0,2,event,True); /* bring selected in sight */
99        width = new_width;
100        height=new_height;
101     }
102     INFMESSAGE(action_shellConfigureNotify calling XawScrollbarSetThumb)
103     XawScrollbarSetThumb(newtocScroll,
104 		   VlistScrollPosition(newtoc),
105 		   VlistVisibleLength(newtoc,newtocClip->core.height));
106 
107   }
108   ENDMESSAGE(action_shellConfigureNotify)
109 }
110 
111 /*##################################################################*/
112 /* action_page */
113 /*##################################################################*/
114 
scroll_success(Widget clip,int e,int x,int y,int nx,int ny)115 static int scroll_success(Widget clip, int e, int x, int y, int nx, int ny)
116 {
117   int tx,ty;
118   ClipWidgetCheckCoordinates(clip,nx,ny,&tx,&ty);
119   if (((e&PAGE_H) && tx != x) || ((e&PAGE_V) && ty != y)) {
120     INFMESSAGE(scrolling has effect)
121     return(1);
122   } else {
123     INFMESSAGE(scrolling has no effect)
124     return(0);
125   }
126 }
127 
128 static void
catch_timer(XtPointer client_data,XtIntervalId * idp _GL_UNUSED)129 catch_timer(XtPointer client_data, XtIntervalId *idp _GL_UNUSED)
130 {
131   Widget w = (Widget) client_data;
132   Cardinal n = 0;
133   BEGINMESSAGE(catch_timer)
134   action_page(w,NULL,NULL,&n);
135   ENDMESSAGE(catch_timer)
136 }
137 
138 void
action_page(Widget w,XEvent * event,String * params,Cardinal * num_params)139 action_page(Widget w, XEvent *event, String *params, Cardinal *num_params)
140 {
141   int a,e,x,y,nx,ny,cw,ch,d;
142   float f;
143   Widget clip,gvw,aaa;
144   int i;
145   char *s;
146   static String *old_params = NULL;
147   static int old_num_params = 0;
148   String *pars;
149   int    npars;
150   static XtIntervalId timer = 0;
151   int page_changed = 0;
152   int success=0;
153   int    old;
154   float dc = 2.4;
155   int dp;
156   int z=0;
157 
158   BEGINMESSAGE(action_page)
159 
160   if (timer) { XtRemoveTimeOut(timer); timer = 0; }
161 
162   if (w && (XtClass(w) != ghostviewWidgetClass)) {
163      Widget p=w;
164      gvw=NULL;
165      while (p && !gvw) {
166        if (XtIsSubclass(p,shellWidgetClass)) gvw = XtNameToWidget(p,"*page");
167        p=XtParent(p);
168      }
169   } else gvw = w;
170   aaa = XtParent(gvw);
171   clip = XtParent(aaa);
172   SMESSAGE(XtName(gvw)) SMESSAGE(XtName(aaa)) SMESSAGE(XtName(clip))
173   if (strstr(XtName(aaa),"zoomControl")) z=1;
174 
175   cw = (int)clip->core.width;
176   ch = (int)clip->core.height;
177 
178   i = -1;
179   while (!success) {
180     ++i;
181     if (i > 0 && i == old_num_params) {
182        INFMESSAGE(freeing old parameters)
183        i = 0;
184        while (i<old_num_params) XtFree(old_params[i++]);
185        i = 0;
186        XtFree((XtPointer)old_params);
187        old_num_params=0;
188        old_params = NULL;
189     }
190     if (i < old_num_params) {
191       INFMESSAGE(using old parameters)
192       pars = old_params;
193       npars = old_num_params;
194       old = 1;
195     } else {
196       INFMESSAGE(using new parameters)
197       pars = params;
198       npars = *num_params;
199       old = 0;
200     }
201     if (i == npars) {
202       INFMESSAGE(no more parameters)
203       ENDMESSAGE(action_page)
204       return;
205     };
206 
207     a = e = dp = 0;
208     s = pars[i];
209     INFSMESSAGE(handling parameter,s)
210     if (*s == '!') { e |= PAGE_NOT; s++; }
211     if      (!strcmp(s,"up"))               { a = PAGE_UP;                  e |= PAGE_V; }
212     else if (!strcmp(s,"down"))             { a = PAGE_DOWN;                e |= PAGE_V; }
213     else if (!strcmp(s,"left"))             { a = PAGE_LEFT;                e |= PAGE_H; }
214     else if (!strcmp(s,"right"))            { a = PAGE_RIGHT;               e |= PAGE_H; }
215     else if (!strcmp(s,"top"))              { a = PAGE_TOP;                 e |= PAGE_V; }
216     else if (!strcmp(s,"bottom"))           { a = PAGE_BOTTOM;              e |= PAGE_V; }
217     else if (!strcmp(s,"leftedge"))         { a = PAGE_LEFTEDGE;            e |= PAGE_H; }
218     else if (!strcmp(s,"rightedge"))        { a = PAGE_RIGHTEDGE;           e |= PAGE_H; }
219     else if (!z && !strcmp(s,"redisplay"))  { a = PAGE_REDISPLAY;           e |= 0; }
220     else if (!strcmp(s,"center"))           { a = PAGE_CENTER;              e |= PAGE_V|PAGE_H; }
221     else if (!strcmp(s,"right-top"))        { a = PAGE_RIGHT|PAGE_TOP;      e |= PAGE_H; }
222     else if (!strcmp(s,"left-top"))         { a = PAGE_LEFT|PAGE_TOP;       e |= PAGE_H; }
223     else if (!strcmp(s,"right-bottom"))     { a = PAGE_RIGHT|PAGE_BOTTOM;   e |= PAGE_H; }
224     else if (!strcmp(s,"left-bottom"))      { a = PAGE_LEFT|PAGE_BOTTOM;    e |= PAGE_H; }
225     else if (!strcmp(s,"down-leftedge"))    { a = PAGE_DOWN|PAGE_LEFTEDGE;  e |= PAGE_V; }
226     else if (!strcmp(s,"up-leftedge"))      { a = PAGE_UP|PAGE_LEFTEDGE;    e |= PAGE_V; }
227     else if (!strcmp(s,"down-rightedge"))   { a = PAGE_DOWN|PAGE_RIGHTEDGE; e |= PAGE_V; }
228     else if (!strcmp(s,"up-rightedge"))     { a = PAGE_UP|PAGE_RIGHTEDGE;   e |= PAGE_V; }
229     else if (!strcmp(s,"top-leftedge"))     { a = PAGE_TOP|PAGE_LEFTEDGE;   e |= PAGE_H|PAGE_V; }
230     else if (!strcmp(s,"bottom-rightedge")) { a = PAGE_BOTTOM|PAGE_RIGHTEDGE; e |= PAGE_H|PAGE_V; }
231     else if (!z && !strncmp(s,"page",4)) {
232       s += 4;
233       a = PAGE_PAGE; e |= PAGE_PAGE;
234     }
235     else if (!z && !strncmp(s,"highlight",9) && toc_text) {
236       int p,aa=0,h,ho;
237       s += 9;
238       if (*s=='=') { s++; aa=1; }
239       p = atoi(s);
240       ho = h = VlistHighlighted(newtoc) + 1;
241       if (!aa) {
242 	if (h<=0) h =  VlistSelected(newtoc) + 1;
243 	h = h + p - 1;
244       } else {
245         if (ho<0) h = p;
246 	else {
247 	  ho = 10*h + p - 1;
248 	  h = doc_putPageInRange(doc,ho);
249 	  if (h != ho) h = p - 1;
250 	}
251       }
252       h = doc_putPageInRange(doc,h);
253       misc_setPageMarker(h,1,event,False);
254     }
255 
256     nx = x = (int)aaa->core.x;
257     ny = y = (int)aaa->core.y;
258 
259     if (a & PAGE_TOP)       ny = 0;
260     if (a & PAGE_BOTTOM)    ny = -(int)aaa->core.height - 1000;
261     if (a & PAGE_LEFTEDGE)  nx = 0;
262     if (a & PAGE_RIGHTEDGE) nx = -(int)aaa->core.width - 1000;
263     if (a & (PAGE_LEFT|PAGE_RIGHT)) {
264       d = (int)aaa->core.width-cw;
265       if (d > 0) {
266 	/* scrolling left or right */
267 	f = (dc*(float)d)/(float)cw;
268         if (f<1) f = 1;
269         d = (int)(((f/(float)abs((int)f))*(float)cw)/dc+1.0);
270 	if (a & PAGE_LEFT) nx = x + d;
271 	else               nx = x - d;
272        }
273     }
274     if (a & (PAGE_UP|PAGE_DOWN)) {
275        d = (int)aaa->core.height - ch;
276        if (d>0) {
277 	 /* scrolling up or down */
278 	 f = (dc*(float)d)/(float)ch;
279 	 if (f<1) f = 1;
280 	 d = (int)(((f/(float)abs((int)f))*(float)ch)/dc+1.0);
281 	 if (a & PAGE_UP)   ny = y + d;
282 	 else               ny = y - d;
283        }
284     }
285     if (a & PAGE_CENTER) {
286       nx = -((int)aaa->core.width - cw)/2;
287       ny = -((int)aaa->core.height - ch)/2;
288     }
289 
290     if (a & PAGE_REDISPLAY) {
291       if (XtIsSensitive(redisplayEntry)) {
292 	cb_redisplay(gvw,NULL,NULL);
293       }
294     }
295     if (a & PAGE_PAGE) {
296        int cp = current_page;
297        cb_page((Widget)w,(XtPointer)s,(XtPointer)NULL);
298        IIMESSAGE(cp,current_page)
299        if (cp != current_page ||
300            (!toc_text && atoi(s)>0)) page_changed = 1;
301     }
302     if (page_changed) {
303       if (e & PAGE_PAGE) success = 1;
304       if (!old) goto save_params;
305     }
306 
307     if (e&(PAGE_H|PAGE_V) && scroll_success(clip,e,x,y,nx,ny)) {
308       ClipWidgetSetCoordinates(clip,nx,ny);
309       success = 1;
310       if (!GhostviewIsBusy(gvw)) misc_drawEyeGuide(gvw,EYEGUIDE_DRAW,x,y);
311     }
312     if (e&PAGE_NOT) success = success ? 0 : 1;
313 
314 #   ifdef MESSAGES
315       if (success) { INFMESSAGE(command successful) }
316       else { INFMESSAGE(command failed) }
317 #   endif
318   }
319   ENDMESSAGE(action_page)
320   return;
321 
322 save_params:
323   INFMESSAGE(saving params)
324   ++i;
325   if (i<(int)*num_params) {
326     old_num_params = *num_params - i;
327     INFIMESSAGE(saving,old_num_params)
328     old_params = (String*) XtMalloc(old_num_params*sizeof(String));
329     old=0;
330     while (i < (int)*num_params) {
331       old_params[old] = XtNewString(params[i]);
332       INFSMESSAGE(saving,old_params[old])
333       ++i; old++;
334     }
335     timer = XtAppAddTimeOut(app_con,10,catch_timer,(XtPointer)w);
336   }
337   ENDMESSAGE(action_page)
338 }
339 
340 /*##################################################################*/
341 /* action_menuPopdown */
342 /*##################################################################*/
343 
344 void
action_menuPopdown(Widget w,XEvent * event,String * params,Cardinal * num_params)345 action_menuPopdown(Widget w, XEvent *event, String *params, Cardinal *num_params)
346 {
347   BEGINMESSAGE(action_menuPopdown)
348   while (w) {
349     w = XtParent(w);
350     if (w && XtClass(w) == mbuttonWidgetClass) {
351       ButtonUnset(w, event, params, num_params);
352       w = (Widget)NULL;
353     }
354   }
355   ENDMESSAGE(action_menuPopdown)
356 }
357 
358 /*##################################################################*/
359 /* action_toc */
360 /*##################################################################*/
361 
362 void
action_toc(Widget w _GL_UNUSED,XEvent * event,String * params,Cardinal * num_params)363 action_toc(Widget w _GL_UNUSED, XEvent *event, String *params, Cardinal *num_params)
364 {
365   static int xf,yf,xo,yo,xp,yp,dyo;
366   static Boolean scroll_initialized=False;
367   static int startvisible;
368   static Boolean scrolling=False;
369   static int entryo = -1;
370   Boolean toggle_mark=False;
371   int entry,dy;
372   Widget tocslider = newtocControl;
373   Widget tocpanner = newtocClip;
374 
375   BEGINMESSAGE(action_toc)
376 
377   if (!strcmp(params[0],"scroll") && scroll_initialized) {
378     int x,y,dh,ph;
379     float deltay,m;
380     ph = (int)tocpanner->core.height; if (ph<1) ph = 1;
381     dh = ph - (int)tocslider->core.height;
382     deltay = (float)(event->xbutton.y_root - yo);
383     if (!app_res.reverse_scrolling) deltay = -deltay;
384     m  = 1.3*((float)tocslider->core.height/(float)ph);
385     if (m<=1) m = 1;
386     y = yp -(int)(m*deltay);
387     yo = (int) event->xbutton.y_root;
388 
389     ph = (int)tocpanner->core.width; if (ph<1) ph = 1;
390     dh = ph - (int)tocslider->core.width;
391     deltay = (float)(event->xbutton.x_root - xo);
392     if (!app_res.reverse_scrolling) deltay = -deltay;
393     m  = 1.3*((float)tocslider->core.width/(float)ph);
394     if (m<=1) m = 1;
395     x = xp +(int)(m*deltay);
396     if (x<dh) x=dh; if (x>0) x=0;
397     xo = (int) event->xbutton.x_root;
398 
399     if (x!=xp) {
400       ClipWidgetSetCoordinates(tocpanner,x,0);
401       xp = x;
402     }
403     if (y!=yp) {
404       VlistMoveFirstVisible(newtoc, startvisible, y);
405       yp = y;
406     }
407     if (abs(xf-xo) > 6 || abs(yf-yo) > 6) scrolling = True;
408   }
409   else if (!strcmp(params[0],"scrollon")) {
410     scroll_initialized = True;
411     scrolling = False;
412     xp = (int) tocslider->core.x; xf = xo = (int) event->xbutton.x_root;
413     yp = 0; yf = yo = (int) event->xbutton.y_root;
414     startvisible = VlistGetFirstVisible(newtoc);
415   }
416   else if (!strcmp(params[0],"scrolloff")) {
417     scroll_initialized = False;
418     scrolling = False;
419   }
420   else if (!strcmp(params[0],"select")) {
421     if (!scrolling && toc_text) {
422       entry = VlistEntryOfPosition(newtoc,(int)event->xbutton.y);
423       if (entry >=0 && entry < doc->numpages) {
424 	misc_setPageMarker(entry,0,event,True);
425         show_page(entry,NULL);
426       }
427     }
428   }
429   else if (!strcmp(params[0],"toggleon")) {
430     toggle_mark = True;
431     dyo = 0;
432     yo = (int) event->xbutton.y_root;
433   } else if (!strcmp(params[0],"toggleextend")) {
434     entry = VlistEntryOfPosition(newtoc,(int)event->xbutton.y);
435     dy = yo - (int) event->xbutton.y_root;
436     if (dy*dyo < 0 || entry != entryo) toggle_mark = True;
437     dyo = dy;
438     yo = (int) event->xbutton.y_root;
439   } else if (!strcmp(params[0],"toggleoff")) {
440     entryo=-1;
441   } else if (!strcmp(params[0],"highlight")) {
442     entry = VlistEntryOfPosition(newtoc,(int)event->xbutton.y);
443     if (entry != VlistHighlighted(newtoc))
444       VlistChangeHighlighted(newtoc,entry,XawVlistSet);
445   } else if (!strcmp(params[0],"unhighlight")) {
446     entry = VlistEntryOfPosition(newtoc,(int)event->xbutton.y);
447     VlistChangeHighlighted(newtoc,entry,XawVlistUnset);
448   }
449 
450   if (toggle_mark) {
451     int st;
452     scroll_initialized = False;
453     entry = VlistEntryOfPosition(newtoc,(int)event->xbutton.y);
454     if (entryo==-1 || entryo==entry) entryo=entry-1;
455     if (entry<=entryo) st = -1;
456     else st = 1;
457     while (entryo != entry) {
458       entryo += st;
459       if (entryo>=0) VlistChangeMark(newtoc,entryo,XawVlistToggle);
460     }
461   }
462   ENDMESSAGE(action_toc)
463 }
464 
465 /*############################################################*/
466 /* action_otherPage */
467 /*############################################################*/
468 
469 void
action_otherPage(Widget w,XEvent * event,String * params _GL_UNUSED,Cardinal * num_params _GL_UNUSED)470 action_otherPage(Widget w, XEvent *event, String *params _GL_UNUSED, Cardinal *num_params _GL_UNUSED)
471 {
472   static int xo=0,yo=0;
473   static Time to = 0;
474   int x,y,vpwx,vpwy;
475   Dimension vpww;
476   Time t;
477   Position px,py;
478   Arg args[1];
479   Widget vpw;
480 
481   BEGINMESSAGE1(action_otherPage)
482 
483   if (event->type != ButtonRelease || w != page) {
484     INFMESSAGE1(event not a button release or not in main window)
485     ENDMESSAGE1(action_otherPage)
486     return;
487   }
488 
489   vpw = XtParent(XtParent(w));
490   XtTranslateCoords(vpw, 0, 0, &px, &py);
491   vpwx = (int)px;
492   vpwy = (int)py;
493   x = ((int) event->xbutton.x_root) - vpwx + 1;
494   y = ((int) event->xbutton.y_root) - vpwy + 1;
495   t = ((XMotionEvent*)event)->time;
496 #if 0
497   printf("to=%d xo=%d yo=%d\n",(int)to,xo,yo);
498   printf("t= %d x= %d y= %d\n",(int)t,x,y);
499 #endif
500   if (t - to < 400) {
501     if (xo - x < 2 && yo - y < 2) {
502       XtSetArg(args[0], XtNwidth,  &vpww);
503       XtGetValues(vpw, args, ONE);
504       if (2*x<(int)vpww) cb_page(w,(XtPointer)"-1",(XtPointer)NULL);
505       else               cb_page(w,(XtPointer)"+1",(XtPointer)NULL);
506     }
507   }
508   to = t;
509   xo = x;
510   yo = y;
511   ENDMESSAGE1(action_otherPage)
512 }
513 
514 /*############################################################*/
515 /* action_movePage */
516 /*############################################################*/
517 
518 void
action_movePage(Widget w,XEvent * event,String * params,Cardinal * num_params)519 action_movePage(Widget w, XEvent *event, String *params, Cardinal *num_params)
520 {
521 #   define HISTORY_POINTS 10
522 #   define DECAY_TIME 200
523     int x,y;
524     static int posx[HISTORY_POINTS+1],posix;
525     static int posy[HISTORY_POINTS+1],posiy;
526     static int xp,yp,pw,ph,pvw,pvh;
527     static Bool initialized=False;
528     static Time to;
529     Widget vpw;
530 
531     BEGINMESSAGE1(action_movePage)
532 
533     if (XtClass(w) != ghostviewWidgetClass) {
534        INFMESSAGE1(not a ghostview widget) ENDMESSAGE1(action_movePage)
535        return;
536     }
537     vpw = XtParent(XtParent(w));
538 
539     if (*num_params) {
540        if (!strcmp(params[0],"adjusted")) { /* called by cb_pageAdjustNotify */
541           XawPannerReport *rep= (XawPannerReport*) params[1];
542           INFMESSAGE(adjusting)
543 	  xp  = (int) (-rep->slider_x);
544 	  yp  = (int) (-rep->slider_y);
545           pw  = (int) (rep->canvas_width);
546           ph  = (int) (rep->canvas_height);
547           pvw = (int) (rep->slider_width);
548           pvh = (int) (rep->slider_height);
549           IIMESSAGE1(xp,yp) IIMESSAGE1(pw,ph) IIMESSAGE1(pvw,pvh)
550           initialized = True;
551        } else if (!strcmp(params[0],"move")) {
552           INFMESSAGE(moving)
553           if (event->type != MotionNotify) goto break_movePage;
554           if (initialized==True && pvw && pvh) {
555              int dx,dy;
556              double relfactor=1.0;  /* some default value */
557              double absfactor=0.0;  /* some default value */
558              x = (int) event->xbutton.x_root;
559              y = (int) event->xbutton.y_root;
560 
561              if ((((XMotionEvent*)event)->time - to) > DECAY_TIME) {
562                 if (posix>0) { posx[0]=posx[posix]; posix=0; }
563                 if (posiy>0) { posy[0]=posy[posiy]; posiy=0; }
564              }
565              if (posix>0 && (x-posx[posix])*(posx[posix]-posx[posix-1]) < 0) {
566                                posx[0]=posx[posix]; posix=0;
567              }
568              if (posiy>0 && (y-posy[posiy])*(posy[posiy]-posy[posiy-1]) < 0) {
569                                posy[0]=posy[posiy]; posiy=0;
570              }
571              to = ((XMotionEvent*)event)->time;
572              ++posix;
573              ++posiy;
574 
575              if (posix>HISTORY_POINTS) {
576                 posix=1;
577                 while (posix<=HISTORY_POINTS) { posx[posix-1]=posx[posix]; posix++; }
578                 posix=HISTORY_POINTS;
579              }
580              posx[posix] = x;
581              if (posiy>HISTORY_POINTS) {
582                 posiy=1;
583                 while (posiy<=HISTORY_POINTS) { posy[posiy-1]=posy[posiy]; posiy++; }
584                 posiy=HISTORY_POINTS;
585              }
586              posy[posiy] = y;
587 
588              dx = (x - posx[0])/(posix);
589              dy = (y - posy[0])/(posiy);
590 #if 0
591              printf("time=%d x=%d y=%d dx=%d dy=%d\n",(int)to,x,y,dx,dy);
592              printf("posix=%d posx[posix]=%d posx[0]=%d\n",posix,posx[posix],posx[0]);
593              printf("posiy=%d posy[posiy]=%d posy[0]=%d\n",posiy,posy[posiy],posy[0]);
594 #endif
595              if (dx || dy) {
596                 if (*num_params>=2) relfactor = atof((char*)(params[1]));
597                 relfactor = relfactor >= 0 ? (relfactor<=100 ? relfactor : 100) : 0;
598                 if (*num_params>=3) absfactor = atof((char*)(params[2]));
599                 absfactor = absfactor >= 0 ? (absfactor<=200 ? absfactor : 200) : 0;
600                 DDMESSAGE1(absfactor,relfactor)
601                 if (app_res.reverse_scrolling) { dx = -dx; dy = -dy; }
602                 xp = (int) (xp-(dx*absfactor)-(relfactor*pw*dx)/pvw);
603                 yp = (int) (yp-(dy*absfactor)-(relfactor*ph*dy)/pvh);
604                 ClipWidgetSetCoordinates(vpw,xp,yp);
605              }
606           }
607        } else if (!strcmp(params[0],"start")) {
608            Position positx,posity;
609            Arg args[2];
610            INFMESSAGE(start)
611            if (event->type != ButtonPress) goto break_movePage;
612            initialized = False;
613            gv_scroll_mode = SCROLL_MODE_GHOSTVIEW;
614            XtSetArg(args[0], XtNx, (Position*)&positx);
615            XtSetArg(args[1], XtNy, (Position*)&posity);
616            XtGetValues(XtParent(w), args, TWO);
617            xp = (int)positx; yp = (int)posity;
618            posix=posiy=0;
619            posx[0] = (int) event->xbutton.x_root;
620            posy[0] = (int) event->xbutton.y_root;
621            to = ((XMotionEvent*)event)->time;
622            IIMESSAGE1(xp,yp)
623            ClipWidgetSetCoordinates(vpw,xp,yp);
624        } else if (!strcmp(params[0],"stop")) {
625            INFMESSAGE(stop)
626            gv_scroll_mode = SCROLL_MODE_NONE;
627            initialized = False;
628        }
629     }
630     ENDMESSAGE1(action_movePage)
631     return;
632 
633 break_movePage:
634     INFMESSAGE1(interrupting due to wrong event type)
635     initialized = False;
636     gv_scroll_mode = SCROLL_MODE_NONE;
637     ENDMESSAGE1(action_movePage) return;
638 }
639 
640 /*##################################################################*/
641 /* action_panner */
642 /*##################################################################*/
643 
644 void
action_panner(Widget w,XEvent * event,String * params,Cardinal * num_params)645 action_panner(Widget w, XEvent *event, String *params, Cardinal *num_params)
646 {
647     int x,y,cw,ch;
648     static int xo,yo,xp,yp;
649     static Bool initialized=False;
650 
651     BEGINMESSAGE(action_panner)
652 
653     if (!strcmp(params[0],"move") && initialized) {
654        INFMESSAGE1(move)
655        y = yp + (int)event->xbutton.y_root - yo;
656        ch = (int)w->core.height-(int)slider->core.height;
657        if (y>ch) y=ch; else if (y<0) y=0;
658        x = xp + (int)event->xbutton.x_root - xo;
659        cw = (int)w->core.width-(int)slider->core.width;
660        if (x>cw) x=cw; else if (x<0) x=0;
661        if (x!=xp || y!=yp) {
662           int pxp,pyp,dw,dh;
663           XtMoveWidget(slider,x,y);
664           IIMESSAGE(x,y) IIMESSAGE(xp,yp) IIMESSAGE(xo,yo)
665           dw = (int)viewControl->core.width  - (int)viewClip->core.width;
666           dh = (int)viewControl->core.height - (int)viewClip->core.height;
667           if (cw) pxp = (x*dw+cw/2)/cw; else pxp = 0;
668           if (ch) pyp = (y*dh+ch/2)/ch; else pyp = 0;
669           IIMESSAGE(x,y) IIMESSAGE(xp,yp) IIMESSAGE(xo,yo) IIMESSAGE(pxp,pyp)
670           ClipWidgetSetCoordinates(viewClip,-pxp,-pyp);
671           xp = x; xo = (int) event->xbutton.x_root;
672           yp = y; yo = (int) event->xbutton.y_root;
673        }
674     }
675     else if (strcmp(params[0],"on") == 0) {
676        INFMESSAGE(on)
677        gv_scroll_mode = SCROLL_MODE_PANNER;
678        initialized = True;
679        xp = (int) slider->core.x; xo = (int) event->xbutton.x_root;
680        yp = (int) slider->core.y; yo = (int) event->xbutton.y_root;
681     }
682     else if (strcmp(params[0],"off") == 0) {
683        INFMESSAGE(off)
684        gv_scroll_mode = SCROLL_MODE_NONE;
685        initialized = False;
686     }
687     ENDMESSAGE(action_panner)
688 }
689 
690 /*##################################################################*/
691 /* action_handleDSC */
692 /* Call the cb_handleDSC callback */
693 /*##################################################################*/
694 
695 void
action_handleDSC(Widget w,XEvent * event _GL_UNUSED,String * params _GL_UNUSED,Cardinal * num_params _GL_UNUSED)696 action_handleDSC(Widget w, XEvent *event _GL_UNUSED, String *params _GL_UNUSED, Cardinal *num_params _GL_UNUSED)
697 {
698   BEGINMESSAGE(action_handleDSC)
699   cb_handleDSC(w, (XtPointer)1, NULL);
700   ENDMESSAGE(action_handleDSC)
701 }
702 
703 /*##################################################################*/
704 /* action_antialias */
705 /* Call the cb_antialias callback */
706 /*##################################################################*/
707 
708 void
action_antialias(Widget w,XEvent * event _GL_UNUSED,String * params _GL_UNUSED,Cardinal * num_params _GL_UNUSED)709 action_antialias(Widget w, XEvent *event _GL_UNUSED, String *params _GL_UNUSED, Cardinal *num_params _GL_UNUSED)
710 {
711   BEGINMESSAGE(action_antialias)
712   cb_antialias(w, (XtPointer)1, NULL);
713   ENDMESSAGE(action_antialias)
714 }
715 
716 /*##################################################################*/
717 /* action_quit */
718 /* Call the quit callback to stop ghostview */
719 /*##################################################################*/
720 
721 void
action_quit(Widget w,XEvent * event _GL_UNUSED,String * params _GL_UNUSED,Cardinal * num_params _GL_UNUSED)722 action_quit(Widget w, XEvent *event _GL_UNUSED, String *params _GL_UNUSED, Cardinal *num_params _GL_UNUSED)
723 {
724   BEGINMESSAGE(action_quit)
725   cb_quitGhostview(w, NULL, NULL);
726   ENDMESSAGE(action_quit)
727 }
728 
729 /*##################################################################*/
730 /* action_open */
731 /* Popup the open file dialog box. */
732 /*##################################################################*/
733 
734 void
action_open(Widget w _GL_UNUSED,XEvent * event _GL_UNUSED,String * params _GL_UNUSED,Cardinal * num_params _GL_UNUSED)735 action_open(Widget w _GL_UNUSED, XEvent *event _GL_UNUSED, String *params _GL_UNUSED, Cardinal *num_params _GL_UNUSED)
736 {
737   BEGINMESSAGE(action_open)
738   cb_openFile((Widget)NULL,(XtPointer)NULL, NULL);
739   ENDMESSAGE(action_open)
740 }
741 
742 /*##################################################################*/
743 /* action_reopen */
744 /*##################################################################*/
745 
746 void
action_reopen(Widget w _GL_UNUSED,XEvent * event _GL_UNUSED,String * params _GL_UNUSED,Cardinal * num_params _GL_UNUSED)747 action_reopen(Widget w _GL_UNUSED, XEvent *event _GL_UNUSED, String *params _GL_UNUSED, Cardinal *num_params _GL_UNUSED)
748 {
749   BEGINMESSAGE(action_reopen)
750   if (!XtIsSensitive(reopenEntry)) {INFMESSAGE(insensitive) ENDMESSAGE(action_reopen) return; }
751   cb_reopen((Widget)NULL,(XtPointer)NULL,(XtPointer)NULL);
752   ENDMESSAGE(action_reopen)
753 }
754 
755 /*##################################################################*/
756 /* action_savepos */
757 /*##################################################################*/
758 
759 void
action_savepos(Widget w _GL_UNUSED,XEvent * event _GL_UNUSED,String * params _GL_UNUSED,Cardinal * num_params _GL_UNUSED)760 action_savepos(Widget w _GL_UNUSED, XEvent *event _GL_UNUSED, String *params _GL_UNUSED, Cardinal *num_params _GL_UNUSED)
761 {
762   BEGINMESSAGE(action_savepos)
763   if (!XtIsSensitive(saveposEntry)) {INFMESSAGE(insensitive) ENDMESSAGE(action_savepos) return; }
764   cb_savepos((Widget)NULL,(XtPointer)NULL,(XtPointer)NULL);
765   ENDMESSAGE(action_savepos)
766 }
767 
768 /*##################################################################*/
769 /* action_presentation */
770 /*##################################################################*/
771 
772 void
action_presentation(Widget w _GL_UNUSED,XEvent * event _GL_UNUSED,String * params _GL_UNUSED,Cardinal * num_params _GL_UNUSED)773 action_presentation(Widget w _GL_UNUSED, XEvent *event _GL_UNUSED, String *params _GL_UNUSED, Cardinal *num_params _GL_UNUSED)
774 {
775   BEGINMESSAGE(action_savepos)
776   if (!XtIsSensitive(presentationEntry)) {INFMESSAGE(insensitive) ENDMESSAGE(action_presentation) return; }
777   cb_presentation((Widget)NULL,(XtPointer)NULL,(XtPointer)NULL);
778   ENDMESSAGE(action_presentation)
779 }
780 
781 /*##################################################################*/
782 /* action_save */
783 /* Popup the save file dialog box. */
784 /*##################################################################*/
785 
786 void
action_save(Widget w _GL_UNUSED,XEvent * event _GL_UNUSED,String * params,Cardinal * num_params)787 action_save(Widget w _GL_UNUSED, XEvent *event _GL_UNUSED, String *params, Cardinal *num_params)
788 {
789     BEGINMESSAGE(action_save)
790     if (*num_params<1)  {
791        INFMESSAGE(no parameter)
792        ENDMESSAGE(action_save)
793        return;
794     }
795     SMESSAGE(params[0])
796     if (!strcmp(params[0],"marked")) {
797        INFMESSAGE(saving marked)
798        if (!XtIsSensitive(saveMarkedEntry)) {
799           INFMESSAGE(save denied)
800           ENDMESSAGE(action_save)return;
801        }
802        cb_save((Widget)NULL,(XtPointer)(PAGE_MODE_CURRENT|PAGE_MODE_MARKED),NULL);
803     } else if (!strcmp(params[0],"all")) {
804        INFMESSAGE(saving all)
805        if (!XtIsSensitive(saveAllEntry)) {
806           INFMESSAGE(save denied)
807           ENDMESSAGE(action_save)
808           return;
809        }
810        cb_save((Widget)NULL,(XtPointer)(PAGE_MODE_ALL),NULL);
811     }
812     ENDMESSAGE(action_save)
813 }
814 
815 /*##################################################################*/
816 /* action_print */
817 /* Popup the print file dialog box. */
818 /*##################################################################*/
819 
820 void
action_print(Widget w _GL_UNUSED,XEvent * event _GL_UNUSED,String * params,Cardinal * num_params)821 action_print(Widget w _GL_UNUSED, XEvent *event _GL_UNUSED, String *params, Cardinal *num_params)
822 {
823 
824     BEGINMESSAGE(action_print)
825     if (*num_params<1)  {
826        INFMESSAGE(no parameter)
827        ENDMESSAGE(action_print)
828        return;
829     }
830     if (!strcmp(params[0],"marked")) {
831        if (!XtIsSensitive(printMarkedEntry)) {
832           INFMESSAGE(print denied)
833           ENDMESSAGE(action_print)
834           return;
835        }
836        cb_print((Widget)NULL,(XtPointer)(PAGE_MODE_CURRENT|PAGE_MODE_MARKED),NULL);
837     } else if (!strcmp(params[0],"all")) {
838        if (!XtIsSensitive(printAllEntry)) {
839           INFMESSAGE(print denied)
840           ENDMESSAGE(action_print)
841           return;
842        }
843        cb_print((Widget)NULL,(XtPointer)PAGE_MODE_ALL,NULL);
844     }
845     ENDMESSAGE(action_print)
846 }
847 
848 void
action_print_pos(Widget w _GL_UNUSED,XEvent * event _GL_UNUSED,String * params _GL_UNUSED,Cardinal * num_params _GL_UNUSED)849 action_print_pos(Widget w _GL_UNUSED, XEvent *event _GL_UNUSED, String *params _GL_UNUSED, Cardinal *num_params _GL_UNUSED)
850 {
851 
852     BEGINMESSAGE(action_print_pos)
853     cb_print_pos((Widget)NULL,0,NULL);
854     ENDMESSAGE(action_print_pos)
855 }
856 
857 /*##################################################################*/
858 /* action_setPageMark */
859 /* Call the cb_setPageMark callback */
860 /*##################################################################*/
861 
862 void
action_setPageMark(Widget w _GL_UNUSED,XEvent * event _GL_UNUSED,String * params,Cardinal * num_params)863 action_setPageMark(Widget w _GL_UNUSED, XEvent *event _GL_UNUSED, String *params, Cardinal *num_params)
864 {
865     char *current   = "current";
866     char *even      = "even";
867     char *odd       = "odd";
868     char *mark      = "mark";
869     char *toggle    = "toggle";
870     int spm=0;
871 
872     BEGINMESSAGE(action_setPageMark)
873     if (*num_params<2) { INFMESSAGE(no parameters)ENDMESSAGE(action_setPageMark)return; }
874 
875     if (!strcmp(params[0],even))           spm=spm|SPM_EVEN;
876     else if (!strcmp(params[0],odd))       spm=spm|SPM_ODD;
877     else if (!strcmp(params[0],current))   spm=spm|SPM_CURRENT;
878     else                                   spm=spm|SPM_ALL;
879     if      (!strcmp(params[1],toggle))    spm=spm|SPM_TOGGLE;
880     else if (!strcmp(params[1],mark))      spm=spm|SPM_MARK;
881     else                                   spm=spm|SPM_UNMARK;
882 
883     cb_setPageMark((Widget)NULL,(XtPointer)(intptr_t)spm,NULL);
884 
885     ENDMESSAGE(action_setPageMark)
886 }
887 
888 /*##################################################################*/
889 /* action_autoResize */
890 /* Call the cb_autoResize callback */
891 /*##################################################################*/
892 
893 void
action_autoResize(Widget w,XEvent * event _GL_UNUSED,String * params _GL_UNUSED,Cardinal * num_params _GL_UNUSED)894 action_autoResize(Widget w, XEvent *event _GL_UNUSED, String *params _GL_UNUSED, Cardinal *num_params _GL_UNUSED)
895 {
896     BEGINMESSAGE(action_autoResize)
897     cb_autoResize(w, (XtPointer)1, NULL);
898     ENDMESSAGE(action_autoResize)
899 }
900 
901 /*##################################################################*/
902 /* action_setScale */
903 /*##################################################################*/
904 
905 void
action_setScale(Widget w,XEvent * event _GL_UNUSED,String * params,Cardinal * num_params)906 action_setScale(Widget w, XEvent *event _GL_UNUSED, String *params, Cardinal *num_params)
907 {
908     int i;
909 
910     BEGINMESSAGE(action_setScale)
911     if (*num_params < 1) {
912       INFMESSAGE(no parameters)
913       ENDMESSAGE(action_setScale)
914       return;
915     }
916     if (!strcmp(params[0],"+"))      i = (gv_scale+1)|SCALE_ABS;
917     else if (!strcmp(params[0],"-")) i = (gv_scale-1)|SCALE_ABS;
918     else {
919       i = atoi(params[0]);
920       if (i<0) i = (-i)|SCALE_MIN;
921       i |= SCALE_REL;
922     }
923     cb_setScale(w, (XtPointer)(intptr_t)i, NULL);
924     ENDMESSAGE(action_setScale)
925 }
926 
927 /*##################################################################*/
928 /* action_setOrientation */
929 /* Set orientation action routine.  Converts text parameter
930  * to XtPageOrientation and calls cb_setOrientation callback */
931 /*##################################################################*/
932 
933 void
action_setOrientation(Widget w,XEvent * event _GL_UNUSED,String * params,Cardinal * num_params)934 action_setOrientation(Widget w, XEvent *event _GL_UNUSED, String *params, Cardinal *num_params)
935 {
936     int o;
937 
938     BEGINMESSAGE(action_setOrientation)
939     if (*num_params != 1) {
940        INFMESSAGE(no parameter)
941        ENDMESSAGE(action_set_orientation)
942        return;
943     }
944     o = doc_convStringToDocOrient(params[0]);
945     if (o != O_UNSPECIFIED) cb_setOrientation(w, (XtPointer)(intptr_t)o, NULL);
946     ENDMESSAGE(action_setOrientation)
947 }
948 
949 /*##################################################################*/
950 /* action_setPagemedia */
951 /* Set pagemedia action routine.  Converts text parameter
952  * to index into the pagemedia widgets and calls the cb_setPagemedia
953  * callback. */
954 /*##################################################################*/
955 
956 void
action_setPagemedia(Widget w,XEvent * event _GL_UNUSED,String * params,Cardinal * num_params)957 action_setPagemedia(Widget w, XEvent *event _GL_UNUSED, String *params, Cardinal *num_params)
958 {
959     int m;
960 
961     BEGINMESSAGE(action_setPagemedia)
962     if (*num_params != 1) {
963        INFMESSAGE(no parameter)
964        ENDMESSAGE(action_set_pagemedia)
965        return;
966     }
967 
968     m = doc_convStringToPageMedia(doc,params[0]);
969     if (m!= MEDIA_ID_INVALID) cb_setPagemedia(w, (XtPointer)(intptr_t)m, NULL);
970 
971     ENDMESSAGE(action_setPagemedia)
972 }
973 
974 /*##################################################################*/
975 /* action_dismissPopup */
976 /* dismiss a popup window */
977 /*##################################################################*/
978 
979 #define IS_ZOOM(sss) (!strcmp(XtName(sss),"zoomPopup"))
980 void
action_dismissPopup(Widget w,XEvent * event _GL_UNUSED,String * params _GL_UNUSED,Cardinal * num_params _GL_UNUSED)981 action_dismissPopup(Widget w, XEvent *event _GL_UNUSED, String *params _GL_UNUSED, Cardinal *num_params _GL_UNUSED)
982 {
983    Widget s;
984    BEGINMESSAGE(action_dismissPopup)
985    if (w) {
986       INFSMESSAGE(calling widget:,XtName(w))
987       if (XtClass(w) == aaaWidgetClass)	s = XtParent(w);
988       else					s = w;
989       if      (s==infopopup)       {INFMESSAGE(infopopup)     cb_popdownInfoPopup((Widget)NULL,NULL,NULL);    }
990       else if (s==dialogpopup)     {INFMESSAGE(dialogpopup)   cb_popdownDialogPopup((Widget)NULL,NULL,NULL);  }
991       else if (s==notepopup)       {INFMESSAGE(notepopup)     cb_popdownNotePopup((Widget)NULL,NULL,NULL);    }
992       else if (s==gv_options_fs->popup)    { INFMESSAGE(options fs)    options_cb_popdown((Widget)NULL,(XtPointer)gv_options_fs,NULL);  }
993       else if (s==gv_options_gs->popup)    { INFMESSAGE(options gs)    options_cb_popdown((Widget)NULL,(XtPointer)gv_options_gs,NULL);  }
994       else if (s==gv_options_gv->popup)    { INFMESSAGE(options gv)    options_cb_popdown((Widget)NULL,(XtPointer)gv_options_gv,NULL);  }
995       else if (s==gv_options_setup->popup) { INFMESSAGE(options setup) options_cb_popdown((Widget)NULL,(XtPointer)gv_options_setup,NULL);  }
996       else if (s==versionpopup)    {INFMESSAGE(versionpopup)  cb_popdownVersionPopup((Widget)NULL,NULL,NULL); }
997       else if (s==FileSel_popup)   {INFMESSAGE(Filesel_popup) XtPopdown(s);				    }
998       else if IS_ZOOM(s)           {INFMESSAGE(zoomPopup)     XtDestroyWidget(s);                   }
999    }
1000    ENDMESSAGE(action_dismissPopup)
1001 }
1002 
1003 /*##################################################################*/
1004 /* action_deleteWindow */
1005 /* Implement WM_DELETE_WINDOW protocol */
1006 /*##################################################################*/
1007 
1008 void
action_deleteWindow(Widget w,XEvent * event,String * params _GL_UNUSED,Cardinal * num_params _GL_UNUSED)1009 action_deleteWindow(Widget w, XEvent *event, String *params _GL_UNUSED, Cardinal *num_params _GL_UNUSED)
1010 {
1011    BEGINMESSAGE(action_deleteWindow)
1012    if (w) {
1013       INFSMESSAGE(widget:,XtName(w))
1014       if (event->type == ClientMessage && (Atom)event->xclient.data.l[0] == wm_delete_window) {
1015          if (w==toplevel)     { INFMESSAGE(toplevel) cb_quitGhostview((Widget)NULL,NULL,NULL); }
1016          else                 { action_dismissPopup(w,NULL,NULL,NULL); }
1017       }
1018    }
1019    ENDMESSAGE(action_deleteWindow)
1020 }
1021 
1022 /*##################################################################*/
1023 /* action_eraseLocator */
1024 /* Pop down locator window */
1025 /*##################################################################*/
1026 
1027 void
action_eraseLocator(Widget w _GL_UNUSED,XEvent * event _GL_UNUSED,String * params _GL_UNUSED,Cardinal * num_params _GL_UNUSED)1028 action_eraseLocator(Widget w _GL_UNUSED, XEvent *event _GL_UNUSED, String *params _GL_UNUSED, Cardinal *num_params _GL_UNUSED)
1029 {
1030     Arg args[1];
1031 
1032     BEGINMESSAGE1(action_eraseLocator)
1033     if (!show_locator) {INFMESSAGE1(no locator)ENDMESSAGE1(action_erase_locator)return;}
1034     XtSetArg(args[0], XtNlabel, "");
1035     XtSetValues(locator, args, ONE);
1036     ENDMESSAGE1(action_eraseLocator)
1037 }
1038 
1039 /*##################################################################*/
1040 /* action_checkFile */
1041 /* Check to see if file changed */
1042 /*##################################################################*/
1043 
1044 void
action_checkFile(Widget w _GL_UNUSED,XEvent * event _GL_UNUSED,String * params,Cardinal * num_params)1045 action_checkFile(Widget w _GL_UNUSED, XEvent *event _GL_UNUSED, String *params, Cardinal *num_params)
1046 {
1047     BEGINMESSAGE(action_checkFile)
1048     if (*num_params != 1) {INFMESSAGE(no parameters) ENDMESSAGE(action_checkFile) return;}
1049     if (!strcmp(params[0],"date"))
1050        cb_checkFile((Widget)NULL,(XtPointer)CHECK_FILE_DATE,NULL);
1051     else if (!strcmp(params[0],"version"))
1052        cb_checkFile((Widget)NULL,(XtPointer)CHECK_FILE_VERSION,NULL);
1053     ENDMESSAGE(action_checkFile)
1054 }
1055 
1056 /*##################################################################*/
1057 /* action_watchFile */
1058 /*##################################################################*/
1059 
1060 void
action_watchFile(Widget w _GL_UNUSED,XEvent * event _GL_UNUSED,String * params _GL_UNUSED,Cardinal * num_params _GL_UNUSED)1061 action_watchFile(Widget w _GL_UNUSED, XEvent *event _GL_UNUSED, String *params _GL_UNUSED, Cardinal *num_params _GL_UNUSED)
1062 {
1063   BEGINMESSAGE(action_watchFile)
1064   cb_watchFile(NULL,(XtPointer)1,NULL);
1065   ENDMESSAGE(action_watchFile)
1066 }
1067 
1068 
1069 
1070 void
clean_safe_tempdir(void)1071 clean_safe_tempdir(void)
1072 {
1073    if (gv_safe_gs_tempdir)
1074    {
1075       chdir("/");
1076       rmdir(gv_safe_gs_workdir);
1077    }
1078 }
1079