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/page.c,v 1.15 2011/05/16 16:21:58 william Exp $
19  */
20 
21 #define _INCLUDE_FROM_PAGE_C_
22 
23 #include "tgifdefs.h"
24 #include "expfdefs.h"
25 
26 #include "attr.e"
27 #include "auxtext.e"
28 #include "button.e"
29 #include "cmd.e"
30 #include "choice.e"
31 #include "choose.e"
32 #include "color.e"
33 #include "cursor.e"
34 #include "dialog.e"
35 #include "drawing.e"
36 #include "dup.e"
37 #include "file.e"
38 #include "font.e"
39 #include "grid.e"
40 #include "mark.e"
41 #include "mainloop.e"
42 #include "mainmenu.e"
43 #include "menu.e"
44 #include "menuinfo.e"
45 #include "move.e"
46 #include "msg.e"
47 #include "names.e"
48 #include "navigate.e"
49 #include "obj.e"
50 #include "page.e"
51 #include "raster.e"
52 #include "rect.e"
53 #include "scroll.e"
54 #include "select.e"
55 #include "setup.e"
56 #include "stk.e"
57 #include "strtbl.e"
58 #include "text.e"
59 #include "util.e"
60 #include "wb.e"
61 #include "xpixmap.e"
62 #include "xprtfltr.e"
63 
64 #include "xbm/leftend.xbm"
65 
66 struct PageRec	*firstPage=NULL, *lastPage=NULL, *curPage=NULL;
67 int		curPageNum=1, lastPageNum=1;
68 int		paperRow=1, paperCol=1;
69 int		pageLayoutMode=PAGE_STACK;
70 int		pageLineShownInTileMode=TRUE;
71 
72 static int pageWindowFirstIndex=1;
73 
74 static int gnPageNumOnTab=TRUE;
75 
76 static
DrawAHorizontalTab(page_num,page_ptr,x,y,on_top,skip)77 int DrawAHorizontalTab(page_num, page_ptr, x, y, on_top, skip)
78    int page_num, x, y, on_top, skip;
79    struct PageRec *page_ptr;
80 {
81    char s[20];
82    XPoint v[5];
83    int w=0, num_digits=0, x_offset, y_offset;
84    int bg_pixel=(threeDLook ? myLtGryPixel : myBgPixel);
85 
86    if (gnPageNumOnTab) {
87       sprintf(s, "%1d", page_num);
88       num_digits = strlen(s);
89       w = (num_digits+2)*rulerFontWidth;
90    } else {
91       /* not implemented yet */
92       if (page_ptr->name == NULL) {
93       } else {
94       }
95       w = (num_digits+2)*rulerFontWidth;
96    }
97    if (skip) return w;
98 
99    v[0].x = v[4].x = x;         v[0].y = v[4].y = y-1;
100    v[1].x = x+rulerFontWidth;   v[1].y = y+2+rulerFontHeight;
101    v[2].x = x+w;                v[2].y = y+2+rulerFontHeight;
102    v[3].x = x+w+rulerFontWidth; v[3].y = y-1;
103 
104    XSetForeground(mainDisplay, defaultGC, (on_top ? myBgPixel: bg_pixel));
105    XFillPolygon(mainDisplay, pageWindow, defaultGC, v, 5, Convex,
106          CoordModeOrigin);
107    XSetForeground(mainDisplay, defaultGC, myFgPixel);
108    if (on_top) {
109       XDrawLines(mainDisplay, pageWindow, defaultGC, v, 4, CoordModeOrigin);
110       XSetForeground(mainDisplay, defaultGC, myBgPixel);
111       XDrawLines(mainDisplay, pageWindow, defaultGC, &v[3], 2, CoordModeOrigin);
112       XSetForeground(mainDisplay, defaultGC, myFgPixel);
113    } else {
114       XDrawLines(mainDisplay, pageWindow, defaultGC, v, 5, CoordModeOrigin);
115    }
116    y_offset = ((rulerFontHeight-7)>>1)+1;
117    x_offset = (rulerFontWidth>>1)+rulerFontWidth;
118    XDrawString(mainDisplay, pageWindow, defaultGC, x+x_offset,
119          y+1+rulerFontAsc, s, num_digits);
120    XSetForeground(mainDisplay, defaultGC, myFgPixel);
121    return w;
122 }
123 
124 static
MaxPageTabsWidth()125 int MaxPageTabsWidth()
126 {
127    int i=0, total=0;
128 
129    for (i=1; i <= lastPageNum; i++) {
130       total += DrawAHorizontalTab(i, NULL, 0, 0, FALSE, TRUE);
131    }
132    return total;
133 }
134 
135 static
PageTabsVisible(pn_last_tab_visible)136 int PageTabsVisible(pn_last_tab_visible)
137    int *pn_last_tab_visible;
138 {
139    int i=0, total=pageWindowW-(scrollBarW<<2)-1;
140    int last_tab_visible=pageWindowFirstIndex;
141 
142    for (i=pageWindowFirstIndex; i <= lastPageNum; i++) {
143       total -= DrawAHorizontalTab(i, NULL, 0, 0, FALSE, TRUE);
144       if (total < 0) {
145          break;
146       }
147       last_tab_visible = i;
148    }
149    if (pn_last_tab_visible != NULL) {
150       *pn_last_tab_visible = last_tab_visible;
151    }
152    if (curPageNum >= pageWindowFirstIndex &&
153          curPageNum <= last_tab_visible) {
154       return TRUE;
155    }
156    return FALSE;
157 }
158 
159 static
MakePageTabsVisible(last_tab_visible)160 void MakePageTabsVisible(last_tab_visible)
161    int last_tab_visible;
162 {
163    int total=pageWindowW-(scrollBarW<<2)-1;
164 
165    if (MaxPageTabsWidth() <= total) {
166       pageWindowFirstIndex = 1;
167       return;
168    }
169    if (curPageNum < pageWindowFirstIndex) {
170       while (pageWindowFirstIndex > 1) {
171          pageWindowFirstIndex--;
172          if (PageTabsVisible(NULL)) {
173             return;
174          }
175       }
176    } else if (curPageNum >= pageWindowFirstIndex &&
177          curPageNum <= last_tab_visible) {
178       return;
179    } else {
180       while (pageWindowFirstIndex <= lastPageNum) {
181          pageWindowFirstIndex++;
182          if (PageTabsVisible(NULL)) {
183             return;
184          }
185       }
186 #ifdef _TGIF_DBG /* debug, do not translate */
187       TgAssert(pageWindowFirstIndex > lastPageNum,
188             "pageWindowFirstIndex > lastPageNum in MakePageTabsVisible()", NULL);
189 #endif /* _TGIF_DBG */
190       pageWindowFirstIndex = curPageNum;
191    }
192 }
193 
RedrawPageWindow()194 void RedrawPageWindow()
195 {
196    int i=0, x=0, y=1;
197    struct PageRec *page_ptr=NULL;
198 
199    XClearArea(mainDisplay, pageWindow, 0, 0, pageWindowW,
200          scrollBarW+(brdrW<<1), FALSE);
201    XDrawRectangle(mainDisplay, pageWindow, defaultGC, 0, 0, pageWindowW-1,
202          scrollBarW+(brdrW<<1)-1);
203    if (pageLayoutMode == PAGE_TILE) return;
204 
205    x = 1 + (leftend_width<<2);
206    XSetFont(mainDisplay, defaultGC, rulerFontPtr->fid);
207    for (i=1, page_ptr=firstPage; page_ptr != NULL;
208          page_ptr=page_ptr->next, i++) {
209       if (i >= pageWindowFirstIndex) {
210          int w=0;
211 
212          if (i == curPageNum) {
213             w = DrawAHorizontalTab(i, page_ptr, x, y, TRUE, TRUE);
214          } else {
215             w = DrawAHorizontalTab(i, page_ptr, x, y, FALSE, FALSE);
216          }
217          x += w;
218       }
219    }
220    x = 1 + (leftend_width<<2);
221    for (i=1, page_ptr=firstPage; page_ptr != NULL;
222          page_ptr=page_ptr->next, i++) {
223       if (i >= pageWindowFirstIndex) {
224          int w=0;
225 
226          if (i == curPageNum) {
227             w = DrawAHorizontalTab(i, page_ptr, x, y, TRUE, FALSE);
228             break;
229          } else {
230             w = DrawAHorizontalTab(i, page_ptr, x, y, FALSE, TRUE);
231          }
232          x += w;
233       }
234    }
235    XSetFont(mainDisplay, defaultGC, defaultFontPtr->fid);
236 
237    y = (threeDLook ? (windowPadding>>1) : brdrW);
238    for (i=0, x=y; i < 4; i++, x += leftend_width) {
239       XSetTSOrigin(mainDisplay, rasterGC, x, y);
240       XSetStipple(mainDisplay, rasterGC, scrollPixmap[i]);
241       XFillRectangle(mainDisplay, pageWindow, rasterGC,
242             x, y, leftend_width, leftend_height);
243       if (threeDLook) {
244          struct BBRec bbox;
245 
246          SetBBRec(&bbox, x, y, x+leftend_height, y+leftend_height);
247          TgDrawThreeDButton(mainDisplay, pageWindow, textMenuGC, &bbox,
248                TGBS_RAISED, 1, FALSE);
249       }
250    }
251    XSetTSOrigin(mainDisplay, rasterGC, 0, 0);
252 }
253 
MakeCurPageTabVisible()254 void MakeCurPageTabVisible()
255 {
256    int last_tab_visible=(-1);
257 
258    if (pageLayoutMode == PAGE_TILE) return;
259 
260    if (!PageTabsVisible(&last_tab_visible)) {
261       MakePageTabsVisible(last_tab_visible);
262    }
263 }
264 
GotoPageNum(new_page_num)265 void GotoPageNum(new_page_num)
266    int new_page_num;
267 {
268    int i=1;
269    struct PageRec *page_ptr=NULL;
270 
271    if (new_page_num <= 0 || curPage == NULL) return;
272 
273    curPage->draw_orig_x = drawOrigX;
274    curPage->draw_orig_y = drawOrigY;
275    curPage->zoom_scale = zoomScale;
276    curPage->zoomed_in = zoomedIn;
277 
278    for (page_ptr=firstPage; page_ptr != NULL; page_ptr=page_ptr->next, i++) {
279       if (i == new_page_num) {
280          break;
281       }
282    }
283    curPageNum = new_page_num;
284    curPage = page_ptr;
285    topObj = curPage->top;
286    botObj = curPage->bot;
287    if (curPage->draw_orig_x != drawOrigX || curPage->draw_orig_y != drawOrigY ||
288          curPage->zoom_scale != zoomScale || curPage->zoomed_in != zoomedIn) {
289       if (!PRTGIF) AdjSplineVs();
290       if (!PRTGIF) AdjCaches();
291       curPage->draw_orig_x = drawOrigX;
292       curPage->draw_orig_y = drawOrigY;
293       curPage->zoom_scale = zoomScale;
294       curPage->zoomed_in = zoomedIn;
295    }
296    MakeCurPageTabVisible();
297 }
298 
299 static int curChoiceBeforePageChange=NOTHING;
300 
SetCurPage(page_number)301 void SetCurPage(page_number)
302    int page_number;
303 {
304    int need_to_redraw=TRUE;
305 
306    if (pageLayoutMode == PAGE_TILE) return;
307 
308    MakeQuiescent();
309    if (gstWBInfo.do_whiteboard) {
310       /* No warning!  Just clear the whiteboard! */
311       RecordWBClearAll();
312    } else {
313       PrepareToRecord(CMD_GOTO_PAGE, NULL, NULL, curPageNum);
314    }
315    GotoPageNum(page_number);
316    if (!gstWBInfo.do_whiteboard) {
317       RecordCmd(CMD_GOTO_PAGE, NULL, NULL, NULL, curPageNum);
318    }
319    if (resetOriginOnAdvancePage) {
320       int saved_x=0, saved_y=0, saved_zoom_scale=0, saved_zoomed_in=0;
321 
322       GetOrigin(&saved_x, &saved_y, &saved_zoom_scale, &saved_zoomed_in);
323       SetOrigin(0, 0, 0, FALSE);
324       if (ScrollToOrigin()) {
325          /* scrolled or un-zoomed */
326          need_to_redraw = FALSE;
327       }
328       SetOrigin(saved_x, saved_y, saved_zoom_scale, saved_zoomed_in);
329    }
330    if (need_to_redraw) {
331       ClearAndRedrawDrawWindow();
332    }
333    RedrawTitleWindow();
334    MakeCurPageTabVisible();
335    ShowPage();
336    SetCurChoice(curChoiceBeforePageChange);
337    if (gstWBInfo.do_whiteboard && topObj != NULL) {
338 #ifdef _TGIF_WB2_NO_DELAY_BUG
339       sleep(1);
340 #endif /* ~_TGIF_WB2_NO_DELAY_BUG */
341       /*
342        * In slideshow mode, SelAllObj() will *not* select anything!
343        * Since we really want the objects to be selected (because
344        *         we want to record them), we must set ignore_slideshow
345        *         to TRUE when we call SelAllObj().
346        */
347       SelAllObj(FALSE, TRUE);
348       PrepareToRecord(CMD_NEW, NULL, NULL, 0);
349       RecordCmd(CMD_NEW, NULL, topSel, botSel, numObjSelected);
350       RemoveAllSel();
351    }
352 }
353 
354 static
HandleClickInPageWindow(button_ev)355 void HandleClickInPageWindow(button_ev)
356    XButtonEvent *button_ev;
357 {
358    int i, index=(int)(button_ev->x / scrollBarW), total, offset;
359    struct PageRec *page_ptr;
360 
361    if (button_ev->x <= 0) {
362       index = 0;
363    } else {
364       index = (int)((button_ev->x-1) / scrollBarW);
365    }
366    switch (index) {
367    case SCROLL_LEFTEND:
368       pageWindowFirstIndex = 1;
369       RedrawPageWindow();
370       break;
371    case SCROLL_LEFT:
372       if (pageWindowFirstIndex > 1) {
373          if (button_ev->state & (ShiftMask | ControlMask)) {
374             pageWindowFirstIndex -= 10;
375             if (pageWindowFirstIndex < 1) pageWindowFirstIndex = 1;
376          } else {
377             pageWindowFirstIndex--;
378          }
379          RedrawPageWindow();
380       }
381       break;
382    case SCROLL_RIGHT:
383       if (pageWindowFirstIndex < lastPageNum) {
384          if (button_ev->state & (ShiftMask | ControlMask)) {
385             pageWindowFirstIndex += 10;
386             if (pageWindowFirstIndex > lastPageNum) {
387                pageWindowFirstIndex = lastPageNum;
388             }
389          } else {
390             pageWindowFirstIndex++;
391          }
392          RedrawPageWindow();
393       }
394       break;
395    case SCROLL_RIGHTEND:
396       total = pageWindowW-(scrollBarW<<2)-1;
397       pageWindowFirstIndex = lastPageNum;
398       for (i=lastPageNum, page_ptr=lastPage; page_ptr != NULL;
399             page_ptr=page_ptr->prev, i--) {
400          int w=DrawAHorizontalTab(i, page_ptr, 0, 0, FALSE, TRUE);
401 
402          total -= w;
403          if (total > 0) {
404             pageWindowFirstIndex = i;
405          } else {
406             break;
407          }
408       }
409       RedrawPageWindow();
410       break;
411    default:
412       offset = button_ev->x-(scrollBarW<<2)-1;
413       for (i=1, page_ptr=firstPage; page_ptr != NULL;
414             page_ptr=page_ptr->next, i++) {
415          if (i >= pageWindowFirstIndex) {
416             int w=DrawAHorizontalTab(i, page_ptr, 0, 0, FALSE, TRUE);
417 
418             if (w >= offset) {
419                /* int start=(((rulerFontWidth<<1)-7)>>1)+rulerFontWidth; */
420 
421                if (page_ptr != curPage) {
422                   curChoiceBeforePageChange = curChoice;
423                   SetCurPage(i);
424                }
425                break;
426             }
427             offset -= w;
428          }
429       }
430       break;
431    }
432 }
433 
434 static
HandleMotionInPageWindow(motion_ev)435 void HandleMotionInPageWindow(motion_ev)
436    XMotionEvent *motion_ev;
437 {
438    int i=0, index=0, offset=0, left_stid=0;
439    struct PageRec *page_ptr=NULL;
440 
441    if (motion_ev->x <= 0) {
442       index = 0;
443    } else {
444       index = (int)((motion_ev->x-1) / scrollBarW);
445    }
446    switch (index) {
447    case SCROLL_LEFTEND:
448    case SCROLL_LEFT:
449    case SCROLL_RIGHT:
450    case SCROLL_RIGHTEND:
451       if (motion_ev->state & (ShiftMask | ControlMask)) {
452          switch (index) {
453          case SCROLL_LEFTEND: left_stid = CSTID_SHIFT_ALL_TABS_RIGHT; break;
454          case SCROLL_LEFT: left_stid = CSTID_SHIFT_10_TABS_RIGHT; break;
455          case SCROLL_RIGHT: left_stid = CSTID_SHIFT_10_TABS_LEFT; break;
456          case SCROLL_RIGHTEND: left_stid = CSTID_SHIFT_ALL_TABS_LEFT; break;
457          }
458       } else {
459          switch (index) {
460          case SCROLL_LEFTEND: left_stid = CSTID_SHIFT_ALL_TABS_RIGHT; break;
461          case SCROLL_LEFT: left_stid = CSTID_SHIFT_TABS_RIGHT; break;
462          case SCROLL_RIGHT: left_stid = CSTID_SHIFT_TABS_LEFT; break;
463          case SCROLL_RIGHTEND: left_stid = CSTID_SHIFT_ALL_TABS_LEFT; break;
464          }
465       }
466       SetMouseStatus(TgLoadCachedString(left_stid),
467             TgLoadCachedString(CSTID_PAGE_MENU),
468             TgLoadCachedString(CSTID_PARANED_NONE));
469       break;
470    default:
471       offset = motion_ev->x-(scrollBarW<<2)-1;
472       for (i=1, page_ptr=firstPage; page_ptr != NULL;
473             page_ptr=page_ptr->next, i++) {
474          if (i >= pageWindowFirstIndex) {
475             int w=DrawAHorizontalTab(i, page_ptr, 0, 0, FALSE, TRUE);
476 
477             if (w >= offset) {
478                /* int start=(((rulerFontWidth<<1)-7)>>1)+rulerFontWidth; */
479 
480                if (page_ptr->name == NULL) {
481                   sprintf(gszMsgBox, TgLoadCachedString(CSTID_GOTO_GIVEN_PAGE),
482                         i);
483                } else {
484                   sprintf(gszMsgBox,
485                         TgLoadCachedString(CSTID_GOTO_GIVEN_PAGE_WITH_NAME), i,
486                         page_ptr->name);
487                }
488                SetStringStatus(gszMsgBox);
489                break;
490             }
491             offset -= w;
492          }
493       }
494       if (page_ptr == NULL) {
495          SetMouseStatus(TgLoadCachedString(CSTID_PARANED_NONE),
496                TgLoadCachedString(CSTID_PAGE_MENU),
497                TgLoadCachedString(CSTID_PARANED_NONE));
498       }
499       break;
500    }
501 }
502 
RedrawPageDummyWindow()503 void RedrawPageDummyWindow()
504 {
505    XClearWindow(mainDisplay, pageDummyWindow);
506    if (threeDLook) {
507       struct BBRec bbox;
508 
509       SetBBRec(&bbox, 0, 0, pageDummyWindowW, scrollBarW);
510       TgDrawThreeDButton(mainDisplay, pageDummyWindow, textMenuGC, &bbox,
511             TGBS_RAISED, 2, FALSE);
512    }
513 }
514 
PageDummyEventHandler(input)515 void PageDummyEventHandler(input)
516    XEvent *input;
517 {
518    if (input->type == Expose) {
519       XEvent ev;
520 
521       while (XCheckWindowEvent(mainDisplay,pageDummyWindow,ExposureMask,&ev)) ;
522       RedrawPageDummyWindow();
523    } else if (input->type == EnterNotify) {
524       SetMouseStatusToAllNone();
525    }
526 }
527 
528 static
FreePage(page_ptr)529 void FreePage(page_ptr)
530    struct PageRec *page_ptr;
531 {
532    topObj = page_ptr->top;
533    botObj = page_ptr->bot;
534    DelAllObj();
535    if (page_ptr->name != NULL) free(page_ptr->name);
536    if (page_ptr->page_file_name != NULL) free(page_ptr->page_file_name);
537    free(page_ptr);
538    topObj = NULL;
539    botObj = NULL;
540 }
541 
542 static
InitPageOnlyOnce()543 void InitPageOnlyOnce()
544 {
545    static int initialized=FALSE;
546 
547    if (initialized) return;
548    initialized = TRUE;
549 
550    if (PRTGIF) return;
551 }
552 
InitPage()553 void InitPage()
554    /* given lastPageNum, allocate enough pages */
555 {
556    int i;
557 
558    InitPageOnlyOnce();
559    while (firstPage != NULL) {
560       curPage = firstPage->next;
561       FreePage(firstPage);
562       firstPage = curPage;
563    }
564    firstPage = lastPage = curPage = NULL;
565    for (i=1; i <= lastPageNum; i++) {
566       curPage = (struct PageRec *)malloc(sizeof(struct PageRec));
567       if (curPage == NULL) FailAllocMessage();
568       memset(curPage, 0, sizeof(struct PageRec));
569       curPage->layer_on = TRUE;
570       curPage->name = NULL;
571       curPage->page_file_name = NULL;
572       curPage->top = curPage->bot = topObj = botObj = NULL;
573       curPage->next = NULL;
574       curPage->prev = lastPage;
575       curPage->draw_orig_x = drawOrigX;
576       curPage->draw_orig_y = drawOrigY;
577       curPage->zoom_scale = zoomScale;
578       curPage->zoomed_in = zoomedIn;
579       if (firstPage == NULL) {
580          firstPage = curPage;
581       } else {
582          lastPage->next = curPage;
583       }
584       lastPage = curPage;
585    }
586    curPageNum = (lastPageNum > 0 ? 1 : 0);
587    curPage = (lastPageNum > 0 ? firstPage : NULL);
588 }
589 
NextPage()590 void NextPage()
591 {
592    if (pageLayoutMode == PAGE_TILE) {
593       MsgBox(TgLoadString(STID_CANT_DO_NEXTPAGE_IN_TILED), TOOL_NAME, INFO_MB);
594       return;
595    }
596    if (curPageNum == lastPageNum) {
597       if (!inSlideShow) {
598          MsgBox(TgLoadString(STID_ALREADY_AT_LAST_PAGE), TOOL_NAME, INFO_MB);
599       }
600       return;
601    }
602    curChoiceBeforePageChange = curChoice;
603    SetCurPage(curPageNum+1);
604 }
605 
PrevPage()606 void PrevPage()
607 {
608    if (pageLayoutMode == PAGE_TILE) {
609       MsgBox(TgLoadString(STID_CANT_DO_PREVPAGE_IN_TILED), TOOL_NAME, INFO_MB);
610       return;
611    }
612    if (curPageNum == 1) {
613       if (!inSlideShow) {
614          MsgBox(TgLoadString(STID_ALREADY_AT_FIRST_PAGE), TOOL_NAME, INFO_MB);
615       }
616       return;
617    }
618    curChoiceBeforePageChange = curChoice;
619    SetCurPage(curPageNum-1);
620 }
621 
622 static int	leadingChars=(-1);
623 static char	formatStr[20];
624 static DspList	*pageNameDspPtr=NULL;
625 
626 static
PageNameListing(pn_entries)627 DspList *PageNameListing(pn_entries)
628    int *pn_entries;
629 {
630    int i;
631    DspList *dsp_ptr=NULL;
632    struct PageRec *page_ptr=NULL;
633 
634    for (leadingChars=1, i=lastPageNum; ;leadingChars++, i /= 10) {
635       if (i < 10) {
636          break;
637       }
638    }
639    sprintf(formatStr, "%%%1dd %%s", leadingChars++);
640    pageNameDspPtr = (DspList*)malloc(lastPageNum*sizeof(DspList));
641    if (pageNameDspPtr == NULL) FailAllocMessage();
642    memset(pageNameDspPtr, 0, lastPageNum*sizeof(DspList));
643    for (i=1, dsp_ptr=pageNameDspPtr, page_ptr=firstPage; i <= lastPageNum;
644          i++, dsp_ptr++, page_ptr=page_ptr->next) {
645       sprintf(gszMsgBox, formatStr, i,
646             ((page_ptr->name == NULL) ? "" : page_ptr->name));
647       UtilStrCpyN(dsp_ptr->itemstr, sizeof(dsp_ptr->itemstr), gszMsgBox);
648       dsp_ptr->directory = FALSE;
649       dsp_ptr->next = ((i == lastPageNum) ? NULL : &dsp_ptr[1]);
650    }
651    *pn_entries = lastPageNum;
652    return pageNameDspPtr;
653 }
654 
655 static
EditOrSelectPageNames(TopStr,Which,entries,num_entries)656 int EditOrSelectPageNames(TopStr, Which, entries, num_entries)
657    char *TopStr, **entries;
658    int Which; /* either PAGE_GOTO or PAGE_NAME */
659    int num_entries;
660 {
661    int marked_index=curPageNum-1, rc=INVALID;
662    char win_name[128];
663 
664    ResetNamesInfo();
665    NamesSetTitle(TopStr);
666    NamesAddButton(TgLoadCachedString(CSTID_OK), BUTTON_OK);
667    NamesAddButton(TgLoadCachedString(CSTID_CANCEL), BUTTON_CANCEL);
668    NamesSetEntries(NULL, entries, num_entries, NULL, TRUE, marked_index,
669          leadingChars);
670    if (Which==PAGE_NAME) {
671       /* ignore double-click and <CR> */
672       NamesSetDefaultBtnId(INVALID, INVALID);
673       sprintf(win_name, TgLoadString(STID_TOOL_NAME_PAGES), TOOL_NAME);
674       NamesSetStyle(NAMES_EDIT_NAME, NAMES_LOOP_ONCE);
675       if (Names(win_name, NULL, NULL, 0, NULL) == BUTTON_OK) {
676          rc = TRUE;
677       }
678    } else {
679       int selected_index=INVALID;
680 
681       sprintf(win_name, TgLoadString(STID_TOOL_GOTO_PAGE), TOOL_NAME);
682       NamesSetStyle(NAMES_COMPLEX_SELECT_NAME, NAMES_LOOP_ONCE);
683       if (Names(win_name, &selected_index, NULL, 0, NULL) != INVALID) {
684          return selected_index;
685       }
686    }
687    return rc;
688 }
689 
GotoPage(psz_page_num)690 void GotoPage(psz_page_num)
691    char *psz_page_num;
692 {
693    int index=(-1);
694 
695    if (pageLayoutMode == PAGE_TILE) {
696       MsgBox(TgLoadString(STID_CANT_DO_GOTOPAGE_IN_TILED), TOOL_NAME, INFO_MB);
697       return;
698    }
699    curChoiceBeforePageChange = curChoice;
700    MakeQuiescent();
701 
702    if (psz_page_num != NULL && strcmp(psz_page_num, "-1") != 0) {
703       index = atoi(psz_page_num);
704    } else {
705       int num_entries=0;
706       DspList *dsp_ptr;
707       char **entries=NULL;
708 
709       dsp_ptr = PageNameListing(&num_entries);
710       ignoreDirectoryFlag = TRUE;
711       entries = MakeNameDspItemArray(num_entries, dsp_ptr);
712       ignoreDirectoryFlag = FALSE;
713 
714       index = EditOrSelectPageNames(TgLoadString(STID_GOTO_PAGE_DOTS),
715             PAGE_GOTO, entries, num_entries);
716 
717       free(dsp_ptr);
718       free(*entries);
719       free(entries);
720 
721       if (index++ == (-1)) {
722          Msg(TgLoadString(STID_NO_PAGE_SELECTED));
723          return;
724       }
725    }
726    if (index < 1 || index > lastPageNum) {
727       sprintf(gszMsgBox, TgLoadString(STID_INVALID_GIVEN_PAGE_NUMBER), index);
728       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
729       return;
730    }
731    if (psz_page_num == NULL && index == curPageNum) {
732       sprintf(gszMsgBox, TgLoadString(STID_ALREADY_AT_GIVEN_PAGE), curPageNum);
733       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
734       return;
735    }
736    SetCurPage(index);
737 
738    sprintf(gszMsgBox, TgLoadString(STID_CUR_PAGE_IS_GIVEN_PAGE_NUM),
739          curPageNum);
740    Msg(gszMsgBox);
741 }
742 
NamePages()743 void NamePages()
744 {
745    int i, num_entries=0;
746    DspList *dsp_ptr;
747    char **entries=NULL;
748 
749    if (pageLayoutMode == PAGE_TILE) {
750       MsgBox(TgLoadString(STID_CANT_DO_NAMEPAGES_IN_TILED), TOOL_NAME, INFO_MB);
751       return;
752    }
753    MakeQuiescent();
754 
755    dsp_ptr = PageNameListing(&num_entries);
756    ignoreDirectoryFlag = TRUE;
757    entries = MakeNameDspItemArray(num_entries, dsp_ptr);
758    ignoreDirectoryFlag = FALSE;
759    if (EditOrSelectPageNames(TgLoadString(STID_EDIT_PAGE_NAMES_DOTS), PAGE_NAME,
760          entries, num_entries)) {
761       int modified=FALSE;
762       struct PageRec *page_ptr;
763 
764       for (page_ptr=firstPage, i=0; page_ptr!=NULL;
765             page_ptr=page_ptr->next, i++) {
766          int blank_str=BlankStr(&(entries[i])[leadingChars]);
767 
768          if (page_ptr->name == NULL) {
769             if (!blank_str) {
770                modified = TRUE;
771                page_ptr->name = UtilStrDup(&(entries[i])[leadingChars]);
772                if (page_ptr->name == NULL) FailAllocMessage();
773             }
774          } else {
775             if (blank_str || strcmp(page_ptr->name,
776                   &(entries[i])[leadingChars]) != 0) {
777                modified = TRUE;
778                UtilFree(page_ptr->name);
779                if (blank_str) {
780                   page_ptr->name = NULL;
781                } else {
782                   page_ptr->name = UtilStrDup(&(entries[i])[leadingChars]);
783                   if (page_ptr->name == NULL) FailAllocMessage();
784                }
785             }
786          }
787       }
788       if (modified) {
789          SetFileModified(TRUE);
790          RedrawTitleWindow();
791       }
792    }
793    free(dsp_ptr);
794    free(*entries);
795    free(entries);
796    Msg("");
797    SetCurChoice(curChoiceBeforeMakeQuiescent);
798 }
799 
800 static
PageFileNameListing(pn_entries)801 DspList *PageFileNameListing(pn_entries)
802    int *pn_entries;
803 {
804    int i;
805    DspList *dsp_ptr=NULL;
806    struct PageRec *page_ptr=NULL;
807 
808    for (leadingChars=1, i=lastPageNum; ;leadingChars++, i /= 10) {
809       if (i < 10) {
810          break;
811       }
812    }
813    sprintf(formatStr, "%%%1dd %%s", leadingChars++);
814    pageNameDspPtr = (DspList*)malloc(lastPageNum*sizeof(DspList));
815    if (pageNameDspPtr == NULL) FailAllocMessage();
816    memset(pageNameDspPtr, 0, lastPageNum*sizeof(DspList));
817    for (i=1, dsp_ptr=pageNameDspPtr, page_ptr=firstPage; i <= lastPageNum;
818          i++, dsp_ptr++, page_ptr=page_ptr->next) {
819       char *psz=NULL;
820 
821       sprintf(gszMsgBox, formatStr, i,
822             ((page_ptr->page_file_name == NULL) ? "" :
823             page_ptr->page_file_name));
824       UtilTrimBlanks(&gszMsgBox[leadingChars]);
825       if ((psz=strchr(&gszMsgBox[leadingChars], ' ')) != NULL) *psz = '\0';
826       UtilStrCpyN(dsp_ptr->itemstr, sizeof(dsp_ptr->itemstr), gszMsgBox);
827       dsp_ptr->directory = FALSE;
828       dsp_ptr->next = ((i == lastPageNum) ? NULL : &dsp_ptr[1]);
829    }
830    *pn_entries = lastPageNum;
831    return pageNameDspPtr;
832 }
833 
EditPageFileNames()834 void EditPageFileNames()
835 {
836    int i, num_entries=0;
837    DspList *dsp_ptr=NULL;
838    char **entries=NULL;
839 
840    if (pageLayoutMode == PAGE_TILE) {
841       MsgBox(TgLoadString(STID_CANT_EDITPAGEFNAME_IN_TILED), TOOL_NAME,
842             INFO_MB);
843       return;
844    }
845    MakeQuiescent();
846 
847    dsp_ptr = PageFileNameListing(&num_entries);
848    ignoreDirectoryFlag = TRUE;
849    entries = MakeNameDspItemArray(num_entries, dsp_ptr);
850    ignoreDirectoryFlag = FALSE;
851    if (EditOrSelectPageNames(TgLoadString(STID_EDIT_PAGE_FILE_NAMES_DOTS),
852          PAGE_NAME, entries, num_entries)) {
853       int modified=FALSE;
854       struct PageRec *page_ptr=NULL;
855       char *psz=NULL;
856 
857       for (page_ptr=firstPage, i=0; page_ptr!=NULL;
858             page_ptr=page_ptr->next, i++) {
859          int blank_str=BlankStr(&(entries[i])[leadingChars]);
860 
861          if (page_ptr->page_file_name == NULL) {
862             if (!blank_str) {
863                modified = TRUE;
864                page_ptr->page_file_name =
865                      UtilStrDup(&(entries[i])[leadingChars]);
866                if (page_ptr->page_file_name == NULL) FailAllocMessage();
867                if ((psz=strchr(page_ptr->page_file_name, ' ')) != NULL) {
868                   char truncated_name[MAXSTRING];
869 
870                   *psz = *truncated_name = '\0';
871                   UtilStrCpyN(truncated_name, sizeof(truncated_name),
872                         page_ptr->page_file_name);
873                   *psz = ' ';
874                   sprintf(gszMsgBox,
875                         TgLoadString(STID_PAGE_FNAME_NO_SPACE_TRUNC),
876                         page_ptr->page_file_name, truncated_name);
877                   MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
878                   strcpy(page_ptr->page_file_name, truncated_name);
879                }
880             }
881          } else {
882             if (blank_str || strcmp(page_ptr->page_file_name,
883                   &(entries[i])[leadingChars]) != 0) {
884                modified = TRUE;
885                UtilFree(page_ptr->page_file_name);
886                if (blank_str) {
887                   page_ptr->page_file_name = NULL;
888                } else {
889                   page_ptr->page_file_name =
890                         UtilStrDup(&(entries[i])[leadingChars]);
891                   if (page_ptr->page_file_name == NULL) FailAllocMessage();
892                   if ((psz=strchr(page_ptr->page_file_name, ' ')) != NULL) {
893                      char truncated_name[MAXSTRING];
894 
895                      *psz = *truncated_name = '\0';
896                      UtilStrCpyN(truncated_name, sizeof(truncated_name),
897                            page_ptr->page_file_name);
898                      *psz = ' ';
899                      sprintf(gszMsgBox,
900                            TgLoadString(STID_PAGE_FNAME_NO_SPACE_TRUNC),
901                            page_ptr->page_file_name, truncated_name);
902                      MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
903                      strcpy(page_ptr->page_file_name, truncated_name);
904                   }
905                }
906             }
907          }
908       }
909       if (modified) {
910          SetFileModified(TRUE);
911          RedrawTitleWindow();
912       }
913    }
914    free(dsp_ptr);
915    free(*entries);
916    free(entries);
917    Msg("");
918    SetCurChoice(curChoiceBeforeMakeQuiescent);
919 }
920 
OkToFlushUndoBuffer(msg_prefix)921 int OkToFlushUndoBuffer(msg_prefix)
922    char *msg_prefix;
923 {
924    if (firstCmd != NULL) {
925       int len=strlen(msg_prefix), rc=0;
926       char *buf=(char*)malloc((len+MAXSTRING)*sizeof(char));
927 
928       if (buf == NULL) FailAllocMessage();
929       XBell(mainDisplay, 0);
930       sprintf(buf, "%s\n\n%s",
931             msg_prefix, TgLoadString(STID_OK_TO_FLUSH_UNDO_AND_PROCEED));
932       rc = MsgBox(buf, TOOL_NAME, YNC_MB);
933       UtilFree(buf);
934       if (rc == MB_ID_YES) {
935          CleanUpCmds();
936          return TRUE;
937       }
938       return FALSE;
939    }
940    return TRUE;
941 }
942 
943 #define BEFORE_CUR_PAGE 0
944 #define AFTER_CUR_PAGE 1
945 
946 typedef struct tagAddPageCopyAllInfo {
947    struct ObjRec *top_obj;
948    struct ObjRec *bot_obj;
949 } AddPageCopyAllInfo;
950 
951 static
AddPage(AfterCurPage,papcai)952 void AddPage(AfterCurPage, papcai)
953    int AfterCurPage;
954    AddPageCopyAllInfo *papcai;
955 {
956    int n;
957    struct PageRec *page_ptr=NULL;
958    struct AttrRec *attr_ptr=NULL;
959 
960    if (pageLayoutMode == PAGE_TILE) {
961       MsgBox(TgLoadString(STID_CANT_DO_ADDPAGE_IN_TILED), TOOL_NAME, INFO_MB);
962       return;
963    }
964    if (firstCmd != NULL) {
965       sprintf(gszMsgBox, TgLoadString(AfterCurPage ?
966             STID_ADD_PAGE_AFTER_GIVEN_FLUSH : STID_ADD_PAGE_BEFORE_GIVEN_FLUSH),
967             curPageNum);
968       if (!OkToFlushUndoBuffer(gszMsgBox)) {
969          return;
970       }
971       CleanUpCmds();
972    }
973    n = (AfterCurPage ? curPageNum : curPageNum-1);
974 
975    MakeQuiescent();
976 
977    for (curPageNum=1, curPage=firstPage; curPageNum <= n; curPageNum++) {
978       curPage=curPage->next;
979    }
980    page_ptr = (struct PageRec *)malloc(sizeof(struct PageRec));
981    if (page_ptr == NULL) FailAllocMessage();
982    memset(page_ptr, 0, sizeof(struct PageRec));
983    page_ptr->layer_on = TRUE;
984    page_ptr->top = page_ptr->bot = topObj = botObj = NULL;
985    page_ptr->next = curPage;
986    page_ptr->name = NULL;
987    page_ptr->page_file_name = NULL;
988    page_ptr->draw_orig_x = drawOrigX;
989    page_ptr->draw_orig_y = drawOrigY;
990    page_ptr->zoom_scale = zoomScale;
991    page_ptr->zoomed_in = zoomedIn;
992    if (curPage == NULL) {
993       page_ptr->prev = lastPage;
994       lastPage->next = page_ptr;
995       lastPage = page_ptr;
996    } else {
997       page_ptr->prev = curPage->prev;
998       if (curPage->prev == NULL) {
999          firstPage = page_ptr;
1000       } else {
1001          curPage->prev->next = page_ptr;
1002       }
1003       curPage->prev = page_ptr;
1004    }
1005    curPage = page_ptr;
1006    lastPageNum++;
1007    topObj = curPage->top;
1008    botObj = curPage->bot;
1009 
1010    if (papcai != NULL) {
1011       struct ObjRec *obj_ptr=NULL;
1012       struct SelRec *top_sel=NULL, *bot_sel=NULL;
1013 
1014       for (obj_ptr=papcai->bot_obj; obj_ptr != NULL; obj_ptr=obj_ptr->prev) {
1015          obj_ptr->tmp_parent = NULL;
1016          AddObjIntoSel(obj_ptr, NULL, topSel, &topSel, &botSel);
1017       }
1018       DupTheseObjects(topSel, botSel, &top_sel, &bot_sel);
1019       RemoveAllSel();
1020       curPage->top = topObj = top_sel->obj;
1021       curPage->bot = botObj = bot_sel->obj;
1022       topSel = top_sel;
1023       botSel = bot_sel;
1024       RemoveAllSel();
1025    }
1026    ClearAndRedrawDrawWindow();
1027    RedrawTitleWindow();
1028    SetFileModified(TRUE);
1029    MakeCurPageTabVisible();
1030    ShowPage();
1031    if (papcai == NULL && !cmdLineMerge) {
1032       if ((attr_ptr=FindAttrWithName(tgifObj, "template=", NULL)) != NULL) {
1033          char file_name[MAXPATHLENGTH];
1034 
1035          if (*attr_ptr->attr_value.s == DIR_SEP) {
1036             UtilStrCpyN(file_name, sizeof(file_name), attr_ptr->attr_value.s);
1037          } else {
1038             sprintf(file_name, "%s%c%s", bootDir, DIR_SEP,
1039                attr_ptr->attr_value.s);
1040          }
1041          importingFile = TRUE;
1042          if (ImportGivenFile(file_name, TRUE, TRUE)) {
1043             sprintf(gszMsgBox, TgLoadString(STID_NAMED_TEMPLATE_LOADED),
1044                   attr_ptr->attr_value.s);
1045             Msg(gszMsgBox);
1046          } else {
1047             sprintf(gszMsgBox, TgLoadString(STID_PROB_LOADING_NAMED_TEMPLATE),
1048                   file_name);
1049             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1050          }
1051          importingFile = FALSE;
1052       }
1053    }
1054    sprintf(gszMsgBox, TgLoadString(STID_GIVEN_PAGE_NUM_ADDED), curPageNum);
1055    Msg(gszMsgBox);
1056    SetCurChoice(curChoiceBeforeMakeQuiescent);
1057 }
1058 
AddPageBefore()1059 void AddPageBefore()
1060 {
1061    if (gstWBInfo.do_whiteboard) {
1062       MsgBox(TgLoadString(STID_ADDPAGEBEFORE_IN_WB), TOOL_NAME, INFO_MB);
1063       return;
1064    }
1065    AddPage(BEFORE_CUR_PAGE, NULL);
1066 }
1067 
AddPageAfter()1068 void AddPageAfter()
1069 {
1070    if (gstWBInfo.do_whiteboard) {
1071       MsgBox(TgLoadString(STID_ADDPAGEAFTER_IN_WB), TOOL_NAME, INFO_MB);
1072       return;
1073    }
1074    AddPage(AFTER_CUR_PAGE, NULL);
1075 }
1076 
AddPageBeforeCopyAll()1077 void AddPageBeforeCopyAll()
1078 {
1079    AddPageCopyAllInfo apcai;
1080 
1081    if (gstWBInfo.do_whiteboard) {
1082       MsgBox(TgLoadString(STID_ADDPAGEBEFORE_IN_WB), TOOL_NAME, INFO_MB);
1083       return;
1084    }
1085    memset(&apcai, 0, sizeof(AddPageCopyAllInfo));
1086    apcai.top_obj = topObj;
1087    apcai.bot_obj = botObj;
1088 
1089    AddPage(BEFORE_CUR_PAGE, &apcai);
1090 }
1091 
AddPageAfterCopyAll()1092 void AddPageAfterCopyAll()
1093 {
1094    AddPageCopyAllInfo apcai;
1095 
1096    if (gstWBInfo.do_whiteboard) {
1097       MsgBox(TgLoadString(STID_ADDPAGEAFTER_IN_WB), TOOL_NAME, INFO_MB);
1098       return;
1099    }
1100    memset(&apcai, 0, sizeof(AddPageCopyAllInfo));
1101    apcai.top_obj = topObj;
1102    apcai.bot_obj = botObj;
1103 
1104    AddPage(AFTER_CUR_PAGE, &apcai);
1105 }
1106 
DeleteCurPage()1107 void DeleteCurPage()
1108 {
1109    int n;
1110    struct PageRec *page_ptr=NULL;
1111 
1112    if (pageLayoutMode == PAGE_TILE) {
1113       MsgBox(TgLoadString(STID_CANT_DO_DELETEPAGE_IN_TILED), TOOL_NAME,
1114             INFO_MB);
1115       return;
1116    }
1117    if (lastPageNum == 1) {
1118       MsgBox(TgLoadString(STID_CANT_DEL_ONLY_PAGE_IN_STACKED), TOOL_NAME,
1119             INFO_MB);
1120       return;
1121    }
1122    if (firstCmd != NULL || topObj != NULL) {
1123       sprintf(gszMsgBox, TgLoadString(STID_DELETE_GIVEN_PAGE_CAUSE_FLUSH),
1124             curPageNum);
1125       if (!OkToFlushUndoBuffer(gszMsgBox)) {
1126          return;
1127       }
1128       CleanUpCmds();
1129    }
1130    n = curPageNum;
1131    SetFileModified(TRUE);
1132 
1133    MakeQuiescent();
1134 
1135    if (curPage == firstPage) {
1136       page_ptr = firstPage = curPage->next;
1137       firstPage->prev = NULL;
1138    } else if (curPage == lastPage) {
1139       page_ptr = lastPage = curPage->prev;
1140       lastPage->next = NULL;
1141       curPageNum--;
1142    } else {
1143       curPage->next->prev = curPage->prev;
1144       curPage->prev->next = curPage->next;
1145       page_ptr = curPage->next;
1146    }
1147    FreePage(curPage);
1148    curPage = page_ptr;
1149    lastPageNum--;
1150    topObj = curPage->top;
1151    botObj = curPage->bot;
1152 
1153    ClearAndRedrawDrawWindow();
1154    RedrawTitleWindow();
1155    MakeCurPageTabVisible();
1156    ShowPage();
1157 
1158    sprintf(gszMsgBox, TgLoadString(STID_GIVEN_PAGE_NUM_DELETED), n);
1159    Msg(gszMsgBox);
1160    SetCurChoice(curChoiceBeforeMakeQuiescent);
1161 }
1162 
TogglePageLineShown()1163 void TogglePageLineShown()
1164 {
1165    if (pageLayoutMode == PAGE_STACK) {
1166       MsgBox(TgLoadString(STID_CANT_TPLS_IN_STACKED), TOOL_NAME, INFO_MB);
1167       return;
1168    }
1169    pageLineShownInTileMode = !pageLineShownInTileMode;
1170    ClearAndRedrawDrawWindow();
1171 }
1172 
1173 static
JustSpecifyDrawingSize()1174 int JustSpecifyDrawingSize()
1175 {
1176    char spec[MAXSTRING+1], *c_ptr, *part_1;
1177    int cols=0, rows=0;
1178 
1179    *spec = '\0';
1180    if (Dialog(TgLoadString(STID_ENTER_DRAW_SIZE_SPEC_WH),
1181          TgLoadCachedString(CSTID_DLG_ACCEPT_CANCEL), spec) == INVALID) {
1182       return FALSE;
1183    }
1184    if ((part_1=strtok(spec, " ,xX")) == NULL) return FALSE;
1185    if ((c_ptr=strtok(NULL, " ,xX")) == NULL) {
1186       MsgBox(TgLoadString(STID_BAD_DRAW_SIZE_SPEC_WH), TOOL_NAME, INFO_MB);
1187       return FALSE;
1188    } else {
1189       cols = atoi(part_1);
1190       rows = atoi(c_ptr);
1191    }
1192    if (cols > 0 && rows > 0 && (cols*rows >= lastPageNum)) {
1193       if (cols*rows < lastPageNum) {
1194          sprintf(gszMsgBox, TgLoadString(STID_BAD_DRAW_SIZE_SPEC_W_TIMES_H),
1195                lastPageNum);
1196          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1197       } else {
1198          paperCol = cols;
1199          paperRow = rows;
1200          return TRUE;
1201       }
1202    } else if (cols == 0 || rows == 0) {
1203       MsgBox(TgLoadString(STID_BAD_DRAW_SIZE_SPEC_WH), TOOL_NAME, INFO_MB);
1204       return FALSE;
1205    } else if (cols*rows < lastPageNum) {
1206       sprintf(gszMsgBox, TgLoadString(STID_BAD_DRAW_SIZE_SPEC_W_TIMES_H),
1207             lastPageNum);
1208       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1209    } else {
1210       MsgBox(TgLoadString(STID_INVALID_DRAW_SIZE_SPEC), TOOL_NAME, INFO_MB);
1211    }
1212    return FALSE;
1213 }
1214 
SpecifyDrawingSize()1215 void SpecifyDrawingSize()
1216 {
1217    if (pageLayoutMode != PAGE_TILE) {
1218       MsgBox(TgLoadString(STID_CANT_DO_SPECDRAWSIZE_IN_TILED), TOOL_NAME,
1219             INFO_MB);
1220       return;
1221    }
1222    if (JustSpecifyDrawingSize()) {
1223       UpdPageStyle(pageStyle);
1224       RedrawScrollBars();
1225       UpdDrawWinBBox();
1226       AdjSplineVs();
1227       ClearAndRedrawDrawWindow();
1228 
1229       ShowPage();
1230    }
1231 }
1232 
PrintOnePage()1233 void PrintOnePage()
1234 {
1235    int x=0, y=0;
1236 
1237    switch (pageLayoutMode) {
1238    case PAGE_TILE:
1239       switch (whereToPrint) {
1240       case XBM_FILE:
1241       case TEXT_FILE:
1242       case NETLIST_FILE:
1243       case GIF_FILE:
1244       case HTML_FILE:
1245       case PNG_FILE:
1246       case JPEG_FILE:
1247       case PPM_FILE:
1248          sprintf(gszMsgBox, TgLoadString(STID_CANT_PRINTONEPAGE_IN_FORMAT),
1249                GetExportName(whereToPrint, EXPORT_THIS));
1250          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1251          return;
1252       default: break;
1253       }
1254       MakeQuiescent();
1255 
1256       sprintf(gszMsgBox, "    %s",
1257             TgLoadString(STID_OTHER_BTN_CANCEL_PRINTONEPAGE));
1258       TwoLineMsg(TgLoadString(STID_BTN1_SEL_PAGE_TO_PRINT), gszMsgBox);
1259       SetMouseStatus(TgLoadString(STID_SELECT_A_PAGE_TO_PRINT),
1260             TgLoadCachedString(CSTID_CANCEL), TgLoadCachedString(CSTID_CANCEL));
1261       if (PickAPoint(&x, &y, handCursor) != Button1) {
1262          Msg(TgLoadString(STID_OPERATION_CANCEL_BY_USER));
1263       } else if (x>=0 && x<ZOOMED_SIZE(drawWinW) && y>=0 &&
1264             y<ZOOMED_SIZE(drawWinH)) {
1265          int abs_x=ABS_X(x), abs_y=ABS_Y(y);
1266          int col=(int)(abs_x / onePageWidth);
1267          int row=(int)(abs_y / onePageHeight);
1268 
1269          if (col >= paperCol || row >= paperRow) {
1270             MsgBox(TgLoadString(STID_MUST_SEL_A_PT_ON_THE_PAPER), TOOL_NAME,
1271                   INFO_MB);
1272          } else {
1273             DumpOnePageInTileMode(row, col);
1274          }
1275       } else {
1276          sprintf(gszMsgBox, TgLoadString(STID_MUST_SEL_A_PT_IN_TOOL_WIN),
1277                TOOL_NAME);
1278          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1279       }
1280       SetCurChoice(curChoiceBeforeMakeQuiescent);
1281       break;
1282    case PAGE_STACK:
1283       MakeQuiescent();
1284 
1285       DumpOnePageInStackMode();
1286       SetCurChoice(curChoiceBeforeMakeQuiescent);
1287       break;
1288    }
1289 }
1290 
GetDimension(Spec,nNonPosReturnOK,pnNumPixels)1291 int GetDimension(Spec, nNonPosReturnOK, pnNumPixels)
1292    char *Spec;
1293    int nNonPosReturnOK, *pnNumPixels;
1294 {
1295    char *c_ptr;
1296    double val;
1297 
1298    /* do not translate -- program constants */
1299    if ((c_ptr=strstr(Spec, "in")) != NULL ||
1300          (c_ptr=strstr(Spec, "In")) != NULL ||
1301          (c_ptr=strstr(Spec, "IN")) != NULL) {
1302       *c_ptr = '\0';
1303       val = atof(Spec) * ((double)PIX_PER_INCH);
1304       *pnNumPixels = round(val);
1305       if (!nNonPosReturnOK && *pnNumPixels <= 0) return FALSE;
1306    } else if ((c_ptr=strstr(Spec, "cm")) != NULL ||
1307          (c_ptr=strstr(Spec, "Cm")) != NULL ||
1308          (c_ptr=strstr(Spec, "CM")) != NULL) {
1309       *c_ptr = '\0';
1310       val = atof(Spec) * ((double)ONE_CM);
1311       *pnNumPixels = round(val);
1312       if (!nNonPosReturnOK && *pnNumPixels <= 0) return FALSE;
1313    } else if (sscanf(Spec, "%d", pnNumPixels) != 1) {
1314       return FALSE;
1315    } else {
1316       if (!nNonPosReturnOK && *pnNumPixels <= 0) return FALSE;
1317    }
1318    return TRUE;
1319 }
1320 
GetDimensionInDouble(Spec,nNonPosReturnOK,pd_num_pixels)1321 int GetDimensionInDouble(Spec, nNonPosReturnOK, pd_num_pixels)
1322    char *Spec;
1323    int nNonPosReturnOK;
1324    double *pd_num_pixels;
1325 {
1326    char *c_ptr=NULL;
1327    double dval=(double)0;
1328 
1329    /* do not translate -- program constants */
1330    if ((c_ptr=strstr(Spec, "in")) != NULL ||
1331          (c_ptr=strstr(Spec, "In")) != NULL ||
1332          (c_ptr=strstr(Spec, "IN")) != NULL) {
1333       *c_ptr = '\0';
1334       dval = atof(Spec) * ((double)PIX_PER_INCH);
1335       *pd_num_pixels = dval;
1336       if (!nNonPosReturnOK && dval < (double)0) return FALSE;
1337    } else if ((c_ptr=strstr(Spec, "cm")) != NULL ||
1338          (c_ptr=strstr(Spec, "Cm")) != NULL ||
1339          (c_ptr=strstr(Spec, "CM")) != NULL) {
1340       *c_ptr = '\0';
1341       dval = atof(Spec) * ((double)ONE_CM);
1342       *pd_num_pixels = dval;
1343       if (!nNonPosReturnOK && dval < (double)0) return FALSE;
1344    } else if (sscanf(Spec, "%lf", pd_num_pixels) != 1) {
1345       return FALSE;
1346    } else {
1347       if (!nNonPosReturnOK && dval < (double)0) return FALSE;
1348    }
1349    return TRUE;
1350 }
1351 
SetPaperSize(Spec)1352 int SetPaperSize(Spec)
1353    char *Spec;
1354 {
1355    int ok=TRUE;
1356    char *c_ptr;
1357 
1358    UtilTrimBlanks(Spec);
1359    /* do not translate -- program constants */
1360    if (UtilStrICmp(Spec, "letter") == 0) {
1361       onePageWidth = (85*PIX_PER_INCH)/10;
1362       onePageHeight = 11*PIX_PER_INCH;
1363       SetPSPageWidthHeight();
1364    } else if (UtilStrICmp(Spec, "legal") == 0) {
1365       onePageWidth = (85*PIX_PER_INCH)/10;
1366       onePageHeight = 14*PIX_PER_INCH;
1367       SetPSPageWidthHeight();
1368    } else if (UtilStrICmp(Spec, "a4") == 0) {
1369       onePageWidth = (825*PIX_PER_INCH)/100;
1370       onePageHeight = (117*PIX_PER_INCH)/10;
1371       SetPSPageWidthHeight();
1372    } else if ((c_ptr=strstr(Spec, " x ")) == NULL &&
1373          (c_ptr=strstr(Spec, " X ")) == NULL) {
1374       ok = FALSE;
1375    } else {
1376       int w_in_pixel, h_in_pixel;
1377 
1378       *c_ptr = '\0';
1379       UtilTrimBlanks(&c_ptr[3]);
1380       if (GetDimension(Spec, FALSE, &w_in_pixel) &&
1381             GetDimension(&c_ptr[3], FALSE, &h_in_pixel)) {
1382          onePageWidth = w_in_pixel;
1383          onePageHeight = h_in_pixel;
1384          SetPSPageWidthHeight();
1385       } else {
1386          ok = FALSE;
1387       }
1388    }
1389    if (ok) {
1390       if (mainWindow != None) {
1391          sprintf(gszMsgBox,
1392                TgLoadString(STID_NEW_PAPER_SIZE_IS_GIVEN),
1393                (float)(((float)onePageWidth)/((float)PIX_PER_INCH)),
1394                (float)(((float)onePageHeight)/((float)PIX_PER_INCH)),
1395                (float)(((float)onePageWidth)/((float)ONE_CM)),
1396                (float)(((float)onePageHeight)/((float)ONE_CM)));
1397          Msg(gszMsgBox);
1398       }
1399    } else {
1400       if (mainWindow == None) {
1401          sprintf(gszMsgBox, TgLoadString(STID_INVALID_XDEF),
1402                TOOL_NAME, "InitialPaperSize", Spec);
1403          fprintf(stderr, "%s\n", gszMsgBox);
1404       } else {
1405          sprintf(gszMsgBox, TgLoadString(STID_INVALID_GIVEN_PAPER_SIZE_SPEC),
1406                Spec);
1407          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1408       }
1409    }
1410    return ok;
1411 }
1412 
1413 static
GetCurPaperSizeSpec(buf)1414 void GetCurPaperSizeSpec(buf)
1415    char *buf;
1416 {
1417    char w_str[MAXSTRING], h_str[MAXSTRING];
1418    float w=((float)onePageWidth)*printMag/((float)100.0);
1419    float h=((float)onePageHeight)*printMag/((float)100.0);
1420    float unit=(float)0.0, w_val=(float)0.0, h_val=(float)0.0;
1421 
1422    switch (gridSystem) {
1423    case ENGLISH_GRID:
1424       unit = (float)PIX_PER_INCH;
1425 
1426       switch (pageStyle) {
1427       case PORTRAIT: w_val = w/unit; h_val = h/unit; break;
1428       case LANDSCAPE: w_val = h/unit; h_val = w/unit; break;
1429       }
1430       FormatFloat(&w_val, w_str);
1431       FormatFloat(&h_val, h_str);
1432       /* do not translate -- program constants */
1433       sprintf(buf, "%s in x %s in", w_str, h_str);
1434       break;
1435    case METRIC_GRID:
1436       unit = (float)ONE_CM;
1437 
1438       switch (pageStyle) {
1439       case PORTRAIT: w_val = w/unit; h_val = h/unit; break;
1440       case LANDSCAPE: w_val = h/unit; h_val = w/unit; break;
1441       }
1442       FormatFloat(&w_val, w_str);
1443       FormatFloat(&h_val, h_str);
1444       /* do not translate -- program constants */
1445       sprintf(buf, "%s cm x %s cm", w_str, h_str);
1446       break;
1447    }
1448 }
1449 
SpecifyPaperSize()1450 void SpecifyPaperSize()
1451 {
1452    char buf[MAXSTRING+1], spec[MAXSTRING+1];
1453 
1454    GetCurPaperSizeSpec(gszMsgBox);
1455    sprintf(buf, TgLoadString(STID_CUR_PAPER_SIZE_IS_GIVEN), gszMsgBox);
1456    *spec = '\0';
1457    if (Dialog(TgLoadString(STID_ENTER_PAPER_SIZE_WH), buf, spec) == INVALID) {
1458       return;
1459    }
1460    MakeQuiescent();
1461 
1462    if (SetPaperSize(spec)) {
1463       UpdPageStyle(pageStyle);
1464       SetFileModified(TRUE);
1465       ClearAndRedrawDrawWindow();
1466    }
1467    SetCurChoice(curChoiceBeforeMakeQuiescent);
1468 }
1469 
FreePageSpec(pspi)1470 void FreePageSpec(pspi)
1471    SpecifyPagesInfo *pspi;
1472 {
1473    if (pspi->page_specified != NULL) free(pspi->page_specified);
1474 }
1475 
ParsePagesSpec(spec,pspi)1476 int ParsePagesSpec(spec, pspi)
1477    char *spec;
1478    SpecifyPagesInfo *pspi;
1479    /* if return TRUE, must call FreePageSpec(pspi) */
1480 {
1481    char *dup_spec=NULL, *c_ptr=NULL;
1482    int i, ok=TRUE;
1483 
1484    UtilTrimBlanks(spec);
1485    if (*spec == '\0') return FALSE;
1486    if ((pspi->page_specified=(int*)malloc(lastPageNum*sizeof(int))) == NULL) {
1487       FailAllocMessage();
1488       return FALSE;
1489    }
1490    if ((dup_spec=UtilStrDup(spec)) == NULL) {
1491       free(pspi->page_specified);
1492       FailAllocMessage();
1493       return FALSE;
1494    }
1495    if (strcmp(dup_spec, "*") == 0) {
1496       for (i=0; i < lastPageNum; i++) pspi->page_specified[i] = TRUE;
1497       pspi->num_pages_specified = lastPageNum;
1498    } else {
1499       for (i=0; i < lastPageNum; i++) pspi->page_specified[i] = FALSE;
1500       if (*dup_spec == '*') *dup_spec = ' ';
1501       for (c_ptr=strtok(dup_spec, " ,\t"); ok && c_ptr != NULL;
1502             c_ptr=strtok(NULL, " ,\t")) {
1503          char *dash_ptr=strchr(c_ptr, '-');
1504 
1505          if (dash_ptr == NULL) {
1506             int page_num=atoi(c_ptr);
1507 
1508             if (page_num > 0 && page_num <= lastPageNum) {
1509                if (!pspi->page_specified[page_num-1]) {
1510                   pspi->num_pages_specified++;
1511                }
1512                pspi->page_specified[page_num-1] = TRUE;
1513             } else {
1514                sprintf(gszMsgBox,
1515                      TgLoadString(STID_GIVEN_PAGE_NUM_IS_OUT_OF_RNG), page_num);
1516                MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1517                ok = FALSE;
1518             }
1519          } else {
1520             int start_page_num, end_page_num;
1521 
1522             *dash_ptr = '\0';
1523             start_page_num = atoi(c_ptr);
1524             end_page_num = atoi(&dash_ptr[1]);
1525             *dash_ptr = '-';
1526             if (start_page_num <= 0 || start_page_num > lastPageNum) {
1527                sprintf(gszMsgBox,
1528                      TgLoadString(STID_GIVEN_PAGE_NUM_IS_OUT_OF_RNG),
1529                      start_page_num);
1530                MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1531                ok = FALSE;
1532             } else if (end_page_num <= 0 || end_page_num > lastPageNum) {
1533                sprintf(gszMsgBox,
1534                      TgLoadString(STID_GIVEN_PAGE_NUM_IS_OUT_OF_RNG),
1535                      end_page_num);
1536                MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1537                ok = FALSE;
1538             } else if (start_page_num > end_page_num) {
1539                sprintf(gszMsgBox,
1540                      TgLoadString(STID_MALFORMED_SPECIFICATION_STR), spec);
1541                MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1542                ok = FALSE;
1543             } else {
1544                for (i=start_page_num; i <= end_page_num; i++) {
1545                   if (!pspi->page_specified[i-1]) pspi->num_pages_specified++;
1546                   pspi->page_specified[i-1] = TRUE;
1547                }
1548             }
1549          }
1550       }
1551    }
1552    free(dup_spec);
1553 
1554    if (!ok) FreePageSpec(pspi);
1555    return ok;
1556 }
1557 
DeletePages()1558 void DeletePages()
1559 {
1560    char spec[MAXSTRING+1];
1561    SpecifyPagesInfo spi;
1562 
1563    if (pageLayoutMode == PAGE_TILE) {
1564       MsgBox(TgLoadString(STID_CANT_DO_DELETEPAGES_IN_TILED), TOOL_NAME,
1565             INFO_MB);
1566       return;
1567    }
1568    if (lastPageNum == 1) {
1569       MsgBox(TgLoadString(STID_CANT_DEL_ONLY_PAGE_IN_STACKED), TOOL_NAME,
1570             INFO_MB);
1571       return;
1572    }
1573    *spec = '\0';
1574    Dialog(TgLoadString(STID_SPECIFY_PAGES_TO_DEL_EX), NULL, spec);
1575    UtilTrimBlanks(spec);
1576    if (*spec == '\0') return;
1577 
1578    memset(&spi, 0, sizeof(SpecifyPagesInfo));
1579    if (!ParsePagesSpec(spec, &spi)) return;
1580 
1581    MakeQuiescent();
1582 
1583    if (spi.num_pages_specified == lastPageNum) {
1584       MsgBox(TgLoadString(STID_CANT_DEL_ALL_PAGES), TOOL_NAME, INFO_MB);
1585    } else if (spi.num_pages_specified > 0) {
1586       sprintf(gszMsgBox, TgLoadString(spi.num_pages_specified > 1 ?
1587             STID_DELETE_A_PAGE_CAUSE_FLUSH :
1588             STID_DELETE_PAGES_PAGE_CAUSE_FLUSH));
1589       if (firstCmd == NULL || OkToFlushUndoBuffer(gszMsgBox)) {
1590          struct PageRec *page_ptr;
1591          int page_num;
1592 
1593          for (page_num=lastPageNum; page_num > 0; page_num--) {
1594             if (spi.page_specified[page_num-1]) {
1595                GotoPageNum(page_num);
1596                if (curPage == firstPage) {
1597                   page_ptr = firstPage = curPage->next;
1598                   firstPage->prev = NULL;
1599                } else if (curPage == lastPage) {
1600                   page_ptr = lastPage = curPage->prev;
1601                   lastPage->next = NULL;
1602                   curPageNum--;
1603                } else {
1604                   curPage->next->prev = curPage->prev;
1605                   curPage->prev->next = curPage->next;
1606                   page_ptr = curPage->next;
1607                }
1608                FreePage(curPage);
1609                curPage = page_ptr;
1610                lastPageNum--;
1611                topObj = curPage->top;
1612                botObj = curPage->bot;
1613             }
1614          }
1615          CleanUpCmds();
1616          ClearAndRedrawDrawWindow();
1617          RedrawTitleWindow();
1618          ShowPage();
1619 
1620          sprintf(gszMsgBox, TgLoadString(spi.num_pages_specified > 1 ?
1621                STID_MANY_PAGES_DELETED : STID_ONE_PAGE_DELETED),
1622                spi.num_pages_specified);
1623          Msg(gszMsgBox);
1624          SetFileModified(TRUE);
1625       }
1626    }
1627    FreePageSpec(&spi);
1628    SetCurChoice(curChoiceBeforeMakeQuiescent);
1629 }
1630 
SavePagesAs()1631 void SavePagesAs()
1632 {
1633    char spec[MAXSTRING+1];
1634    SpecifyPagesInfo spi;
1635 
1636    if (pageLayoutMode == PAGE_TILE) {
1637       MsgBox(TgLoadString(STID_CANT_DO_SAVEPAGESAS_IN_TILED), TOOL_NAME,
1638             INFO_MB);
1639       return;
1640    }
1641    if (lastPageNum == 1) {
1642       SaveNewFile(FALSE, NULL);
1643       return;
1644    }
1645    *spec = '\0';
1646    Dialog(TgLoadString(STID_SPECIFY_PAGES_TO_SAVE_EX), NULL, spec);
1647    UtilTrimBlanks(spec);
1648    if (*spec == '\0') return;
1649 
1650    memset(&spi, 0, sizeof(SpecifyPagesInfo));
1651    if (!ParsePagesSpec(spec, &spi)) return;
1652 
1653    MakeQuiescent();
1654 
1655    if (spi.num_pages_specified == lastPageNum) {
1656       SaveNewFile(FALSE, NULL);
1657    } else if (spi.num_pages_specified > 0) {
1658       SavePages(&spi);
1659    }
1660    FreePageSpec(&spi);
1661    SetCurChoice(curChoiceBeforeMakeQuiescent);
1662 }
1663 
PrintPages()1664 void PrintPages()
1665 {
1666    char spec[MAXSTRING];
1667 
1668    if (pageLayoutMode == PAGE_TILE) {
1669       MsgBox(TgLoadString(STID_CANT_PRINT_PAGES_IN_TILED), TOOL_NAME, INFO_MB);
1670       return;
1671    }
1672    /* only allows PRINTER, PS_FILE, PDF_FILE, or export filter formats */
1673    switch (whereToPrint) {
1674    case LATEX_FIG:
1675    case XBM_FILE:
1676    case TEXT_FILE:
1677    case NETLIST_FILE:
1678    case EPSI_FILE:
1679    case GIF_FILE:
1680    case HTML_FILE:
1681    case TIFFEPSI_FILE:
1682    case PNG_FILE:
1683    case JPEG_FILE:
1684    case PPM_FILE:
1685    case SVG_FILE:
1686       sprintf(gszMsgBox, TgLoadString(STID_CANT_PRINT_PAGES_IN_FORMAT),
1687             GetExportName(whereToPrint, EXPORT_THIS));
1688       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1689       return;
1690    default: break;
1691    }
1692    strcpy(spec, "*");
1693    Dialog(TgLoadString(STID_SPECIFY_PAGES_TO_PRINT_EX), NULL, spec);
1694    UtilTrimBlanks(spec);
1695    if (*spec == '\0') return;
1696 
1697    MakeQuiescent();
1698 
1699    memset(&gPagesToPrintSpec, 0, sizeof(SpecifyPagesInfo));
1700    if (!ParsePagesSpec(spec, &gPagesToPrintSpec)) return;
1701 
1702    DumpPages();
1703 
1704    FreePageSpec(&gPagesToPrintSpec);
1705    SetCurChoice(curChoiceBeforeMakeQuiescent);
1706 }
1707 
PrintOneFilePerPage()1708 void PrintOneFilePerPage()
1709 {
1710    char spec[MAXSTRING];
1711 
1712    if (pageLayoutMode == PAGE_TILE) {
1713       MsgBox(TgLoadString(STID_CANT_DO_POFPP_IN_TILED), TOOL_NAME, INFO_MB);
1714       return;
1715    } else if (whereToPrint == PRINTER) {
1716       MsgBox(TgLoadString(STID_CANT_DO_POFPP_TO_PRINTER), TOOL_NAME, INFO_MB);
1717       return;
1718    }
1719    strcpy(spec, "*");
1720    Dialog(TgLoadString(STID_SPECIFY_PAGES_TO_PRINT_EX), NULL, spec);
1721    UtilTrimBlanks(spec);
1722    if (*spec == '\0') return;
1723 
1724    MakeQuiescent();
1725 
1726    memset(&gPagesToPrintSpec, 0, sizeof(SpecifyPagesInfo));
1727    if (!ParsePagesSpec(spec, &gPagesToPrintSpec)) return;
1728 
1729    DumpOneFilePerPage();
1730 
1731    FreePageSpec(&gPagesToPrintSpec);
1732    SetCurChoice(curChoiceBeforeMakeQuiescent);
1733 }
1734 
StackedPageMenu(X,Y,TrackMenubar)1735 int StackedPageMenu(X, Y, TrackMenubar)
1736    int X, Y, TrackMenubar;
1737 {
1738    int rc=INVALID;
1739    TgMenu *menu=(stackedPageMenuInfo.create_proc)(NULL, X, Y,
1740          &stackedPageMenuInfo, FALSE);
1741 
1742    activeMenu = MENU_STACKEDPAGE;
1743    if (menu != NULL) {
1744       menu->track_menubar = TrackMenubar;
1745 
1746       rc = TgMenuLoop(menu);
1747       TgDestroyMenu(menu, TRUE);
1748    }
1749    return rc;
1750 }
1751 
TiledPageMenu(X,Y,TrackMenubar)1752 int TiledPageMenu(X, Y, TrackMenubar)
1753    int X, Y, TrackMenubar;
1754 {
1755    int rc=INVALID;
1756    TgMenu *menu=(tiledPageMenuInfo.create_proc)(NULL, X, Y, &tiledPageMenuInfo,
1757          FALSE);
1758 
1759    activeMenu = MENU_TILEDPAGE;
1760    if (menu != NULL) {
1761       menu->track_menubar = TrackMenubar;
1762 
1763       rc = TgMenuLoop(menu);
1764       TgDestroyMenu(menu, TRUE);
1765    }
1766    return rc;
1767 }
1768 
RefreshPageMenu(menu)1769 int RefreshPageMenu(menu)
1770    TgMenu *menu;
1771 {
1772    int ok=TRUE;
1773 
1774    ok &= TgEnableMenuItemByIndex(menu, PAGE_STACK,
1775          (pageLayoutMode==PAGE_STACK));
1776    ok &= TgEnableMenuItemByIndex(menu, PAGE_TILE,
1777          (pageLayoutMode!=PAGE_STACK));
1778    return ok;
1779 }
1780 
CreatePageMenu(parent_menu,x,y,menu_info,status_str_xlated)1781 TgMenu *CreatePageMenu(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       if (!RefreshPageMenu(menu)) {
1791          return TgDestroyMenu(menu, TRUE);
1792       }
1793       menu->refresh_proc = ((RefreshMenuFunc*)RefreshPageMenu);
1794    }
1795    return menu;
1796 }
1797 
PageMenu(X,Y,TrackMenubar)1798 int PageMenu(X, Y, TrackMenubar)
1799    int X, Y, TrackMenubar;
1800 {
1801    switch (pageLayoutMode) {
1802    case PAGE_STACK: return StackedPageMenu(X, Y, TrackMenubar);
1803    case PAGE_TILE: return TiledPageMenu(X, Y, TrackMenubar);
1804    }
1805    return INVALID;
1806 }
1807 
DelAllPages()1808 void DelAllPages()
1809 {
1810    register struct PageRec *next_page=NULL;
1811 
1812    for (curPage=firstPage; curPage != NULL; curPage=next_page) {
1813       next_page = curPage->next;
1814       FreePage(curPage);
1815    }
1816    lastPageNum = 0;
1817    firstPage = lastPage = curPage = NULL;
1818    InitPage();
1819 }
1820 
1821 static
AnyObjOnPageBoundary()1822 int AnyObjOnPageBoundary()
1823 {
1824    register struct ObjRec *obj_ptr;
1825    int ltx, lty, rbx, rby, next_page_x, next_page_y;
1826 
1827    for (obj_ptr=topObj; obj_ptr != NULL; obj_ptr=obj_ptr->next) {
1828       ltx = obj_ptr->obbox.ltx; lty = obj_ptr->obbox.lty;
1829       rbx = obj_ptr->obbox.rbx; rby = obj_ptr->obbox.rby;
1830       if (ltx < 0 || lty < 0 || rbx >= onePageWidth*paperCol ||
1831             rby >= onePageHeight*paperRow) {
1832          MsgBox(TgLoadString(STID_OBJ_OUTSIDE_PAGE_BNRDY_SWITCH), TOOL_NAME,
1833                INFO_MB);
1834          return TRUE;
1835       }
1836       next_page_x = ((ltx % onePageWidth) == 0) ?
1837             onePageWidth * (round(ltx / onePageWidth) + 1) :
1838             onePageWidth * (((int)(ltx / onePageWidth)) + 1);
1839       next_page_y = ((lty % onePageHeight) == 0) ?
1840             onePageHeight * (round(lty / onePageHeight) + 1) :
1841             onePageHeight * (((int)(lty / onePageHeight)) + 1);
1842       if (rbx >= next_page_x || rby >= next_page_y) {
1843          MsgBox(TgLoadString(STID_OBJ_OUTSIDE_PAGE_BNRDY_SWITCH), TOOL_NAME,
1844                INFO_MB);
1845          return TRUE;
1846       }
1847    }
1848    return FALSE;
1849 }
1850 
1851 static
CalcStackPageNum(obj_ptr)1852 int CalcStackPageNum(obj_ptr)
1853    struct ObjRec *obj_ptr;
1854 {
1855    int ltx, lty, col, row;
1856 
1857    ltx = obj_ptr->obbox.ltx; lty = obj_ptr->obbox.lty;
1858    col = ((ltx % onePageWidth) == 0) ? round(ltx / onePageWidth) + 1 :
1859          ((int)(ltx / onePageWidth)) + 1;
1860    row = ((lty % onePageHeight) == 0) ? round(lty / onePageHeight) + 1 :
1861          ((int)(lty / onePageHeight)) + 1;
1862    return ((row-1) * paperCol + col);
1863 }
1864 
1865 static
TileToStack()1866 void TileToStack()
1867 {
1868    register int i;
1869    register struct ObjRec *obj_ptr, *prev_obj;
1870    int *dx=NULL, *dy=NULL, index;
1871    struct PageRec **page_handle=NULL;
1872    struct ObjRec *saved_top_obj, *saved_bot_obj;
1873 
1874    saved_top_obj=curPage->top;
1875    saved_bot_obj=curPage->bot;
1876    curPage->top = curPage->bot = NULL;
1877    DelAllPages();
1878 
1879    firstPage = lastPage = curPage = NULL;
1880    lastPageNum = paperCol * paperRow;
1881    InitPage();
1882 
1883    page_handle = (struct PageRec **)malloc(lastPageNum*sizeof(struct PageRec*));
1884    if (page_handle == NULL) FailAllocMessage();
1885    dx = (int*)malloc(lastPageNum*sizeof(int));
1886    dy = (int*)malloc(lastPageNum*sizeof(int));
1887    if (dx == NULL || dy == NULL) FailAllocMessage();
1888    for (curPage=firstPage, i=0; curPage != NULL; curPage=curPage->next, i++) {
1889       dx[i] = (i % paperCol) * onePageWidth;
1890       dy[i] = (((i % paperCol) == 0) ? round(i / paperCol):
1891             ((int)(i / paperCol))) * onePageHeight;
1892       page_handle[i] = curPage;
1893    }
1894    for (obj_ptr=saved_bot_obj; obj_ptr != NULL; obj_ptr = prev_obj) {
1895       prev_obj = obj_ptr->prev;
1896       index = CalcStackPageNum(obj_ptr)-1;
1897       curPage = page_handle[index];
1898       AddObj(NULL, curPage->top, obj_ptr);
1899       MoveObj(obj_ptr, -(dx[index]), -(dy[index]));
1900    }
1901    curPage = firstPage;
1902    topObj = curPage->top;
1903    botObj = curPage->bot;
1904    curPageNum = 1;
1905    paperCol = paperRow = 1;
1906    free(dx);
1907    free(dy);
1908    free(page_handle);
1909 }
1910 
1911 static
StackToTile()1912 void StackToTile()
1913 {
1914    register struct ObjRec *obj_ptr, *prev_obj;
1915    int i, dx, dy;
1916    struct PageRec *saved_first_page, *saved_last_page;
1917    struct PageRec *tmp_page, *page_ptr;
1918 
1919    if (paperCol * paperRow < lastPageNum && !JustSpecifyDrawingSize()) return;
1920 
1921    saved_first_page = firstPage;
1922    saved_last_page = lastPage;
1923    firstPage = lastPage = NULL;
1924    lastPageNum = 1;
1925    InitPage();
1926    tmp_page = firstPage;
1927 
1928    i = 0;
1929    for (page_ptr=saved_first_page; page_ptr != NULL;
1930          page_ptr=page_ptr->next, i++) {
1931       dx = (i % paperCol) * onePageWidth;
1932       dy = (((i % paperCol) == 0) ? round(i / paperCol):
1933             ((int)(i / paperCol))) * onePageHeight;
1934       for (obj_ptr=page_ptr->bot; obj_ptr != NULL; obj_ptr=prev_obj) {
1935          prev_obj = obj_ptr->prev;
1936          AddObj(NULL, topObj, obj_ptr);
1937          MoveObj(obj_ptr, dx, dy);
1938       }
1939       page_ptr->top = page_ptr->bot = NULL;
1940    }
1941    firstPage = saved_first_page;
1942    lastPage = saved_last_page;
1943    DelAllPages();
1944    firstPage = lastPage = curPage = tmp_page;
1945    curPageNum = lastPageNum = 1;
1946    pageLineShownInTileMode = TRUE;
1947    topObj = curPage->top;
1948    botObj = curPage->bot;
1949 }
1950 
1951 static
PreservePageNames()1952 int PreservePageNames()
1953 {
1954    struct PageRec *page_ptr=NULL;
1955 
1956    for (page_ptr=firstPage; page_ptr != NULL; page_ptr=page_ptr->next) {
1957       if (page_ptr->name != NULL && *page_ptr->name != '\0') {
1958          break;
1959       } else if (page_ptr->page_file_name != NULL &&
1960             *page_ptr->page_file_name != '\0') {
1961          break;
1962       }
1963    }
1964    if (page_ptr != NULL) {
1965       if (MsgBox(TgLoadString(STID_SWTCH_TO_TILED_LOSE_ALL_NAMES), TOOL_NAME,
1966             YNC_MB) != MB_ID_YES) {
1967          return FALSE;
1968       }
1969    }
1970    return TRUE;
1971 }
1972 
PageLayoutSubMenu(index)1973 void PageLayoutSubMenu(index)
1974    int index;
1975 {
1976    if (pageLayoutMode == index) return;
1977 
1978    if (gstWBInfo.do_whiteboard) {
1979       MsgBox(TgLoadString(STID_CHANGE_PAGE_LAYOUT_MODE_IN_WB), TOOL_NAME,
1980             INFO_MB);
1981       return;
1982    }
1983    if (!OkToFlushUndoBuffer(TgLoadString(STID_CHNG_PAGE_LAYOUT_FLUSH))) {
1984       return;
1985    }
1986    MakeQuiescent();
1987 
1988    switch (index) {
1989    case PAGE_STACK:
1990       if (AnyObjOnPageBoundary()) {
1991          SetCurChoice(curChoiceBeforeMakeQuiescent);
1992          return;
1993       }
1994       pageLayoutMode = index;
1995       TileToStack();
1996       Msg(TgLoadString(STID_PAGE_LAYOUT_MODE_IS_STACKED));
1997       break;
1998    case PAGE_TILE:
1999       if (!PreservePageNames() || !JustSpecifyDrawingSize()) {
2000          SetCurChoice(curChoiceBeforeMakeQuiescent);
2001          return;
2002       }
2003       pageLayoutMode = index;
2004       StackToTile();
2005       Msg(TgLoadString(STID_PAGE_LAYOUT_MODE_IS_TILED));
2006       break;
2007    }
2008    ShowPage();
2009    ShowPageLayout();
2010    UpdatePinnedMenu(MENU_FILE);
2011    UpdatePinnedMenu(MENU_LAYOUT);
2012    UpdatePinnedMenu(MENU_PAGELAYOUT);
2013    UpdatePinnedMenu(MENU_MAIN);
2014    switch (pageLayoutMode) {
2015    case PAGE_STACK: DestroyPinnedMenu(MENU_TILEDPAGE); break;
2016    case PAGE_TILE: DestroyPinnedMenu(MENU_STACKEDPAGE); break;
2017    }
2018    DestroyPinnedMenu(MENU_PAGE);
2019 
2020    UpdPageStyle(pageStyle);
2021    RedrawScrollBars();
2022    UpdDrawWinBBox();
2023    AdjSplineVs();
2024    ClearAndRedrawDrawWindow();
2025    RedrawTitleWindow();
2026    SetFileModified(TRUE);
2027    SetCurChoice(curChoiceBeforeMakeQuiescent);
2028 }
2029 
RefreshPageLayoutMenu(menu)2030 void RefreshPageLayoutMenu(menu)
2031    TgMenu *menu;
2032 {
2033    int i, num_items=menu->num_items;
2034    TgMenuItem *menuitems=menu->menuitems;
2035 
2036    for (i=0; i < num_items; i++) {
2037       TgMenuItem *menu_item=(&menuitems[i]);
2038       TgMenuItem stMenuItem;
2039 
2040       memset(&stMenuItem, 0, sizeof(TgMenuItem));
2041       stMenuItem.state = TGBS_NORMAL;
2042       stMenuItem.checked = (i == pageLayoutMode);
2043       TgSetMenuItemInfo(menu_item, TGMU_MASK_STATE|TGMU_MASK_CHECK,
2044             &stMenuItem);
2045    }
2046 }
2047 
CreatePageLayoutMenu(parent_menu,x,y,menu_info,status_str_xlated)2048 TgMenu *CreatePageLayoutMenu(parent_menu, x, y, menu_info, status_str_xlated)
2049    TgMenu *parent_menu;
2050    int x, y;
2051    TgMenuInfo *menu_info;
2052    int status_str_xlated; /* ignored, always 0 */
2053 {
2054    TgMenu *menu=TgCreateMenuFromMenuInfo(parent_menu, x, y, menu_info, FALSE);
2055 
2056    if (menu != NULL) {
2057       TgMenuItem *menu_item=NULL;
2058       TgMenuItem stMenuItem;
2059 
2060       menu->track_menubar = TRUE;
2061       TgAdjustMenuGeometry(menu, choiceImageW, choiceImageH,
2062             MAXPAGELAYOUTMODES);
2063       menu_item = (&menu->menuitems[pageLayoutMode]);
2064 
2065       memset(&stMenuItem, 0, sizeof(TgMenuItem));
2066       stMenuItem.checked = TRUE;
2067       if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_CHECK, &stMenuItem)) {
2068          return TgDestroyMenu(menu, TRUE);
2069       }
2070       menu->refresh_proc = ((RefreshMenuFunc*)RefreshPageLayoutMenu);
2071    }
2072    return menu;
2073 }
2074 
PageLayoutMenu(X,Y,TrackMenubar)2075 int PageLayoutMenu(X, Y, TrackMenubar)
2076    int X, Y, TrackMenubar;
2077 {
2078    int rc=INVALID;
2079    TgMenu *menu=(pageLayoutMenuInfo.create_proc)(NULL, X, Y,
2080          &pageLayoutMenuInfo, INVALID);
2081 
2082    activeMenu = MENU_PAGELAYOUT;
2083    if (menu != NULL) {
2084       menu->track_menubar = TrackMenubar;
2085 
2086       rc = TgMenuLoop(menu);
2087       TgDestroyMenu(menu, TRUE);
2088    }
2089    return rc;
2090 }
2091 
PageEventHandler(input)2092 void PageEventHandler(input)
2093    XEvent *input;
2094 {
2095    XEvent ev;
2096 
2097    if (input->type == Expose) {
2098       while (XCheckWindowEvent(mainDisplay, pageWindow, ExposureMask, &ev)) ;
2099       RedrawPageWindow();
2100    } else if (input->type == EnterNotify) {
2101       SetMouseStatus("", "", "");
2102    } else if (input->type == MotionNotify) {
2103       while (XCheckWindowEvent(mainDisplay,pageWindow,PointerMotionMask,&ev)) ;
2104       if (pageLayoutMode == PAGE_TILE) {
2105          SetMouseStatus(TgLoadCachedString(CSTID_PARANED_NONE),
2106                TgLoadCachedString(CSTID_PAGE_MENU),
2107                TgLoadCachedString(CSTID_PARANED_NONE));
2108       } else {
2109          HandleMotionInPageWindow(&input->xmotion);
2110       }
2111    } else if (input->type == ButtonPress) {
2112       XButtonEvent *button_ev=(&(input->xbutton));
2113 
2114       if (pageLayoutMode == PAGE_TILE) {
2115          if (button_ev->button == Button2) {
2116             PageMenu(button_ev->x_root, button_ev->y_root, FALSE);
2117          }
2118       } else {
2119          if (button_ev->button == Button1) {
2120             HandleClickInPageWindow(button_ev);
2121          } else if (button_ev->button == Button2) {
2122             PageMenu(button_ev->x_root, button_ev->y_root, FALSE);
2123          }
2124       }
2125    }
2126 }
2127 
CleanUpPage()2128 void CleanUpPage()
2129 {
2130    DelAllPages();
2131    if (leftend_bits == NULL) { }
2132 }
2133 
2134 static PageInfo stPageInfo;
2135 
PushPageInfo()2136 void PushPageInfo()
2137 {
2138    stPageInfo.page_layout_mode = pageLayoutMode;
2139    stPageInfo.paper_col = paperCol;
2140    stPageInfo.paper_row = paperRow;
2141    stPageInfo.cur_page_num = curPageNum;
2142    stPageInfo.last_page_num = lastPageNum;
2143    stPageInfo.first_page = firstPage;
2144    stPageInfo.last_page = lastPage;
2145    stPageInfo.cur_page = curPage;
2146 }
2147 
PopPageInfo()2148 void PopPageInfo()
2149 {
2150    pageLayoutMode = stPageInfo.page_layout_mode;
2151    paperCol = stPageInfo.paper_col;
2152    paperRow = stPageInfo.paper_row;
2153    curPageNum = stPageInfo.cur_page_num;
2154    lastPageNum = stPageInfo.last_page_num;
2155    firstPage = stPageInfo.first_page;
2156    lastPage = stPageInfo.last_page;
2157    curPage = stPageInfo.cur_page;
2158 }
2159 
GetPageInfo(pPageInfo)2160 void GetPageInfo(pPageInfo)
2161    PageInfo *pPageInfo;
2162 {
2163    pPageInfo->page_layout_mode = pageLayoutMode;
2164    pPageInfo->paper_col = paperCol;
2165    pPageInfo->paper_row = paperRow;
2166    pPageInfo->cur_page_num = curPageNum;
2167    pPageInfo->last_page_num = lastPageNum;
2168    pPageInfo->first_page = firstPage;
2169    pPageInfo->last_page = lastPage;
2170    pPageInfo->cur_page = curPage;
2171 }
2172 
2173 /* --------------------- FixPageNumbersForSlideShow() --------------------- */
2174 
2175 static
FixPageNumInStrSeg(pStrSeg,attr_ptr,just_checking)2176 int FixPageNumInStrSeg(pStrSeg, attr_ptr, just_checking)
2177    StrSegInfo *pStrSeg;
2178    struct AttrRec *attr_ptr;
2179    int just_checking;
2180 {
2181    static int page_num_str_len=0, num_pages_str_len=0;
2182    static int stInitialized=FALSE;
2183 
2184    if (!stInitialized) {
2185       stInitialized = TRUE;
2186       /* do not translate -- program constants */
2187       page_num_str_len = strlen("!(STACKED_PAGE_NUM)");
2188       num_pages_str_len = strlen("!(STACKED_NUM_PAGES)");
2189    }
2190    /* do not translate -- program constants */
2191    if (strstr(pStrSeg->dyn_str.s, "!(STACKED_PAGE_NUM)") != NULL ||
2192          strstr(pStrSeg->dyn_str.s, "!(STACKED_NUM_PAGES)") != NULL) {
2193       char *c_ptr=NULL, *c_ptr1=NULL;
2194       struct ObjRec *attr_owner_obj=NULL;
2195 
2196       if (just_checking) {
2197          return TRUE;
2198       }
2199       attr_owner_obj = GetTopOwner(attr_ptr->owner);
2200       while ((c_ptr=strstr(pStrSeg->dyn_str.s, "!(STACKED_PAGE_NUM)")) !=
2201             NULL) {
2202          c_ptr1 = &c_ptr[page_num_str_len];
2203          sprintf(c_ptr, "%1d", curPageNum);
2204          c_ptr = &c_ptr[strlen(c_ptr)];
2205          while (*c_ptr1 != '\0') *c_ptr++ = *c_ptr1++;
2206          *c_ptr = '\0';
2207       }
2208       while ((c_ptr=strstr(pStrSeg->dyn_str.s, "!(STACKED_NUM_PAGES)")) !=
2209             NULL) {
2210          c_ptr1 = &c_ptr[num_pages_str_len];
2211          sprintf(c_ptr, "%1d", lastPageNum);
2212          c_ptr = &c_ptr[strlen(c_ptr)];
2213          while (*c_ptr1 != '\0') *c_ptr++ = *c_ptr1++;
2214          *c_ptr = '\0';
2215       }
2216       RecursivelyAdjObjBBox(attr_ptr->owner, attr_ptr->owner, attr_owner_obj);
2217 
2218       SetFileModified(TRUE);
2219       return TRUE;
2220    }
2221    return FALSE;
2222 }
2223 
2224 static
FixPageNumInStrBlock(pStrBlock,attr_ptr,just_checking)2225 int FixPageNumInStrBlock(pStrBlock, attr_ptr, just_checking)
2226    StrBlockInfo *pStrBlock;
2227    struct AttrRec *attr_ptr;
2228    int just_checking;
2229 {
2230    int changed=FALSE;
2231 
2232    switch (pStrBlock->type) {
2233    case SB_SIMPLE:
2234       if (FixPageNumInStrSeg(pStrBlock->seg, attr_ptr, just_checking)) {
2235          if (just_checking) {
2236             return TRUE;
2237          }
2238          changed = TRUE;
2239       }
2240       break;
2241    case SB_CHAR_SPACE: break;
2242 
2243    case SB_SUPSUB_LEFT:
2244    case SB_SUPSUB_CENTER:
2245    case SB_SUPSUB_RIGHT:
2246       if (pStrBlock->type == SB_SUPSUB_CENTER) {
2247          if (FixPageNumInStrSeg(pStrBlock->seg, attr_ptr, just_checking)) {
2248             if (just_checking) {
2249                return TRUE;
2250             }
2251             changed = TRUE;
2252          }
2253       }
2254       if (pStrBlock->sup != NULL) {
2255          if (FixPageNumInMiniLines(pStrBlock->sup, attr_ptr, just_checking)) {
2256             if (just_checking) {
2257                return TRUE;
2258             }
2259             changed = TRUE;
2260          }
2261       }
2262       if (pStrBlock->sub != NULL) {
2263          if (FixPageNumInMiniLines(pStrBlock->sub, attr_ptr, just_checking)) {
2264             if (just_checking) {
2265                return TRUE;
2266             }
2267             changed = TRUE;
2268          }
2269       }
2270       break;
2271    }
2272    return changed;
2273 }
2274 
2275 static
FixPageNumInMiniLine(pMiniLine,attr_ptr,just_checking)2276 int FixPageNumInMiniLine(pMiniLine, attr_ptr, just_checking)
2277    MiniLineInfo *pMiniLine;
2278    struct AttrRec *attr_ptr;
2279    int just_checking;
2280 {
2281    int changed=FALSE;
2282    StrBlockInfo *pStrBlock=NULL;
2283 
2284    for (pStrBlock=pMiniLine->first_block; pStrBlock != NULL;
2285          pStrBlock=pStrBlock->next) {
2286       if (FixPageNumInStrBlock(pStrBlock, attr_ptr, just_checking)) {
2287          if (just_checking) {
2288             return TRUE;
2289          }
2290          changed = TRUE;
2291       }
2292    }
2293    return changed;
2294 }
2295 
FixPageNumInMiniLines(minilines,attr_ptr,just_checking)2296 int FixPageNumInMiniLines(minilines, attr_ptr, just_checking)
2297    MiniLinesInfo *minilines;
2298    struct AttrRec *attr_ptr;
2299    int just_checking;
2300 {
2301    int changed=FALSE;
2302    MiniLineInfo *pMiniLine=NULL;
2303 
2304    for (pMiniLine=minilines->first; pMiniLine != NULL;
2305          pMiniLine=pMiniLine->next) {
2306       if (FixPageNumInMiniLine(pMiniLine, attr_ptr, just_checking)) {
2307          if (just_checking) {
2308             return TRUE;
2309          }
2310          changed = TRUE;
2311       }
2312    }
2313    return changed;
2314 }
2315 
2316 static
FixPageNumInAttr(AttrPtr,just_checking)2317 int FixPageNumInAttr(AttrPtr, just_checking)
2318    struct AttrRec *AttrPtr;
2319    int just_checking;
2320 {
2321    int changed=FALSE;
2322 
2323    for ( ; AttrPtr != NULL; AttrPtr=AttrPtr->prev) {
2324       if (!AttrPtr->shown) {
2325          continue;
2326       }
2327       /* do not translate -- program constants */
2328       if (!AttrPtr->nameshown && *AttrPtr->attr_name.s == '!' &&
2329             strcmp(AttrPtr->attr_name.s, "!PAGE_NUM=") == 0) {
2330          if (FixPageNumInMiniLines(&AttrPtr->obj->detail.t->minilines, AttrPtr,
2331                just_checking)) {
2332             if (just_checking) {
2333                return TRUE;
2334             }
2335             UpdateAttr(AttrPtr->obj->detail.t, AttrPtr);
2336             changed = TRUE;
2337          }
2338       }
2339    }
2340    return changed;
2341 }
2342 
2343 static
FixPageNumInObj(ObjPtr,just_checking)2344 int FixPageNumInObj(ObjPtr, just_checking)
2345    struct ObjRec *ObjPtr;
2346    int just_checking;
2347 {
2348    int something_changed=FALSE;
2349 
2350    switch (ObjPtr->type) {
2351    case OBJ_POLY:
2352    case OBJ_BOX:
2353    case OBJ_OVAL:
2354    case OBJ_POLYGON:
2355    case OBJ_ARC:
2356    case OBJ_RCBOX:
2357    case OBJ_XBM:
2358    case OBJ_XPM:
2359       if (!colorLayers ||
2360             ObjPtr->tmp_parent!=NULL || ObjInVisibleLayer(ObjPtr)) {
2361          if (FixPageNumInAttr(ObjPtr->lattr, just_checking)) {
2362             if (just_checking) {
2363                return TRUE;
2364             } else {
2365                something_changed = TRUE;
2366             }
2367          }
2368       }
2369       break;
2370    case OBJ_TEXT: break;
2371 
2372    case OBJ_SYM:
2373    case OBJ_ICON:
2374    case OBJ_GROUP:
2375       if (!colorLayers ||
2376             ObjPtr->tmp_parent!=NULL || ObjInVisibleLayer(ObjPtr)) {
2377          struct ObjRec *obj_ptr=ObjPtr->detail.r->last;
2378 
2379          for ( ; obj_ptr != NULL; obj_ptr = obj_ptr->prev) {
2380             obj_ptr->tmp_parent = ObjPtr;
2381             if (FixPageNumInObj(obj_ptr, just_checking)) {
2382                if (just_checking) {
2383                   return TRUE;
2384                } else {
2385                   something_changed = TRUE;
2386                }
2387             }
2388          }
2389          if (FixPageNumInAttr(ObjPtr->lattr, just_checking)) {
2390             if (just_checking) {
2391                return TRUE;
2392             } else {
2393                something_changed = TRUE;
2394             }
2395          }
2396       }
2397       break;
2398    case OBJ_PIN:
2399       if (!colorLayers ||
2400             ObjPtr->tmp_parent!=NULL || ObjInVisibleLayer(ObjPtr)) {
2401          struct ObjRec *obj_ptr=GetPinObj(ObjPtr);
2402 
2403          obj_ptr->tmp_parent = ObjPtr;
2404          if (FixPageNumInObj(obj_ptr, just_checking)) {
2405             if (just_checking) {
2406                return TRUE;
2407             } else {
2408                something_changed = TRUE;
2409             }
2410          }
2411          if (FixPageNumInAttr(ObjPtr->lattr, just_checking)) {
2412             if (just_checking) {
2413                return TRUE;
2414             } else {
2415                something_changed = TRUE;
2416             }
2417          }
2418       }
2419       break;
2420    }
2421    if (just_checking) return FALSE;
2422 
2423    return something_changed;
2424 }
2425 
FixPageNumbersForSlideShow()2426 void FixPageNumbersForSlideShow()
2427 {
2428    int i=0, saved_cur_page_num=curPageNum, page_num=1, num_pages_to_fix=0;
2429    int *pages_to_fix=NULL;
2430    struct PageRec *page_ptr=NULL;
2431    struct ObjRec *obj_ptr=NULL;
2432 
2433    for (page_ptr=firstPage, page_num=1; page_ptr != NULL;
2434          page_ptr=page_ptr->next, page_num++) {
2435       for (obj_ptr=page_ptr->bot; obj_ptr != NULL; obj_ptr=obj_ptr->prev) {
2436          obj_ptr->tmp_parent = NULL;
2437          if (FixPageNumInObj(obj_ptr, TRUE)) {
2438             num_pages_to_fix++;
2439             if (pages_to_fix == NULL) {
2440                pages_to_fix = (int*)malloc(sizeof(int));
2441             } else {
2442                pages_to_fix = (int*)realloc(pages_to_fix,
2443                      num_pages_to_fix*sizeof(int));
2444             }
2445             if (pages_to_fix == NULL) FailAllocMessage();
2446             pages_to_fix[num_pages_to_fix-1] = page_num;
2447             break;
2448          }
2449       }
2450    }
2451    if (num_pages_to_fix == 0) {
2452       /* nothing to fix */
2453       return;
2454    }
2455    StartCompositeCmd();
2456    for (i=0; i < num_pages_to_fix; i++) {
2457       page_num = pages_to_fix[i];
2458       if (page_num != curPageNum) {
2459          PrepareToRecord(CMD_GOTO_PAGE, NULL, NULL, curPageNum);
2460          GotoPageNum(page_num);
2461          RecordCmd(CMD_GOTO_PAGE, NULL, NULL, NULL, curPageNum);
2462       }
2463       if (gstWBInfo.do_whiteboard && curPageNum != saved_cur_page_num) {
2464          /*
2465           * Since the whiteboard is active, others only see
2466           *         the current page.  So, changes to other
2467           *         pages should not be seen by other whiteboards.
2468           */
2469          gstWBInfo.dont_serialize = TRUE;
2470       }
2471       for (obj_ptr=botObj; obj_ptr != NULL; obj_ptr=obj_ptr->prev) {
2472          PrepareToReplaceAnObj(obj_ptr);
2473          if (FixPageNumInObj(obj_ptr, FALSE)) {
2474             RecordReplaceAnObj(obj_ptr);
2475          } else {
2476             AbortPrepareCmd(CMD_REPLACE);
2477          }
2478       }
2479       if (gstWBInfo.do_whiteboard && curPageNum != saved_cur_page_num) {
2480          gstWBInfo.dont_serialize = FALSE;
2481       }
2482    }
2483    if (curPageNum != saved_cur_page_num) {
2484       PrepareToRecord(CMD_GOTO_PAGE, NULL, NULL, curPageNum);
2485       GotoPageNum(saved_cur_page_num);
2486       RecordCmd(CMD_GOTO_PAGE, NULL, NULL, NULL, curPageNum);
2487    }
2488    EndCompositeCmd();
2489 
2490    free(pages_to_fix);
2491 }
2492 
NeedToFixPageNumbersForSlideShow()2493 int NeedToFixPageNumbersForSlideShow()
2494 {
2495    struct PageRec *page_ptr=NULL;
2496    struct ObjRec *obj_ptr=NULL;
2497 
2498    for (page_ptr=firstPage; page_ptr != NULL; page_ptr=page_ptr->next) {
2499       for (obj_ptr=page_ptr->bot; obj_ptr != NULL; obj_ptr=obj_ptr->prev) {
2500          obj_ptr->tmp_parent = NULL;
2501          if (FixPageNumInObj(obj_ptr, TRUE)) {
2502             return TRUE;
2503          }
2504       }
2505    }
2506    return FALSE;
2507 }
2508 
2509 static
ClearPaperColor()2510 void ClearPaperColor()
2511 {
2512    myFileBgPixel = INVALID;
2513    if (myFileBgColorStr != NULL) {
2514       free(myFileBgColorStr);
2515       myFileBgColorStr = NULL;
2516       XSetWindowBackground(mainDisplay, drawWindow, myBgPixel);
2517       ClearAndRedrawDrawWindow();
2518       RecalcXorPixels();
2519    }
2520 }
2521 
2522 static
RemoveAllBgColorFileAttrs()2523 int RemoveAllBgColorFileAttrs()
2524    /* This cannot be undone! */
2525 {
2526    struct AttrRec *attr_ptr=NULL;
2527    int modified=FALSE;
2528 
2529    for (attr_ptr=tgifObj->fattr; attr_ptr != NULL;
2530          attr_ptr=attr_ptr->next) {
2531       if (strcmp(attr_ptr->attr_name.s, "bg_color=") == 0) {
2532          UnlinkAttr(attr_ptr);
2533          FreeTextObj(attr_ptr->obj);
2534          FreeAttr(attr_ptr);
2535 
2536          modified = TRUE;
2537       }
2538    }
2539    return modified;
2540 }
2541 
SetPaperColor()2542 void SetPaperColor()
2543 {
2544    char spec[MAXSTRING+1];
2545    int new_alloc=FALSE, index=0;
2546 
2547    if (!OkToFlushUndoBuffer(TgLoadString(STID_SET_PAPER_COLOR_CAUSE_FLUSH))) {
2548       return;
2549    }
2550    *spec = '\0';
2551    if (myFileBgColorStr == NULL) {
2552       Dialog(TgLoadString(STID_SPECIFY_A_PAPER_COLOR), NULL, spec);
2553    } else {
2554       sprintf(gszMsgBox, TgLoadString(STID_SPECIFY_A_PAPER_COLOR_CUR_IS),
2555             myFileBgColorStr);
2556       Dialog(gszMsgBox, TgLoadString(STID_ENTER_NONE_TO_REMOVE_COLOR), spec);
2557    }
2558    UtilTrimBlanks(spec);
2559    if (*spec == '\0') return;
2560 
2561    if (myFileBgColorStr != NULL) {
2562       if (UtilStrICmp(spec, myFileBgColorStr) == 0) {
2563          return;
2564       }
2565    } else if (UtilStrICmp(spec, "none") == 0) {
2566       return;
2567    }
2568    MakeQuiescent();
2569    CleanUpCmds();
2570 
2571    if (myFileBgColorStr != NULL) {
2572       if (UtilStrICmp(spec, myFileBgColorStr) == 0) {
2573          SetCurChoice(curChoiceBeforeMakeQuiescent);
2574          return;
2575       } else if (UtilStrICmp(spec, "none") == 0) {
2576          ClearPaperColor();
2577          if (RemoveAllBgColorFileAttrs()) {
2578             Msg(TgLoadString(STID_PAPER_COLOR_REMOVED));
2579             SetFileModified(TRUE);
2580          }
2581          SetCurChoice(curChoiceBeforeMakeQuiescent);
2582          return;
2583       }
2584    }
2585    index = QuickFindColorIndex(NULL, spec, &new_alloc, FALSE);
2586 
2587    if (index == INVALID) {
2588       sprintf(gszMsgBox, TgLoadString(STID_FAIL_ALLOC_NAMED_COLOR), spec);
2589       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2590       SetCurChoice(curChoiceBeforeMakeQuiescent);
2591       return;
2592    }
2593    myFileBgColorStr = UtilStrDup(spec);
2594    if (myFileBgColorStr == NULL) FailAllocMessage();
2595    if (SetFileBgColor()) {
2596       ClearAndRedrawDrawWindow();
2597    } else {
2598       ClearPaperColor();
2599    }
2600    RemoveAllBgColorFileAttrs();
2601 
2602    AddAttrByNameAndValue(tgifObj, "bg_color=", spec);
2603 
2604    sprintf(gszMsgBox, TgLoadString(STID_PAPER_COLOR_SET_TO_GIVEN), spec);
2605    Msg(gszMsgBox);
2606 
2607    SetFileModified(TRUE);
2608    SetCurChoice(curChoiceBeforeMakeQuiescent);
2609 }
2610