1 /*
2  * Author:      William Chia-Wei Cheng (bill.cheng@acm.org)
3  *
4  * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5  *
6  * This file may be distributed under the terms of the Q Public License
7  * as defined by Trolltech AS of Norway and appearing in the file
8  * LICENSE.QPL included in the packaging of this file.
9  *
10  * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11  * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12  * PURPOSE.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  * @(#)$Header: /mm2/home/cvs/bc-src/tgif/navigate.c,v 1.12 2011/05/16 16:21:58 william Exp $
19  */
20 
21 #define _INCLUDE_FROM_NAVIGATE_C_
22 
23 #include "tgifdefs.h"
24 #include "cmdids.h"
25 
26 #include "attr.e"
27 #include "auxtext.e"
28 #include "button.e"
29 #include "choice.e"
30 #include "choose.e"
31 #include "cmd.e"
32 #include "color.e"
33 #include "cursor.e"
34 #include "cutpaste.e"
35 #include "dialog.e"
36 #include "drawing.e"
37 #include "exec.e"
38 #include "file.e"
39 #include "font.e"
40 #include "mainloop.e"
41 #include "mainmenu.e"
42 #include "menu.e"
43 #include "menuinfo.e"
44 #include "msg.e"
45 #include "names.e"
46 #include "navigate.e"
47 #include "obj.e"
48 #include "page.e"
49 #include "pattern.e"
50 #include "raster.e"
51 #include "rect.e"
52 #include "remote.e"
53 #include "scroll.e"
54 #include "select.e"
55 #include "setup.e"
56 #include "stk.e"
57 #include "strtbl.e"
58 #include "util.e"
59 #include "xpixmap.e"
60 
61 int navigatingBackAndForth=FALSE;
62 int inHyperSpace=FALSE;
63 int inSlideShow=FALSE;
64 int visibleGridInSlideShow=FALSE;
65 int slideShowInfoValid=FALSE;
66 char *slideShowBorderColor=NULL;
67 int slideShowXOffset=0;
68 int slideShowYOffset=0;
69 int autoHyperSpaceOnRemote=TRUE;
70 int allowLaunchInHyperSpace=FALSE;
71 int navigateRefresh=FALSE;
72 int goHyperSpaceInSlideShow=FALSE;
73 
74 static int validHotListFileName=FALSE;
75 static char *hotListFileName=NULL;
76 
77 struct NavigateRec {
78    struct StkRec *stk;
79    struct NavigateRec *next, *prev;
80    char *full_fname;
81    char *doc_name;
82    int cur_page_num, orig_x, orig_y, zoom_scale, zoomed_in;
83 };
84 
85 static struct NavigateRec *firstNavigate=NULL, *lastNavigate=NULL;
86 static struct NavigateRec *curNavigate=NULL;
87 
88 static struct NavigateRec *firstSessionHistory=NULL, *lastSessionHistory=NULL;
89 
90 static struct URLCacheRec *firstURLCache=NULL, *lastURLCache=NULL;
91 static int maxURLCache=(-1), curURLCache=0;
92 
93 static int lineWidthIndexInSlideShow=4;
94 static int makeUnsavableInSlideShow=FALSE;
95 static int ignoreSlideShowOffsetsInFile=TRUE;
96 static int hideWindowsInSlideShow=TRUE;
97 
98 static int savedSlideShowXOffset=0;
99 static int savedSlideShowYOffset=0;
100 static int savedSlideShowOffsets=FALSE;
101 
ParseXYSpec(spec,pnx,pny)102 int ParseXYSpec(spec, pnx, pny)
103    char *spec;
104    int *pnx, *pny;
105 {
106    char *psz_dx=NULL, *psz_dy=NULL, *psz_dup_spec=NULL;
107    int dx, dy;
108 
109    UtilTrimBlanks(spec);
110    if (*spec == '\0') return FALSE;
111    if ((psz_dup_spec=UtilStrDup(spec)) == NULL) return FailAllocMessage();
112 
113    if ((psz_dx=strtok(psz_dup_spec, " ,\t\n\r")) == NULL ||
114          sscanf(psz_dx, "%d", &dx) != 1) {
115       sprintf(gszMsgBox, TgLoadString(STID_ERR_IN_PARSE_STR_FOR_2_VAL), spec);
116       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
117       free(psz_dup_spec);
118       return FALSE;
119    }
120    psz_dy = strtok(NULL, " ,\t\n\r");
121    if (psz_dy == NULL) {
122       dy = dx;
123    } else {
124       if (sscanf(psz_dy, "%d", &dy) != 1) {
125          sprintf(gszMsgBox, TgLoadString(STID_ERR_IN_PARSE_STR_FOR_2_VAL),
126                spec);
127          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
128          free(psz_dup_spec);
129          return FALSE;
130       }
131    }
132    if (pnx != NULL) *pnx = dx;
133    if (pny != NULL) *pny = dy;
134 
135    free(psz_dup_spec);
136    return TRUE;
137 }
138 
139 static
ParseWHSpecError(spec,psz_dup_spec,rc)140 int ParseWHSpecError(spec, psz_dup_spec, rc)
141    char *spec;
142    char *psz_dup_spec;
143    int rc;
144 {
145    if (!rc) {
146       sprintf(gszMsgBox, TgLoadString(STID_ERR_IN_PARSE_STR_FOR_2_VAL), spec);
147       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
148    }
149    UtilFree(psz_dup_spec);
150 
151    return rc;
152 }
153 
ParseWHSpec(spec,pnw,pnh)154 int ParseWHSpec(spec, pnw, pnh)
155    char *spec;
156    int *pnw, *pnh;
157 {
158    char *psz_h=NULL, *psz_dup_spec=NULL;
159    int w=0, h=0;
160 
161    UtilTrimBlanks(spec);
162    if (*spec == '\0') return FALSE;
163    if ((psz_dup_spec=UtilStrDup(spec)) == NULL) return FailAllocMessage();
164 
165    UtilStrLower(psz_dup_spec);
166    if ((psz_h=strchr(psz_dup_spec, 'x')) == NULL) {
167       if ((psz_h=strchr(psz_dup_spec, ' ')) == NULL) {
168          return ParseWHSpecError(spec, psz_dup_spec, FALSE);
169       }
170       *psz_h++ = '\0';
171    } else {
172       *psz_h++ = '\0';
173    }
174    UtilTrimBlanks(psz_dup_spec);
175    UtilTrimBlanks(psz_h);
176    if (!GetDimension(psz_dup_spec, FALSE, &w)) {
177       return ParseWHSpecError(spec, psz_dup_spec, FALSE);
178    }
179    if (!GetDimension(psz_h, FALSE, &h)) {
180       return ParseWHSpecError(spec, psz_dup_spec, FALSE);
181    }
182    if (pnw != NULL) *pnw = w;
183    if (pnh != NULL) *pnh = h;
184 
185    free(psz_dup_spec);
186    return TRUE;
187 }
188 
CleanUpSlideShowInfo()189 void CleanUpSlideShowInfo()
190 {
191    if (slideShowBorderColor != NULL) UtilFree(slideShowBorderColor);
192    slideShowBorderColor = NULL;
193    slideShowXOffset = slideShowYOffset = 0;
194    slideShowInfoValid = FALSE;
195 }
196 
197 static
InsertNavigate(pnr_prev,pnr_next,pnr)198 void InsertNavigate(pnr_prev, pnr_next, pnr)
199    struct NavigateRec *pnr_prev, *pnr_next, *pnr;
200 {
201    pnr->prev = pnr_prev;
202    pnr->next = pnr_next;
203 
204    if (pnr_prev == NULL) {
205       firstNavigate = pnr;
206    } else {
207       pnr_prev->next = pnr;
208    }
209 
210    if (pnr_next == NULL) {
211       lastNavigate = pnr;
212    } else {
213       pnr_next->prev = pnr;
214    }
215 }
216 
217 static
DeleteNavigate(pnr)218 void DeleteNavigate(pnr)
219    struct NavigateRec *pnr;
220 {
221    if (pnr->full_fname != NULL) free(pnr->full_fname);
222    if (pnr->doc_name != NULL) free(pnr->doc_name);
223    free(pnr);
224 }
225 
226 static
ClearNavigateRecords(pnr)227 void ClearNavigateRecords(pnr)
228    struct NavigateRec *pnr;
229 {
230    struct NavigateRec *pnr_next;
231 
232    for (; pnr != NULL; pnr=pnr_next) {
233       pnr_next = pnr->next;
234       DeleteNavigate(pnr);
235    }
236    lastNavigate = curNavigate;
237    if (lastNavigate == NULL) firstNavigate = NULL;
238 }
239 
240 static
ClearSessionHistory()241 void ClearSessionHistory()
242 {
243    struct NavigateRec *pnr, *pnr_prev;
244 
245    for (pnr=lastSessionHistory; pnr != NULL; pnr=pnr_prev) {
246       pnr_prev = pnr->prev;
247       if (pnr->full_fname != NULL) free(pnr->full_fname);
248       if (pnr->doc_name != NULL) free(pnr->doc_name);
249       free(pnr);
250    }
251    lastSessionHistory = firstSessionHistory = NULL;
252 }
253 
254 static
FreeAnURLCache(url_cache)255 void FreeAnURLCache(url_cache)
256    struct URLCacheRec *url_cache;
257 {
258    if (url_cache == NULL) return;
259    if (url_cache->remote_buf != NULL) free(url_cache->remote_buf);
260    if (url_cache->content_type != NULL) free(url_cache->content_type);
261    if (url_cache->simple_url_name != NULL) free(url_cache->simple_url_name);
262    free(url_cache);
263 }
264 
265 static
CleanUpURLCache()266 void CleanUpURLCache()
267 {
268    struct URLCacheRec *next_cache;
269 
270    for ( ; firstURLCache != NULL; firstURLCache=next_cache) {
271       next_cache = firstURLCache->next;
272       FreeAnURLCache(firstURLCache);
273    }
274    curURLCache = 0;
275    firstURLCache = lastURLCache = NULL;
276 }
277 
CleanUpNavigate()278 void CleanUpNavigate()
279 {
280    curNavigate = NULL;
281    ClearNavigateRecords(firstNavigate);
282    if (hotListFileName != NULL) free(hotListFileName);
283    hotListFileName = NULL;
284    validHotListFileName = FALSE;
285    ClearSessionHistory();
286 
287    CleanUpURLCache();
288    CleanUpSlideShowInfo();
289 
290    savedSlideShowXOffset = 0;
291    savedSlideShowYOffset = 0;
292    savedSlideShowOffsets = FALSE;
293 }
294 
InitNavigate()295 void InitNavigate()
296 {
297    char *c_ptr=NULL, spec[MAXSTRING];
298 
299    visibleGridInSlideShow = FALSE;
300    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
301          "VisibleGridInSlideShow")) != NULL &&
302          UtilStrICmp(c_ptr, "true") == 0) {
303       visibleGridInSlideShow = TRUE;
304    }
305    goHyperSpaceInSlideShow = FALSE;
306    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "GoHyperSpaceInSlideShow")) !=
307          NULL && UtilStrICmp(c_ptr, "true") == 0) {
308       goHyperSpaceInSlideShow = TRUE;
309    }
310    lineWidthIndexInSlideShow = 4;
311    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
312          "LineWidthIndexInSlideShow")) != NULL) {
313       lineWidthIndexInSlideShow = atoi(c_ptr);
314       if (lineWidthIndexInSlideShow < 0 ||
315             lineWidthIndexInSlideShow >= maxLineWidths) {
316          fprintf(stderr, TgLoadString(STID_INVALID_XDEF_USE_ALT_VALUE),
317                TOOL_NAME, "LineWidthIndexInSlideShow", c_ptr, 4);
318          lineWidthIndexInSlideShow = 4;
319       }
320    }
321    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"SlideShowWindowOffsets")) !=
322          NULL) {
323       UtilStrCpyN(spec, sizeof(spec), c_ptr);
324       UtilTrimBlanks(spec);
325       if (ParseXYSpec(spec, &slideShowXOffset, &slideShowYOffset)) {
326          slideShowInfoValid = TRUE;
327 
328          savedSlideShowXOffset = slideShowXOffset;
329          savedSlideShowYOffset = slideShowYOffset;
330          savedSlideShowOffsets = TRUE;
331       } else {
332          fprintf(stderr, TgLoadString(STID_INVALID_XDEF_USE_ALT_STR),
333                TOOL_NAME, "SlideShowWindowOffsets", spec, "0,0");
334          fprintf(stderr, "\n");
335       }
336    }
337    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"SlideShowBorderColor")) !=
338          NULL) {
339       int new_alloc=0;
340 
341       UtilStrCpyN(spec, sizeof(spec), c_ptr);
342       UtilTrimBlanks(spec);
343 
344       if (QuickFindColorIndex(NULL, spec, &new_alloc, FALSE) == INVALID) {
345          fprintf(stderr, TgLoadString(STID_INVALID_XDEF_COLORXPM_GET),
346                TOOL_NAME, "SlideShowBorderColor", spec);
347          fprintf(stderr, "\n");
348          return;
349       }
350       if (slideShowBorderColor != NULL) UtilFree(slideShowBorderColor);
351       slideShowBorderColor = UtilStrDup(spec);
352       if (slideShowBorderColor == NULL) FailAllocMessage();
353       slideShowInfoValid = TRUE;
354    }
355    makeUnsavableInSlideShow = FALSE;
356    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"MakeUnsavableInSlideShow")) !=
357          NULL && UtilStrICmp(c_ptr, "true") == 0) {
358       makeUnsavableInSlideShow = TRUE;
359    }
360    ignoreSlideShowOffsetsInFile = TRUE;
361    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
362          "IgnoreSlideShowOffsetsInFile")) != NULL &&
363          UtilStrICmp(c_ptr, "false") == 0) {
364       ignoreSlideShowOffsetsInFile = FALSE;
365    }
366    hideWindowsInSlideShow = TRUE;
367    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
368          "HideWindowsInSlideShow")) != NULL &&
369          UtilStrICmp(c_ptr, "false") == 0) {
370       hideWindowsInSlideShow = FALSE;
371    }
372 }
373 
374 static
InitURLCache()375 void InitURLCache()
376 {
377    if (maxURLCache == (-1)) {
378       char *c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"MaxNavigateCacheBuffers");
379 
380       maxURLCache = 40;
381       if (c_ptr != NULL) {
382          maxURLCache = atoi(c_ptr);
383          if (maxURLCache < 0) {
384             fprintf(stderr, TgLoadString(STID_INVALID_XDEF_USE_ALT_VALUE),
385                   TOOL_NAME, "MaxNavigateCacheBuffers", c_ptr, 40);
386             maxURLCache = 40;
387          }
388       }
389       curURLCache = 0;
390       firstURLCache = lastURLCache = NULL;
391    }
392 }
393 
394 static
SimpleURLName(psz_url)395 char *SimpleURLName(psz_url)
396    char *psz_url;
397 {
398    char *c_ptr=strchr(psz_url, '#');
399 
400    if (c_ptr != NULL) {
401       char *return_buf;
402 
403       *c_ptr = '\0';
404       return_buf = UtilStrDup(psz_url);
405       *c_ptr = '#';
406       return return_buf;
407    }
408    return UtilStrDup(psz_url);
409 }
410 
411 static
UnlinkURLCache(url_cache)412 void UnlinkURLCache(url_cache)
413    struct URLCacheRec *url_cache;
414 {
415    if (url_cache == NULL) return;
416    if (url_cache->prev == NULL) {
417       firstURLCache = url_cache->next;
418    } else {
419       url_cache->prev->next = url_cache->next;
420    }
421    if (url_cache->next == NULL) {
422       lastURLCache = url_cache->prev;
423    } else {
424       url_cache->next->prev = url_cache->prev;
425    }
426    url_cache->prev = url_cache->next = NULL;
427    curURLCache--;
428 }
429 
430 static
InsertURLCache(prev_url,next_url,url_cache)431 void InsertURLCache(prev_url, next_url, url_cache)
432    struct URLCacheRec *prev_url, *next_url, *url_cache;
433 {
434    url_cache->prev = prev_url;
435    url_cache->next = next_url;
436    if (prev_url == NULL) {
437       firstURLCache = url_cache;
438    } else {
439       prev_url->next = url_cache;
440    }
441    if (next_url == NULL) {
442       lastURLCache = url_cache;
443    } else {
444       next_url->prev = url_cache;
445    }
446    curURLCache++;
447 }
448 
UpdateLRU(url_cache)449 void UpdateLRU(url_cache)
450    struct URLCacheRec *url_cache;
451 {
452    UnlinkURLCache(url_cache);
453    InsertURLCache(lastURLCache, NULL, url_cache);
454 }
455 
FindURLCache(psz_url,update_lru)456 struct URLCacheRec *FindURLCache(psz_url, update_lru)
457    char *psz_url;
458    int update_lru;
459 {
460    char *simple_url_name=NULL;
461    struct URLCacheRec *url_cache;
462 
463    if (PRTGIF) return NULL;
464 
465    simple_url_name = SimpleURLName(psz_url);
466    InitURLCache();
467    if (simple_url_name == NULL) return NULL;
468    for (url_cache=lastURLCache; url_cache != NULL; url_cache=url_cache->prev) {
469       if (strcmp(simple_url_name, url_cache->simple_url_name) == 0) {
470          free(simple_url_name);
471          if (!navigatingBackAndForth) {
472             /*
473              * Should get HEAD of the URL to see if Last-modified has changed.
474              */
475          }
476          if (update_lru) UpdateLRU(url_cache);
477          return url_cache;
478       }
479    }
480    free(simple_url_name);
481    return NULL;
482 }
483 
UpdateURLCache(psz_url,psz_remote_buf,psz_content_type,remote_buf_sz,is_html)484 void UpdateURLCache(psz_url, psz_remote_buf, psz_content_type, remote_buf_sz,
485       is_html)
486    char *psz_url, *psz_remote_buf, *psz_content_type;
487    int remote_buf_sz, is_html;
488 {
489    char *simple_url_name=NULL;
490    struct URLCacheRec *url_cache;
491 
492    if (PRTGIF) return;
493 
494    simple_url_name = SimpleURLName(psz_url);
495    InitURLCache();
496    if (simple_url_name == NULL) return;
497    for (url_cache=lastURLCache; url_cache != NULL; url_cache=url_cache->prev) {
498       if (strcmp(simple_url_name, url_cache->simple_url_name) == 0) {
499          break;
500       }
501    }
502    if (url_cache != NULL) {
503       UnlinkURLCache(url_cache);
504       FreeAnURLCache(url_cache);
505    } else {
506       if (curURLCache >= maxURLCache) {
507          url_cache = firstURLCache;
508          UnlinkURLCache(url_cache);
509          FreeAnURLCache(url_cache);
510       }
511    }
512    url_cache = (struct URLCacheRec*)malloc(sizeof(struct URLCacheRec));
513    if (url_cache == NULL) {
514       FailAllocMessage();
515       free(simple_url_name);
516       return;
517    }
518    memset(url_cache, 0, sizeof(struct URLCacheRec));
519    url_cache->remote_buf_sz = remote_buf_sz;
520    url_cache->is_html = is_html;
521    url_cache->remote_buf = UtilStrDup(psz_remote_buf);
522    url_cache->content_type = UtilStrDup(psz_content_type);
523    url_cache->simple_url_name = simple_url_name;
524    InsertURLCache(lastURLCache, NULL, url_cache);
525 }
526 
527 static
InitHotListFileName()528 int InitHotListFileName()
529 {
530    if (!validHotListFileName)
531    {
532       char *c_ptr;
533 
534       hotListFileName = NULL;
535       if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"HotListFileName")) !=
536             NULL) {
537          hotListFileName = UtilStrDup(c_ptr);
538       } else {
539          int len=strlen(homeDir)+strlen(TOOL_NAME)+20;
540 
541          hotListFileName = (char*)malloc((len+1)*sizeof(char));
542          if (hotListFileName == NULL) FailAllocMessage();
543          sprintf(hotListFileName, "%s%c.%s_hotlist", homeDir, DIR_SEP,
544                TOOL_NAME);
545       }
546    }
547    validHotListFileName = TRUE;
548    return TRUE;
549 }
550 
BeforeNavigate()551 void BeforeNavigate()
552 {
553    if (curFileDefined && curNavigate != NULL) {
554       curNavigate->cur_page_num = curPageNum;
555       curNavigate->orig_x = drawOrigX;
556       curNavigate->orig_y = drawOrigY;
557       curNavigate->zoom_scale = zoomScale;
558       curNavigate->zoomed_in = zoomedIn;
559    }
560 }
561 
562 static
AddToSessionHistory(cur_pnr)563 void AddToSessionHistory(cur_pnr)
564    struct NavigateRec *cur_pnr;
565 {
566    struct NavigateRec *pnr;
567 
568    pnr = (struct NavigateRec *)malloc(sizeof(struct NavigateRec));
569    if (pnr == NULL) FailAllocMessage();
570    memset(pnr, 0, sizeof(struct NavigateRec));
571 
572    pnr->prev = lastSessionHistory;
573    pnr->next = NULL;
574    pnr->stk = NULL;
575    pnr->full_fname = (cur_pnr->full_fname==NULL ? NULL :
576          UtilStrDup(cur_pnr->full_fname));
577    pnr->doc_name = (cur_pnr->doc_name==NULL ? NULL :
578          UtilStrDup(cur_pnr->doc_name));
579 
580    if (lastSessionHistory == NULL) {
581       firstSessionHistory = pnr;
582    } else {
583       lastSessionHistory->next = pnr;
584    }
585    lastSessionHistory = pnr;
586 }
587 
CommitNavigate()588 void CommitNavigate()
589    /* add a navigation record at the end */
590 {
591    int len;
592 
593    if (curNavigate == NULL) {
594       ClearNavigateRecords(firstNavigate);
595    } else if (curNavigate != lastNavigate) {
596       ClearNavigateRecords(curNavigate->next);
597    }
598 
599    if (!curFileDefined) return;
600 
601    curNavigate = (struct NavigateRec *)malloc(sizeof(struct NavigateRec));
602    if (curNavigate == NULL) FailAllocMessage();
603    memset(curNavigate, 0, sizeof(struct NavigateRec));
604    curNavigate->stk = NULL;
605    curNavigate->next = curNavigate->prev = NULL;
606    curNavigate->full_fname = curNavigate->doc_name = NULL;
607    curNavigate->cur_page_num = 1;
608    curNavigate->orig_x = curNavigate->orig_y = 0;
609    curNavigate->zoom_scale = 0;
610    curNavigate->zoomed_in = FALSE;
611 
612    len = strlen(curDir)+1+strlen(curFileName);
613 
614    curNavigate->full_fname = (char*)malloc((len+1)*sizeof(char));
615    if (curNavigate->full_fname == NULL) FailAllocMessage();
616    sprintf(curNavigate->full_fname, "%s%c%s", curDir, DIR_SEP, curFileName);
617    if (firstPage != NULL && firstPage->name != NULL) {
618       curNavigate->doc_name = UtilStrDup(firstPage->name);
619    } else {
620       curNavigate->doc_name = NULL;
621    }
622    AddARecentlyUsedFile(curNavigate->full_fname);
623    curNavigate->stk = topStk;
624 
625    InsertNavigate(lastNavigate, NULL, curNavigate);
626    curNavigate = lastNavigate;
627    AddToSessionHistory(curNavigate);
628 }
629 
630 static
PostNavigate(pnr)631 void PostNavigate(pnr)
632    struct NavigateRec *pnr;
633 {
634    struct AttrRec *exec_attr=FindFileAttrWithName("auto_exec=");
635 
636    if (exec_attr != NULL) {
637       ClearObjCachesInAllPages();
638       DoExecLoop(NULL, exec_attr);
639    } else if (pnr != NULL) {
640       ScrollToSpecifiedOrigin(pnr->cur_page_num, pnr->orig_x, pnr->orig_y,
641             pnr->zoom_scale, pnr->zoomed_in);
642       ClearObjCachesInAllPages();
643    }
644 }
645 
646 static
NavigateTo(full_fname,do_not_save,force_load)647 void NavigateTo(full_fname, do_not_save, force_load)
648    char *full_fname;
649    int do_not_save, force_load;
650 {
651    if (force_load) navigateRefresh = TRUE;
652 
653    if (FileIsRemote(full_fname)) {
654       char *buf=NULL, *content_type=NULL, final_url[MAXPATHLENGTH+1];
655       int rc, buf_sz=0, is_html=FALSE;
656 
657       *final_url = '\0';
658       SetWatchCursor(drawWindow);
659       SetWatchCursor(mainWindow);
660       SaveStatusStrings();
661       rc = LoadRemoteFileInMem(full_fname, &buf, &content_type, &buf_sz,
662             &is_html, force_load, final_url, sizeof(final_url));
663       RestoreStatusStrings();
664       SetDefaultCursor(mainWindow);
665       ShowCursor();
666       if (rc && buf != NULL) {
667          navigatingBackAndForth = TRUE;
668          if (*final_url != '\0') {
669             LoadRemoteFileFromMem(final_url, buf, content_type, buf_sz,
670                   is_html);
671          } else {
672             LoadRemoteFileFromMem(full_fname, buf, content_type, buf_sz,
673                   is_html);
674          }
675          navigatingBackAndForth = FALSE;
676       } else if (do_not_save) {
677          SetFileModified(TRUE);
678       }
679       if (content_type != NULL) FreeRemoteBuf(content_type);
680       if (buf != NULL) FreeRemoteBuf(buf);
681    } else {
682       int obj_file=FALSE, gzipped=FALSE;
683 
684       navigatingBackAndForth = TRUE;
685       obj_file = FileNameHasExtension(full_fname, OBJ_FILE_TYPE, &gzipped,
686             NULL);
687       if (!LoadFile(full_fname, obj_file, obj_file && gzipped)) {
688          if (do_not_save) {
689             SetFileModified(TRUE);
690          }
691       }
692       navigatingBackAndForth = FALSE;
693    }
694    navigateRefresh = FALSE;
695 }
696 
NavigateBack()697 void NavigateBack()
698 {
699    int do_not_save=FALSE;
700    struct NavigateRec nr;
701 
702    if (curNavigate != NULL && curNavigate->stk != NULL &&
703          curNavigate->stk == topStk && (curNavigate->prev == NULL ||
704          (curNavigate->prev != NULL && curNavigate->prev->stk != topStk))) {
705       /* curNavigate->stk = NULL; */
706       /* if (curFileDefined) curNavigate = curNavigate->prev; */
707       PopIcon();
708       return;
709    }
710    while (!DirIsRemote(curDir) && fileModified && !IsFiletUnSavable()) {
711       XBell(mainDisplay, 0);
712       switch (MsgBox(TgLoadString(STID_FILE_MOD_SAVE_BEFORE_BACK), TOOL_NAME,
713             YNC_MB)) {
714       case MB_ID_YES: SaveFile(); break;
715       case MB_ID_NO: do_not_save=TRUE; SetFileModified(FALSE); break;
716       case MB_ID_CANCEL: return;
717       }
718    }
719    if (!DirIsRemote(curDir) && fileModified && IsFiletUnSavable()) {
720       do_not_save = TRUE;
721       SetFileModified(FALSE);
722    }
723    MakeQuiescent();
724    if (curNavigate == NULL || (curFileDefined && curNavigate->prev == NULL)) {
725       MsgBox(TgLoadString(STID_NOTHING_TO_GO_BACK_TO), TOOL_NAME, INFO_MB);
726       if (do_not_save) SetFileModified(TRUE);
727       return;
728    }
729    BeforeNavigate();
730    if (curFileDefined) curNavigate = curNavigate->prev;
731    memcpy(&nr, curNavigate, sizeof(struct NavigateRec));
732    NavigateTo(curNavigate->full_fname, do_not_save, FALSE);
733    PostNavigate(&nr);
734    SetCurChoice(curChoiceBeforeMakeQuiescent);
735 }
736 
NavigateForward()737 void NavigateForward()
738 {
739    int do_not_save=FALSE;
740    struct NavigateRec nr;
741 
742    while (!DirIsRemote(curDir) && fileModified && !IsFiletUnSavable()) {
743       XBell(mainDisplay, 0);
744       switch (MsgBox(TgLoadString(STID_FILE_MOD_SAVE_BEFORE_FORWARD), TOOL_NAME,
745             YNC_MB)) {
746       case MB_ID_YES: SaveFile(); break;
747       case MB_ID_NO: do_not_save=TRUE; SetFileModified(FALSE); break;
748       case MB_ID_CANCEL: return;
749       }
750    }
751    if (!DirIsRemote(curDir) && fileModified && IsFiletUnSavable()) {
752       do_not_save = TRUE;
753       SetFileModified(FALSE);
754    }
755    MakeQuiescent();
756    if (curNavigate == lastNavigate) {
757       MsgBox(TgLoadString(STID_NOTHING_TO_GO_FORWARD_TO), TOOL_NAME, INFO_MB);
758       if (do_not_save) SetFileModified(TRUE);
759       return;
760    }
761    BeforeNavigate();
762    if (curFileDefined) curNavigate = curNavigate->next;
763    memcpy(&nr, curNavigate, sizeof(struct NavigateRec));
764    NavigateTo(curNavigate->full_fname, do_not_save, FALSE);
765    PostNavigate(&nr);
766    SetCurChoice(curChoiceBeforeMakeQuiescent);
767 }
768 
AdjustNavigate()769 void AdjustNavigate()
770 {
771    while (curNavigate != NULL && curNavigate->stk != NULL &&
772          curNavigate->stk == topStk) {
773       curNavigate->stk = NULL;
774       if (curNavigate->prev == NULL || (curNavigate->prev != NULL &&
775             curNavigate->prev->stk != topStk)) {
776          if (curFileDefined && curNavigate->prev != NULL) {
777             curNavigate = curNavigate->prev;
778          }
779          return;
780       } else {
781          curNavigate = curNavigate->prev;
782       }
783    }
784    sprintf(gszMsgBox, TgLoadString(STID_FAIL_TO_FIND_RECORD_IN_FUNC),
785          "AdjustNavigate()");
786    FatalUnexpectedError(gszMsgBox,
787          TgLoadString(STID_FURTHER_NAVIGATE_MAY_CRASH));
788 }
789 
NavigateRefresh()790 void NavigateRefresh()
791 {
792    if (!curFileDefined) {
793       MsgBox(TgLoadString(STID_CANT_REFRESH_UNDEFINED_FILE), TOOL_NAME,
794             INFO_MB);
795       return;
796    }
797    while (!DirIsRemote(curDir) && fileModified && !IsFiletUnSavable()) {
798       XBell(mainDisplay, 0);
799       switch (MsgBox(TgLoadString(STID_FILE_MOD_SAVE_BEFORE_RELOAD), TOOL_NAME,
800             YNC_MB)) {
801       case MB_ID_YES: SaveFile(); break;
802       case MB_ID_NO: SetFileModified(FALSE); break;
803       case MB_ID_CANCEL: return;
804       }
805    }
806    if (!DirIsRemote(curDir) && fileModified && IsFiletUnSavable()) {
807       SetFileModified(FALSE);
808    }
809    NavigateTo(curNavigate->full_fname, TRUE, TRUE);
810    PostNavigate(NULL);
811 }
812 
813 static
ReadHotListFile(pn_count)814 char **ReadHotListFile(pn_count)
815    int *pn_count;
816 {
817    FILE *fp;
818    char **ppsz_buf=NULL, *buf;
819    int num_lines=0;
820 
821    if (pn_count != NULL) *pn_count = 0;
822    if (!InitHotListFileName() || hotListFileName==NULL) {
823       sprintf(gszMsgBox, TgLoadString(STID_HOT_LIST_FILE_UNDEF_PLS_SPEC),
824             TOOL_NAME, "HotListFileName");
825       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
826       return NULL;
827    }
828    if ((ppsz_buf=(char**)malloc((num_lines+1)*sizeof(char*))) == NULL) {
829       FailAllocMessage();
830       return NULL;
831    }
832    if ((fp=fopen(hotListFileName, "r")) == NULL) {
833       ppsz_buf[num_lines] = NULL;
834       return ppsz_buf;
835    }
836    while ((buf=UtilGetALine(fp)) != NULL) {
837       if ((ppsz_buf=(char**)realloc(ppsz_buf,
838             ((++num_lines)+1)*sizeof(char*))) == NULL) {
839          FailAllocMessage();
840          return NULL;
841       }
842       ppsz_buf[num_lines-1] = buf;
843    }
844    ppsz_buf[num_lines] = NULL;
845    if ((num_lines & 0x1) != 0) {
846       ppsz_buf[num_lines-1] = NULL;
847       sprintf(gszMsgBox, TgLoadString(STID_MALFORMED_NAMED_HOT_LIST_FILE),
848             hotListFileName);
849       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
850    }
851    fclose(fp);
852    if (pn_count != NULL) *pn_count = (num_lines>>1);
853    return ppsz_buf;
854 }
855 
856 static
HotListListing(ppsz_buf,pn_count)857 DspList *HotListListing(ppsz_buf, pn_count)
858    char **ppsz_buf;
859    int *pn_count;
860 {
861    int i;
862    char **s_ptr;
863    DspList *pdl, *dsp_ptr;
864 
865    *pn_count = 0;
866    for (s_ptr=ppsz_buf; *s_ptr != NULL; s_ptr=(&s_ptr[2])) {
867       (*pn_count)++;
868    }
869    pdl = (DspList*)malloc((*pn_count)*sizeof(DspList));
870    if (pdl == NULL) FailAllocMessage();
871    memset(pdl, 0, (*pn_count)*sizeof(DspList));
872    for (i=(*pn_count)-1, dsp_ptr=pdl, s_ptr=ppsz_buf; *s_ptr != NULL;
873          i--, dsp_ptr++, s_ptr=(&s_ptr[2])) {
874       if (**s_ptr == '\0') {
875          UtilStrCpyN(dsp_ptr->itemstr, sizeof(dsp_ptr->itemstr), s_ptr[1]);
876          dsp_ptr->directory = FALSE; /* use file name as title */
877       } else {
878          UtilStrCpyN(dsp_ptr->itemstr, sizeof(dsp_ptr->itemstr), s_ptr[0]);
879          dsp_ptr->directory = TRUE; /* file has a title */
880       }
881       UtilStrCpyN(dsp_ptr->pathstr, sizeof(dsp_ptr->pathstr), s_ptr[1]);
882       dsp_ptr->next = (i==0 ? NULL : &dsp_ptr[1]);
883    }
884    return pdl;
885 }
886 
887 static
HistoryListing(pn_count)888 DspList *HistoryListing(pn_count)
889    int *pn_count;
890 {
891    int i;
892    struct NavigateRec *pnr;
893    DspList *pdl, *dsp_ptr;
894 
895    *pn_count = 0;
896    for (pnr=lastSessionHistory; pnr != NULL; pnr=pnr->prev) {
897       (*pn_count)++;
898    }
899    if (*pn_count == 0) return NULL;
900    pdl = (DspList*)malloc((*pn_count)*sizeof(DspList));
901    if (pdl == NULL) FailAllocMessage();
902    memset(pdl, 0, (*pn_count)*sizeof(DspList));
903    for (i=0, dsp_ptr=pdl, pnr=firstSessionHistory; pnr != NULL;
904          i++, dsp_ptr++, pnr=pnr->next) {
905       if (pnr->doc_name == NULL) {
906          UtilStrCpyN(dsp_ptr->itemstr, sizeof(dsp_ptr->itemstr),
907                pnr->full_fname);
908          dsp_ptr->directory = FALSE; /* use file name as title */
909       } else {
910          UtilStrCpyN(dsp_ptr->itemstr, sizeof(dsp_ptr->itemstr), pnr->doc_name);
911          dsp_ptr->directory = TRUE; /* file has a title */
912       }
913       UtilStrCpyN(dsp_ptr->pathstr, sizeof(dsp_ptr->pathstr), pnr->full_fname);
914       dsp_ptr->next = (i==(*pn_count)-1 ? NULL : &dsp_ptr[1]);
915    }
916    return pdl;
917 }
918 
919 struct HotListInfoRec {
920    char **ppsz_buf;
921 };
922 
923 #define GOTO_BUTTON 101
924 #define DELETE_BUTTON 102
925 #define CLOSE_BUTTON 103
926 
927 static
GetHotListEntries(p_dsp_ptr,p_entries,pn_num_entries,pn_marked_index,pp_check_array,cur_buf,p_void)928 int GetHotListEntries(p_dsp_ptr, p_entries, pn_num_entries, pn_marked_index,
929       pp_check_array, cur_buf, p_void)
930    DspList **p_dsp_ptr;
931    char ***p_entries, *cur_buf;
932    int *pn_num_entries, *pn_marked_index;
933    struct CheckArrayRec **pp_check_array;
934    void *p_void;
935 {
936    struct HotListInfoRec *p_hlinfo=(struct HotListInfoRec *)p_void;
937 
938    p_hlinfo->ppsz_buf = ReadHotListFile(NULL);
939 
940    if (p_hlinfo->ppsz_buf == NULL) {
941       return FALSE;
942    } else if (*p_hlinfo->ppsz_buf == NULL) {
943       MsgBox(TgLoadString(STID_HOT_LIST_FILE_IS_EMPTY), TOOL_NAME, INFO_MB);
944       free(p_hlinfo->ppsz_buf);
945       p_hlinfo->ppsz_buf = NULL;
946       return FALSE;
947    } else {
948       *p_dsp_ptr = HotListListing(p_hlinfo->ppsz_buf, pn_num_entries);
949 
950       ignoreDirectoryFlag = TRUE;
951       *p_entries = MakeNameDspItemArray(*pn_num_entries, *p_dsp_ptr);
952       ignoreDirectoryFlag = FALSE;
953    }
954    return TRUE;
955 }
956 
957 static
HotListAfterLoop(p_dsp_ptr,p_entries,pn_num_entries,pn_marked_index,pp_check_array,cur_buf,btn_id,selected_index,p_void)958 int HotListAfterLoop(p_dsp_ptr, p_entries, pn_num_entries, pn_marked_index,
959       pp_check_array, cur_buf, btn_id, selected_index, p_void)
960    DspList **p_dsp_ptr;
961    char ***p_entries, *cur_buf;
962    int *pn_num_entries, *pn_marked_index, btn_id, selected_index;
963    struct CheckArrayRec **pp_check_array;
964    void *p_void;
965 {
966    int i, modified=FALSE, something_deleted=FALSE, goto_something=FALSE;
967    int navigated_to=FALSE;
968    struct HotListInfoRec *p_hlinfo=(struct HotListInfoRec *)p_void;
969    char **s_ptr;
970 
971    switch (btn_id) {
972    case GOTO_BUTTON: goto_something=TRUE; break;
973    case DELETE_BUTTON: something_deleted=TRUE; break;
974    }
975    for (s_ptr=p_hlinfo->ppsz_buf, i=0; *s_ptr != NULL; s_ptr=(&s_ptr[2]), i++) {
976       if (something_deleted && i == (*pn_marked_index)) {
977          sprintf(gszMsgBox, TgLoadString(STID_Q_DEL_NAMED_FROM_HOT_LIST),
978                (**s_ptr == '\0' ? s_ptr[1] : *s_ptr));
979          if (MsgBox(gszMsgBox, TOOL_NAME, YNC_MB)==MB_ID_YES) {
980             *s_ptr[0] = *s_ptr[1] = '\0';
981             modified = TRUE;
982             continue;
983          }
984       }
985       if (*s_ptr[0] == '\0') {
986          if (strcmp((*p_entries)[i], s_ptr[1]) != 0) {
987             free(*s_ptr);
988             if (((*s_ptr)=UtilStrDup((*p_entries)[i])) == NULL) {
989                FailAllocMessage();
990             }
991             modified = TRUE;
992          }
993       } else {
994          if (strcmp((*p_entries)[i], *s_ptr) != 0) {
995             free(*s_ptr);
996             if (((*s_ptr)=UtilStrDup((*p_entries)[i])) == NULL) {
997                FailAllocMessage();
998             }
999             modified = TRUE;
1000          }
1001       }
1002    }
1003    if (modified || something_deleted) {
1004       FILE *fp;
1005 
1006       if ((fp=fopen(hotListFileName, "w")) == NULL) {
1007          sprintf(gszMsgBox, TgLoadString(STID_CANNOT_OPEN_FILE_FOR_WRITING),
1008                hotListFileName);
1009          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1010       } else {
1011          for (s_ptr=p_hlinfo->ppsz_buf; *s_ptr != NULL; s_ptr=(&s_ptr[2])) {
1012             if (!(**s_ptr == '\0' && *s_ptr[1] == '\0')) {
1013                fprintf(fp, "%s\n%s\n", *s_ptr, s_ptr[1]);
1014             }
1015          }
1016          fclose(fp);
1017       }
1018    }
1019    free(*p_dsp_ptr);
1020    free(**p_entries);
1021    free(*p_entries);
1022    *p_entries = NULL;
1023 
1024    if (goto_something) {
1025       int do_not_save=FALSE, canceled=FALSE;
1026 
1027       while (!canceled && !DirIsRemote(curDir) && fileModified &&
1028             !IsFiletUnSavable()) {
1029          switch (MsgBox(TgLoadString(STID_FILE_MOD_SAVE_BEFORE_OPEN_ANO),
1030                TOOL_NAME, YNC_MB)) {
1031          case MB_ID_YES: SaveFile(); break;
1032          case MB_ID_NO: do_not_save=TRUE; SetFileModified(FALSE); break;
1033          case MB_ID_CANCEL: canceled=TRUE; break;
1034          }
1035       }
1036       if (!canceled && !DirIsRemote(curDir) && fileModified &&
1037             IsFiletUnSavable()) {
1038          do_not_save = TRUE;
1039          SetFileModified(FALSE);
1040       }
1041       if (!canceled) {
1042          for (i=0, s_ptr=p_hlinfo->ppsz_buf; *s_ptr != NULL;
1043                s_ptr=(&s_ptr[2]), i++) {
1044             if (i == (*pn_marked_index)) {
1045                NavigateTo(s_ptr[1], do_not_save, FALSE);
1046                CommitNavigate();
1047                navigated_to = TRUE;
1048                break;
1049             }
1050          }
1051       }
1052    }
1053    for (s_ptr=p_hlinfo->ppsz_buf; *s_ptr != NULL; s_ptr++) free(*s_ptr);
1054    free(p_hlinfo->ppsz_buf);
1055    p_hlinfo->ppsz_buf = NULL;
1056 
1057    if (something_deleted) {
1058       if (modified) {
1059          (*pn_marked_index)--;
1060       }
1061    } else if (!goto_something) {
1062       (*pn_marked_index) = (*pn_num_entries)-1;
1063    }
1064    if ((*pn_marked_index) < 0) (*pn_marked_index) = INVALID;
1065 
1066    if (navigated_to) {
1067       PostNavigate(NULL);
1068    }
1069    return TRUE;
1070 }
1071 
1072 static
GetHistoryEntries(p_dsp_ptr,p_entries,pn_num_entries,pn_marked_index,cur_buf,p_void)1073 int GetHistoryEntries(p_dsp_ptr, p_entries, pn_num_entries, pn_marked_index,
1074       cur_buf, p_void)
1075    DspList **p_dsp_ptr;
1076    char ***p_entries, *cur_buf;
1077    int *pn_num_entries, *pn_marked_index;
1078    void *p_void;
1079 {
1080    *p_dsp_ptr = HistoryListing(pn_num_entries);
1081    if (*p_dsp_ptr == NULL) {
1082       MsgBox(TgLoadString(STID_SESSION_HIST_NOT_ESTABLISHED), TOOL_NAME,
1083             INFO_MB);
1084       return FALSE;
1085    } else {
1086       ignoreDirectoryFlag = TRUE;
1087       *p_entries = MakeNameDspItemArray(*pn_num_entries, *p_dsp_ptr);
1088       ignoreDirectoryFlag = FALSE;
1089       if (*pn_marked_index == INVALID) {
1090          *pn_marked_index = (*pn_num_entries)-1;
1091       }
1092    }
1093    return TRUE;
1094 }
1095 
1096 static
HistoryAfterLoop(p_dsp_ptr,p_entries,pn_num_entries,pn_marked_index,cur_buf,btn_id,selected_index,p_void)1097 int HistoryAfterLoop(p_dsp_ptr, p_entries, pn_num_entries, pn_marked_index,
1098       cur_buf, btn_id, selected_index, p_void)
1099    DspList **p_dsp_ptr;
1100    char ***p_entries, *cur_buf;
1101    int *pn_num_entries, *pn_marked_index, btn_id, selected_index;
1102    void *p_void;
1103 {
1104    int goto_something=(btn_id == GOTO_BUTTON), navigated_to=FALSE;
1105 
1106    free(*p_dsp_ptr);
1107    free(**p_entries);
1108    free(*p_entries);
1109    *p_entries = NULL;
1110 
1111    if (goto_something) {
1112       int do_not_save=FALSE, canceled=FALSE;
1113 
1114       while (!canceled && !DirIsRemote(curDir) && fileModified &&
1115             !IsFiletUnSavable()) {
1116          switch (MsgBox(TgLoadString(STID_FILE_MOD_SAVE_BEFORE_OPEN_ANO),
1117                TOOL_NAME, YNC_MB)) {
1118          case MB_ID_YES: SaveFile(); break;
1119          case MB_ID_NO: do_not_save=TRUE; SetFileModified(FALSE); break;
1120          case MB_ID_CANCEL: canceled=TRUE; break;
1121          }
1122       }
1123       if (!canceled && !DirIsRemote(curDir) && fileModified &&
1124             IsFiletUnSavable()) {
1125          do_not_save = TRUE;
1126          SetFileModified(FALSE);
1127       }
1128       if (!canceled) {
1129          int i;
1130          struct NavigateRec *pnr;
1131 
1132          pnr = firstSessionHistory;
1133          for (i=0; pnr != NULL; pnr=pnr->next, i++) {
1134             if (i == (*pn_marked_index)) {
1135                NavigateTo(pnr->full_fname, do_not_save, FALSE);
1136                CommitNavigate();
1137                navigated_to = TRUE;
1138                break;
1139             }
1140          }
1141       }
1142    }
1143    if (navigated_to) {
1144       PostNavigate(NULL);
1145    }
1146    return TRUE;
1147 }
1148 
1149 static
SelectForNavigate(TopStr,Which)1150 void SelectForNavigate(TopStr, Which)
1151    char *TopStr;
1152    int Which; /* either NAVIGATE_HOTLIST or NAVIGATE_HISTORY */
1153 {
1154    char win_name[128];
1155    struct HotListInfoRec hlinfo;
1156 
1157    memset(&hlinfo, 0, sizeof(struct HotListInfoRec));
1158 
1159    ResetNamesInfo();
1160    NamesSetTitle(TopStr);
1161    NamesSetDefaultBtnId(GOTO_BUTTON, GOTO_BUTTON);
1162    NamesSetEntries(NULL, NULL, 0, NULL, TRUE, INVALID, 0);
1163    switch (Which) {
1164    case NAVIGATE_HOTLIST:
1165       NamesAddButton(TgLoadCachedString(CSTID_GOTO), GOTO_BUTTON);
1166       NamesAddButton(TgLoadCachedString(CSTID_DELETE), DELETE_BUTTON);
1167       NamesAddButton(TgLoadCachedString(CSTID_CLOSE), BUTTON_CANCEL);
1168       NamesSetStyle(NAMES_EDIT_NAME, NAMES_LOOP_MANY);
1169       NamesSetCallback((GetEntriesFunc*)GetHotListEntries,
1170             (AfterLoopFunc*)HotListAfterLoop, NULL);
1171       sprintf(win_name, TgLoadString(STID_TOOL_HOT_LIST), TOOL_NAME);
1172       break;
1173    case NAVIGATE_HISTORY:
1174       NamesAddButton(TgLoadCachedString(CSTID_GOTO), GOTO_BUTTON);
1175       NamesAddButton(TgLoadCachedString(CSTID_CLOSE), BUTTON_CANCEL);
1176       NamesSetStyle(NAMES_COMPLEX_SELECT_NAME, NAMES_LOOP_MANY);
1177       NamesSetCallback((GetEntriesFunc*)GetHistoryEntries,
1178             (AfterLoopFunc*)HistoryAfterLoop, NULL);
1179       sprintf(win_name, TgLoadString(STID_TOOL_HOT_LIST), TOOL_NAME);
1180       break;
1181    default: return;
1182    }
1183    Names(win_name, NULL, NULL, 0, &hlinfo);
1184 }
1185 
NavigateHotList()1186 void NavigateHotList()
1187 {
1188    MakeQuiescent();
1189    if (!InitHotListFileName() || hotListFileName==NULL) {
1190       sprintf(gszMsgBox, TgLoadString(STID_HOT_LIST_FILE_UNDEF_PLS_SPEC),
1191             TOOL_NAME, "HotListFileName");
1192       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1193       return;
1194    }
1195    SelectForNavigate(TgLoadString(STID_HOT_LIST_DOTS), NAVIGATE_HOTLIST);
1196    SetCurChoice(curChoiceBeforeMakeQuiescent);
1197 }
1198 
NavigateAddToHotList()1199 void NavigateAddToHotList()
1200 {
1201    int len=strlen(curDir)+1+strlen(curFileName), num_entries=0;
1202    char **s_ptr, **ppsz_buf, *full_fname;
1203    FILE *fp;
1204 
1205    if (!curFileDefined) {
1206       MsgBox(TgLoadString(STID_CANT_ADD_UNDEF_TO_HOT_LIST), TOOL_NAME, INFO_MB);
1207       return;
1208    }
1209    if ((full_fname=(char*)malloc((len+1)*sizeof(char))) == NULL) {
1210       FailAllocMessage();
1211       return;
1212    }
1213    sprintf(full_fname, "%s%c%s", curDir, DIR_SEP, curFileName);
1214    if ((ppsz_buf=ReadHotListFile(&num_entries)) == NULL) return;
1215    if ((fp=fopen(hotListFileName, "w")) == NULL) {
1216       sprintf(gszMsgBox, TgLoadString(STID_CANNOT_OPEN_FILE_FOR_WRITING),
1217             hotListFileName);
1218       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1219       free(full_fname);
1220       return;
1221    }
1222    for (s_ptr=ppsz_buf; *s_ptr != NULL; s_ptr=(&s_ptr[2])) {
1223       if (strcmp(s_ptr[1], full_fname) == 0) {
1224          char **s_ptr1;
1225 
1226          if (s_ptr[2] != NULL) {
1227             for (s_ptr1=ppsz_buf; s_ptr1 != s_ptr; s_ptr1++) {
1228                fprintf(fp, "%s\n", *s_ptr1);
1229             }
1230             for (s_ptr1=(&s_ptr[2]); *s_ptr1 != NULL; s_ptr1++) {
1231                fprintf(fp, "%s\n", *s_ptr1);
1232             }
1233          } else {
1234             for (s_ptr1=ppsz_buf; s_ptr1 != s_ptr; s_ptr1++) {
1235                fprintf(fp, "%s\n", *s_ptr1);
1236             }
1237          }
1238          fprintf(fp, "%s\n", (firstPage->name==NULL ? "" : firstPage->name));
1239          fprintf(fp, "%s\n", full_fname);
1240          break;
1241       }
1242    }
1243    if (*s_ptr == NULL) {
1244       for (s_ptr=ppsz_buf; *s_ptr != NULL; s_ptr++) {
1245          fprintf(fp, "%s\n", *s_ptr);
1246       }
1247       fprintf(fp, "%s\n", (firstPage->name==NULL ? "" : firstPage->name));
1248       fprintf(fp, "%s\n", full_fname);
1249       num_entries++;
1250    }
1251    for (s_ptr=ppsz_buf; *s_ptr != NULL; s_ptr++) free(*s_ptr);
1252    free(ppsz_buf);
1253    fclose(fp);
1254    free(full_fname);
1255    Msg(TgLoadString(STID_HOT_LIST_FILE_UPDATED));
1256 }
1257 
NavigateSessionHistory()1258 void NavigateSessionHistory()
1259 {
1260    MakeQuiescent();
1261    SelectForNavigate(TgLoadString(STID_SESSION_HISTORY_DOTS), NAVIGATE_HISTORY);
1262    SetCurChoice(curChoiceBeforeMakeQuiescent);
1263 }
1264 
ToggleHyperSpace(KeepSelected)1265 void ToggleHyperSpace(KeepSelected)
1266    int KeepSelected;
1267 {
1268    inHyperSpace = !inHyperSpace;
1269    if (inHyperSpace) {
1270       if (!KeepSelected) MakeQuiescent();
1271       Msg(TgLoadString(STID_ENTER_HYPERSPACE_DOTS));
1272    } else {
1273       ShowCursor();
1274       Msg(TgLoadString(STID_LEAVING_HYPERSPACE_DOTS));
1275    }
1276    UpdatePinnedMenu(MENU_NAVIGATE);
1277    RedrawDummyWindow1();
1278 }
1279 
NextSlide()1280 void NextSlide()
1281 {
1282    struct ObjRec *obj_ptr=FindTopLevelObjWithType("page_defaultplay");
1283 
1284    if (obj_ptr != NULL) {
1285       struct AttrRec *exec_attr=FindObjAttrWithName(obj_ptr, "exec=");
1286       struct AttrRec *attr_ptr=FindObjAttrWithName(obj_ptr, "finished=");
1287 
1288       if (exec_attr != NULL && attr_ptr != NULL) {
1289          char *attr_value=attr_ptr->attr_value.s;
1290 
1291          if (strcmp(attr_value, "0") == 0) {
1292             DoExecLoop(obj_ptr, exec_attr);
1293             /*
1294              * if (!userAbortExec) {
1295              *    ReplaceAttrFirstValue(obj_ptr, attr_ptr, "1");
1296              * }
1297              */
1298             return;
1299          }
1300       }
1301    }
1302    NextPage();
1303 }
1304 
PrevSlide()1305 void PrevSlide()
1306 {
1307    struct ObjRec *obj_ptr=FindTopLevelObjWithType("page_defaultrewind");
1308 
1309    if (obj_ptr != NULL) {
1310       struct AttrRec *exec_attr=FindObjAttrWithName(obj_ptr, "exec=");
1311       struct AttrRec *attr_ptr=FindObjAttrWithName(obj_ptr, "finished=");
1312 
1313       if (exec_attr != NULL && attr_ptr != NULL) {
1314          char *attr_value=attr_ptr->attr_value.s;
1315 
1316          if (strcmp(attr_value, "0") == 0) {
1317             DoExecLoop(obj_ptr, exec_attr);
1318             /*
1319              * if (!userAbortExec) {
1320              *    ReplaceAttrFirstValue(obj_ptr, attr_ptr, "1");
1321              * }
1322              */
1323             return;
1324          }
1325       }
1326    }
1327    PrevPage();
1328 }
1329 
1330 struct SlideShowInfoRec {
1331    int saved_in_hyperspace;
1332    int saved_fill, saved_pen;
1333    int saved_line_width, saved_line_style, saved_cur_dash;
1334 };
1335 static struct SlideShowInfoRec gstSlideShow;
1336 
1337 static
HideAllWindowsForSlideShow()1338 void HideAllWindowsForSlideShow()
1339 {
1340    int i=0;
1341 
1342    if (canvasWindowOnly || !hideWindowsInSlideShow) return;
1343 
1344    XUnmapWindow(mainDisplay, titleWindow);
1345    if (menubarWindow != None) XUnmapWindow(mainDisplay, menubarWindow);
1346    if (!noChoiceWindow) XUnmapWindow(mainDisplay, msgWindow);
1347    if (!noChoiceWindow) XUnmapWindow(mainDisplay, choiceWindow);
1348 
1349    XUnmapWindow(mainDisplay, hRuleWindow);
1350    XUnmapWindow(mainDisplay, vRuleWindow);
1351 
1352    XUnmapWindow(mainDisplay, colorWindow);
1353    XUnmapWindow(mainDisplay, colorDummyWindow);
1354    XUnmapWindow(mainDisplay, vSBarWindow);
1355    XUnmapWindow(mainDisplay, pageWindow);
1356    XUnmapWindow(mainDisplay, pageDummyWindow);
1357    XUnmapWindow(mainDisplay, hSBarWindow);
1358    XUnmapWindow(mainDisplay, dummyWindow1);
1359    XUnmapWindow(mainDisplay, dummyWindow2);
1360    if (!noChatWindow) XUnmapWindow(mainDisplay, chatWindow);
1361    if (!noStatusWindow) {
1362       XUnmapWindow(mainDisplay, userRedrawWindow);
1363       XUnmapWindow(mainDisplay, statusWindow);
1364       for (i=0; i < MAX_STATUS_BTNS; i++) {
1365          XUnmapWindow(mainDisplay, statusSubWindow[i]);
1366       }
1367    }
1368    if (!noModeWindow) XUnmapWindow(mainDisplay, modeWindow);
1369 }
1370 
1371 static
ShowAllWindowsForSlideShow()1372 void ShowAllWindowsForSlideShow()
1373 {
1374    int i=0;
1375 
1376    if (canvasWindowOnly || !hideWindowsInSlideShow) return;
1377 
1378    XMapWindow(mainDisplay, titleWindow);
1379    if (menubarWindow != None) XMapWindow(mainDisplay, menubarWindow);
1380    if (!noChoiceWindow) XMapWindow(mainDisplay, msgWindow);
1381    if (!noChoiceWindow) XMapWindow(mainDisplay, choiceWindow);
1382 
1383    XMapWindow(mainDisplay, hRuleWindow);
1384    XMapWindow(mainDisplay, vRuleWindow);
1385 
1386    XMapWindow(mainDisplay, colorWindow);
1387    XMapWindow(mainDisplay, colorDummyWindow);
1388    XMapWindow(mainDisplay, vSBarWindow);
1389    XMapWindow(mainDisplay, pageWindow);
1390    XMapWindow(mainDisplay, pageDummyWindow);
1391    XMapWindow(mainDisplay, hSBarWindow);
1392    XMapWindow(mainDisplay, dummyWindow1);
1393    XMapWindow(mainDisplay, dummyWindow2);
1394    if (!noChatWindow) XMapWindow(mainDisplay, chatWindow);
1395    if (!noStatusWindow) {
1396       XMapWindow(mainDisplay, userRedrawWindow);
1397       XMapWindow(mainDisplay, statusWindow);
1398       for (i=0; i < MAX_STATUS_BTNS; i++) {
1399          XMapWindow(mainDisplay, statusSubWindow[i]);
1400       }
1401    }
1402    if (!noModeWindow) XMapWindow(mainDisplay, modeWindow);
1403 }
1404 
1405 static
StartSlideShow()1406 void StartSlideShow()
1407 {
1408    struct AttrRec *exec_attr=FindFileAttrWithName("start_slide_show=");
1409 
1410    gstSlideShow.saved_in_hyperspace = inHyperSpace;
1411    gstSlideShow.saved_fill = objFill;
1412    gstSlideShow.saved_pen = penPat;
1413    gstSlideShow.saved_line_width = lineWidth;
1414    gstSlideShow.saved_line_style = lineStyle;
1415    gstSlideShow.saved_cur_dash = curDash;
1416    objFill = NONEPAT;
1417    penPat = SOLIDPAT;
1418    lineStyle = LS_PLAIN;
1419    curDash = 0;
1420    lineWidth = lineWidthIndexInSlideShow;
1421 
1422    if (!goHyperSpaceInSlideShow) {
1423       SetCurChoice(FREEHAND);
1424    }
1425    if (slideShowBorderColor != NULL) {
1426       int new_alloc=FALSE, index=0;
1427 
1428       index = QuickFindColorIndex(NULL, slideShowBorderColor, &new_alloc,
1429             FALSE);
1430       if (index != INVALID) {
1431          XSetWindowBackground(mainDisplay, mainWindow, colorPixels[index]);
1432       }
1433    } else if (myFileBgColorStr != NULL && myFileBgPixel != INVALID) {
1434       XSetWindowBackground(mainDisplay, mainWindow, myFileBgPixel);
1435    }
1436    if (goHyperSpaceInSlideShow && !inHyperSpace) {
1437       ToggleHyperSpace(FALSE);
1438    }
1439    FixPageNumbersForSlideShow();
1440    ClearObjCachesInAllPages();
1441    HideAllWindowsForSlideShow();
1442    HidePopupMenusForSlideShow();
1443 
1444    RecordWBSlideShow(TRUE);
1445 
1446    if (exec_attr != NULL) {
1447       DoExecLoop(NULL, exec_attr);
1448    }
1449 }
1450 
1451 static
EndSlideShow()1452 void EndSlideShow()
1453 {
1454    XSetWindowBackground(mainDisplay, mainWindow, myBgPixel);
1455 
1456    RecordWBSlideShow(FALSE);
1457 
1458    ShowAllWindowsForSlideShow();
1459    ShowPopupMenusForSlideShow();
1460    ClearObjCachesInAllPages();
1461    if (gstSlideShow.saved_in_hyperspace != inHyperSpace) {
1462       ToggleHyperSpace(FALSE);
1463    }
1464    objFill = gstSlideShow.saved_fill;
1465    penPat = gstSlideShow.saved_pen;
1466    lineWidth = gstSlideShow.saved_line_width;
1467    lineStyle = gstSlideShow.saved_line_style;
1468    curDash = gstSlideShow.saved_cur_dash;
1469    ShowFill();
1470    ShowPen();
1471    ShowLineWidth();
1472    ShowLineStyle();
1473    ShowDash();
1474    UpdatePinnedMenu(MENU_FILL);
1475    UpdatePinnedMenu(MENU_PEN);
1476    UpdatePinnedMenu(MENU_LINEWIDTH);
1477    UpdatePinnedMenu(MENU_LINESTYLE);
1478    UpdatePinnedMenu(MENU_LINEDASH);
1479    MakeQuiescent();
1480 }
1481 
1482 static
ToggleSlideShow()1483 void ToggleSlideShow()
1484 {
1485    int need_to_restore_cur_choice=FALSE;
1486 
1487    if (!inSlideShow) {
1488       if (pageLayoutMode == PAGE_TILE) {
1489          switch (MsgBox(TgLoadString(STID_CANT_SLIDESHOW_IN_TILED_PAGE),
1490                TOOL_NAME, YNC_MB)) {
1491          case MB_ID_YES: SetUnSavableFile(TRUE); break;
1492          case MB_ID_NO: return;
1493          case MB_ID_CANCEL: return;
1494          }
1495          PageLayoutSubMenu(PAGE_STACK);
1496          if (pageLayoutMode != PAGE_STACK) return;
1497       } else {
1498          if (fileModified && !IsFiletUnSavable() &&
1499                ((curFileDefined && !DirIsRemote(curDir)) || !curFileDefined)) {
1500             XBell(mainDisplay, 0);
1501             switch (MsgBox(TgLoadString(STID_FILE_MOD_SAVE_BEFORE_SLIDE),
1502                   TOOL_NAME, YNC_MB)) {
1503             case MB_ID_YES: SaveFile(); break;
1504             case MB_ID_NO: break;
1505             case MB_ID_CANCEL: return;
1506             }
1507          }
1508          if (!IsFiletUnSavable() && (makeUnsavableInSlideShow ||
1509                NeedToFixPageNumbersForSlideShow())) {
1510             if (!makeUnsavableInSlideShow) {
1511                sprintf(gszMsgBox,
1512                      TgLoadString(STID_Q_PAGE_NUM_MOD_IN_SLIDE_YNC), TOOL_NAME);
1513                switch (MsgBox(gszMsgBox, TOOL_NAME, YNC_MB)) {
1514                case MB_ID_YES: break;
1515                case MB_ID_NO: return;
1516                case MB_ID_CANCEL: return;
1517                }
1518             }
1519             SetUnSavableFile(TRUE);
1520          }
1521       }
1522       MakeQuiescent();
1523       need_to_restore_cur_choice = TRUE;
1524    }
1525    inSlideShow = !inSlideShow;
1526 
1527    if (inSlideShow) {
1528       Msg(TgLoadString(STID_ENTERING_SLIDESHOW_DOTS));
1529       StartSlideShow();
1530    } else {
1531       ShowCursor();
1532       Msg(TgLoadString(STID_LEAVING_SLIDESHOW_DOTS));
1533       EndSlideShow();
1534    }
1535    RedrawDummyWindow1();
1536    if (need_to_restore_cur_choice) SetCurChoice(curChoiceBeforeMakeQuiescent);
1537 }
1538 
EnterSlideShow()1539 void EnterSlideShow()
1540 {
1541    if (!inSlideShow) ToggleSlideShow();
1542 }
1543 
LeaveSlideShow()1544 void LeaveSlideShow()
1545 {
1546    if (inSlideShow) ToggleSlideShow();
1547 }
1548 
SetSlideShowBorderColor()1549 void SetSlideShowBorderColor()
1550 {
1551    char spec[MAXSTRING];
1552    int new_alloc=0;
1553 
1554    *spec = '\0';
1555    if (Dialog(TgLoadString(STID_ENTER_A_COLOR_FOR_SLIDE_BRDR),
1556          TgLoadString(STID_PRESS_ENTER_FOR_DEF_COLOR), spec) == INVALID) {
1557       return;
1558    }
1559    UtilTrimBlanks(spec);
1560    if (*spec == '\0') {
1561       if (slideShowBorderColor != NULL) UtilFree(slideShowBorderColor);
1562       slideShowBorderColor = NULL;
1563       Msg(TgLoadString(STID_SLIDE_WILL_USE_DEF_BRDR_COLOR));
1564       if (slideShowXOffset == 0 && slideShowYOffset == 0) {
1565          slideShowInfoValid = FALSE;
1566       }
1567       return;
1568    }
1569    if (QuickFindColorIndex(NULL, spec, &new_alloc, FALSE) == INVALID) {
1570       sprintf(gszMsgBox, TgLoadString(STID_FAIL_ALLOC_NAMED_COLOR), spec);
1571       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1572       return;
1573    }
1574    if (slideShowBorderColor != NULL) UtilFree(slideShowBorderColor);
1575    slideShowBorderColor = UtilStrDup(spec);
1576    if (slideShowBorderColor == NULL) FailAllocMessage();
1577    slideShowInfoValid = TRUE;
1578 
1579    sprintf(gszMsgBox, TgLoadString(STID_SLIDE_BRDR_COLOR_SET_TO_NAMED),
1580          slideShowBorderColor);
1581    Msg(gszMsgBox);
1582 }
1583 
SetSlideShowWindowOffsets()1584 void SetSlideShowWindowOffsets()
1585 {
1586    char spec[MAXSTRING];
1587 
1588    *spec = '\0';
1589    sprintf(gszMsgBox, TgLoadString(STID_ENTER_XY_OFFSET_FOR_SLIDE_WIN),
1590          slideShowXOffset, slideShowYOffset);
1591    if (Dialog(gszMsgBox, NULL, spec) == INVALID) return;
1592    UtilTrimBlanks(spec);
1593    if (*spec == '\0') return;
1594 
1595    if (ParseXYSpec(spec, &slideShowXOffset, &slideShowYOffset)) {
1596       sprintf(gszMsgBox, TgLoadString(STID_SLIDE_WIN_XY_OFFSETS_SET_TO),
1597             slideShowXOffset, slideShowYOffset);
1598       Msg(gszMsgBox);
1599 
1600       savedSlideShowXOffset = slideShowXOffset;
1601       savedSlideShowYOffset = slideShowYOffset;
1602       savedSlideShowOffsets = TRUE;
1603    }
1604    slideShowInfoValid = TRUE;
1605 }
1606 
ToggleVisibleGridInSlideShow()1607 void ToggleVisibleGridInSlideShow()
1608 {
1609    visibleGridInSlideShow = (!visibleGridInSlideShow);
1610    Msg(TgLoadString(visibleGridInSlideShow ? STID_GRID_BE_VISIBLE_IN_SLIDE :
1611          STID_GRID_NOT_BE_VISIBLE_IN_SLIDE));
1612 }
1613 
GoHyperSpaceInSlideShow()1614 void GoHyperSpaceInSlideShow()
1615 {
1616    if (goHyperSpaceInSlideShow) return;
1617 
1618    goHyperSpaceInSlideShow = TRUE;
1619    Msg(TgLoadString(STID_GO_HYPERSPACE_IN_SLIDE));
1620    if (inSlideShow) {
1621       if (!inHyperSpace) {
1622          inSlideShow = FALSE;
1623          ToggleHyperSpace(FALSE);
1624          inSlideShow = TRUE;
1625       }
1626    }
1627 }
1628 
FreehandModeInSlideShow()1629 void FreehandModeInSlideShow()
1630 {
1631    if (!goHyperSpaceInSlideShow) return;
1632 
1633    goHyperSpaceInSlideShow = FALSE;
1634    Msg(TgLoadString(STID_DONT_GO_HYPERSPACE_IN_SLIDE));
1635    if (inSlideShow) {
1636       if (inHyperSpace) {
1637          ToggleHyperSpace(FALSE);
1638       }
1639       SetCurChoice(FREEHAND);
1640    }
1641 }
1642 
RefreshSlideShowModeMenu(menu)1643 int RefreshSlideShowModeMenu(menu)
1644    TgMenu *menu;
1645 {
1646    int ok=TRUE;
1647 
1648    /* GoHyperSpaceInSlideShow */
1649    ok &= TgSetMenuItemRadioById(menu, CMDID_GOHYPERSPACEINSLIDESHOW,
1650          goHyperSpaceInSlideShow);
1651    /* FreehandModeInSlideShow */
1652    ok &= TgSetMenuItemRadioById(menu, CMDID_FREEHANDMODEINSLIDESHOW,
1653          !goHyperSpaceInSlideShow);
1654 
1655    /* ColorMenu */
1656    if (goHyperSpaceInSlideShow) {
1657       ok &= TgEnableMenuItemById(menu, MENU_COLOR, FALSE);
1658    }
1659    return ok;
1660 }
1661 
CreateSlideShowModeMenu(parent_menu,X,Y,menu_info,status_str_xlated)1662 TgMenu *CreateSlideShowModeMenu(parent_menu, X, Y, menu_info, status_str_xlated)
1663    TgMenu *parent_menu;
1664    int X, Y;
1665    TgMenuInfo *menu_info;
1666    int status_str_xlated; /* ignored, always 0 */
1667 {
1668    TgMenu *menu=TgCreateMenuFromMenuInfo(parent_menu, X, Y, menu_info, FALSE);
1669 
1670    if (menu != NULL) {
1671       if (!RefreshSlideShowModeMenu(menu)) {
1672          return TgDestroyMenu(menu, TRUE);
1673       }
1674       menu->refresh_proc =
1675             ((RefreshMenuFunc*)RefreshSlideShowModeMenu);
1676    }
1677    return menu;
1678 }
1679 
SlideShowModeMenu(X,Y,TrackMenubar)1680 int SlideShowModeMenu(X, Y, TrackMenubar)
1681    int X, Y, TrackMenubar;
1682 {
1683    int rc=INVALID;
1684    TgMenu *menu=(slideShowModeMenuInfo.create_proc)(NULL, X, Y,
1685          &slideShowModeMenuInfo, INVALID);
1686 
1687    activeMenu = INVALID;
1688    if (menu != NULL) {
1689       menu->track_menubar = TrackMenubar;
1690 
1691       rc = TgMenuLoop(menu);
1692       TgDestroyMenu(menu, TRUE);
1693    }
1694    return rc;
1695 }
1696 
RefreshSlideShowMenu(menu)1697 int RefreshSlideShowMenu(menu)
1698    TgMenu *menu;
1699 {
1700    int ok=TRUE;
1701 
1702    /* SlideShow */
1703    ok &= TgSetMenuItemCheckById(menu, CMDID_TOGGLESLIDESHOW, inSlideShow);
1704    /* VisibleGridInSlideShow */
1705    ok &= TgSetMenuItemCheckById(menu, CMDID_VISIBLEGRIDINSLIDESHOW,
1706          visibleGridInSlideShow);
1707    /* GoHyperSpaceInSlideShow */
1708    ok &= TgSetMenuItemRadioById(menu, CMDID_GOHYPERSPACEINSLIDESHOW,
1709          goHyperSpaceInSlideShow);
1710    /* FreehandModeInSlideShow */
1711    ok &= TgSetMenuItemRadioById(menu, CMDID_FREEHANDMODEINSLIDESHOW,
1712          !goHyperSpaceInSlideShow);
1713    if (inSlideShow) {
1714       ok &= TgEnableMenuItemById(menu, CMDID_GOHYPERSPACEINSLIDESHOW, FALSE);
1715       ok &= TgEnableMenuItemById(menu, CMDID_FREEHANDMODEINSLIDESHOW, FALSE);
1716    }
1717    return ok;
1718 }
1719 
CreateSlideShowMenu(parent_menu,x,y,menu_info,status_str_xlated)1720 TgMenu *CreateSlideShowMenu(parent_menu, x, y, menu_info, status_str_xlated)
1721    TgMenu *parent_menu;
1722    int x, y;
1723    TgMenuInfo *menu_info;
1724    int status_str_xlated; /* ignored, always 0 */
1725 {
1726    TgMenu *menu=TgCreateMenuFromMenuInfo(parent_menu, x, y, menu_info, FALSE);
1727 
1728    if (menu != NULL) {
1729       if (!RefreshSlideShowMenu(menu)) {
1730          return TgDestroyMenu(menu, TRUE);
1731       }
1732    }
1733    return menu;
1734 }
1735 
ReadSlideShowInfo(buf)1736 int ReadSlideShowInfo(buf)
1737    char *buf;
1738 {
1739    if (!importingFile) {
1740       int x=0, y=0;
1741       char color_str[40], *psz=FindChar((int)'(', buf);
1742 
1743       *color_str = '\0';
1744       psz = ParseStr(psz, (int)',', color_str, sizeof(color_str));
1745       InitScan(psz, "\t\n, []");
1746       if (GETINT("slideshow_info", x, "x offset") == INVALID ||
1747           GETINT("slideshow_info", y, "y offset") == INVALID) {
1748          return FALSE;
1749       }
1750       CleanUpSlideShowInfo();
1751       UtilTrimBlanks(color_str);
1752       if (*color_str != '\0') {
1753          slideShowBorderColor = UtilStrDup(color_str);
1754          if (slideShowBorderColor == NULL) FailAllocMessage();
1755       }
1756       if (!ignoreSlideShowOffsetsInFile) {
1757          slideShowXOffset = x;
1758          slideShowYOffset = y;
1759       } else if (savedSlideShowOffsets) {
1760          slideShowXOffset = savedSlideShowXOffset;
1761          slideShowYOffset = savedSlideShowYOffset;
1762       }
1763       slideShowInfoValid = TRUE;
1764    }
1765    return TRUE;
1766 }
1767 
RefreshNavigateMenu(menu)1768 void RefreshNavigateMenu(menu)
1769    TgMenu *menu;
1770 {
1771    TgMenuItem *menu_item=FindMenuItemByCmdId(menu, CMDID_TOGGLEHYPERSPACE);
1772    TgMenuItem stMenuItem;
1773 
1774    if (menu_item == NULL) return;
1775 
1776    memset(&stMenuItem, 0, sizeof(TgMenuItem));
1777    stMenuItem.checked = inHyperSpace;
1778    TgSetMenuItemInfo(menu_item, TGMU_MASK_CHECK, &stMenuItem);
1779 }
1780 
CreateNavigateMenu(parent_menu,x,y,menu_info,status_str_xlated)1781 TgMenu *CreateNavigateMenu(parent_menu, x, y, menu_info, status_str_xlated)
1782    TgMenu *parent_menu;
1783    int x, y;
1784    TgMenuInfo *menu_info;
1785    int status_str_xlated; /* ignored, always 0 */
1786 {
1787    TgMenu *menu=TgCreateMenuFromMenuInfo(parent_menu, x, y, menu_info, FALSE);
1788 
1789    if (menu != NULL) {
1790       TgMenuItem *menu_item=FindMenuItemByCmdId(menu, CMDID_TOGGLEHYPERSPACE);
1791       TgMenuItem stMenuItem;
1792 
1793       if (menu_item == NULL) return TgDestroyMenu(menu, TRUE);
1794 
1795       memset(&stMenuItem, 0, sizeof(TgMenuItem));
1796       stMenuItem.checked = inHyperSpace;
1797 
1798       if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_CHECK, &stMenuItem)) {
1799          return TgDestroyMenu(menu, TRUE);
1800       }
1801    }
1802    return menu;
1803 }
1804 
NavigateMenu(X,Y,TrackMenubar)1805 int NavigateMenu(X, Y, TrackMenubar)
1806    int X, Y, TrackMenubar;
1807 {
1808    int rc=INVALID;
1809    TgMenu *menu=(navigateMenuInfo.create_proc)(NULL, X, Y, &navigateMenuInfo,
1810          INVALID);
1811 
1812    activeMenu = MENU_NAVIGATE;
1813    if (menu != NULL) {
1814       menu->track_menubar = TrackMenubar;
1815 
1816       rc = TgMenuLoop(menu);
1817       TgDestroyMenu(menu, TRUE);
1818    }
1819    return rc;
1820 }
1821