Fix typo in license headers
[oweals/cde.git] / cde / programs / dtcm / dtcm / print.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: print.c /main/18 1996/11/25 10:23:05 rswiston $ */
24 /*
25  *  (c) Copyright 1993, 1994 Hewlett-Packard Company
26  *  (c) Copyright 1993, 1994 International Business Machines Corp.
27  *  (c) Copyright 1993, 1994 Novell, Inc.
28  *  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
29  */
30
31 #include <EUSCompat.h>
32 #include <stdint.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <ctype.h>
36 #include <csa.h>
37 #include <Xm/Xm.h>
38 #include <Xm/Form.h>
39 #include <Xm/LabelG.h>
40 #include <Xm/DialogS.h>
41 #if 0 && defined(PRINTING_SUPPORTED)
42 #include <Xm/Print.h>
43 #endif /* PRINTING_SUPPORTED */
44 #include <Xm/Protocols.h>
45 #include <Xm/PushBG.h>
46 #include <Xm/SeparatoG.h>
47 #include <Xm/SpinB.h>
48 #include <Xm/Text.h>
49 #include <Xm/TextF.h>
50 #include <Xm/ToggleB.h>
51 #include <Xm/ToggleBG.h>
52 #include <Xm/SashP.h>
53 #include <Xm/SSpinB.h>
54 #include <Xm/RowColumn.h>
55 #include <Dt/HourGlass.h>
56 #include "util.h"
57 #include "misc.h"
58 #include "props.h"
59 #include "props_pu.h"
60 #include "getdate.h"
61 #include "datefield.h"
62 #include "timeops.h"
63 #include "calendar.h"
64 #include "print.h"
65 #include "todo.h"
66 #include "help.h"
67
68 /* needed for view-specific print routines */
69 #include "dayglance.h"
70 #include "weekglance.h"
71 #include "monthglance.h"
72 #include "yearglance.h"
73
74 static char *printErrorTitle = "Calendar : Error - Print";
75 static char *setupErrorTitle = "Calendar : Error - Print Setup";
76 static char *pdmErrorText = "Print Dialog Manager error - setup failed.";
77
78 typedef struct {
79    /* widget handles */
80    Widget pdb;
81    Widget form;
82    Widget report_type_option;
83    Widget from_label;
84    Widget from_spin;
85    Widget from_day;
86    Widget from_month;
87    Widget from_year;
88    Widget to_label;
89    Widget to_spin;
90    Widget to_day;
91    Widget to_month;
92    Widget to_year;
93    Widget more_opts;
94 #ifdef GR_DEBUG
95    Widget debugToggle;
96 #endif
97
98    int    report_type;
99    Boolean setupDataValid;
100    DtPrintSetupData setupData;
101    Widget printShell;
102    Boolean badAllocError;
103 } _DtCmPrintData;
104
105 /*
106  * private function declarations
107  */
108 static void print_cb(Widget, XtPointer, XtPointer);
109 static void print_setup_cb(Widget, XtPointer, XtPointer);
110 static void close_print_display_cb(Widget, XtPointer, XtPointer);
111 static void cancel_cb(Widget, XtPointer, XtPointer);
112 static void pdm_notify_cb(Widget, XtPointer, XtPointer);
113 static void report_option_cb(Widget, XtPointer, XtPointer);
114 static void from_modify_verify_cb(Widget, XtPointer, XtPointer);
115 static void to_modify_verify_cb(Widget, XtPointer, XtPointer);
116 static void spin_field_changed_cb(Widget, XtPointer, XtPointer);
117 static void more_opts_cb(Widget, XtPointer, XtPointer);
118 static Tick pd_modify_day(Calendar *, int, Boolean);
119 static Tick pd_modify_month(Calendar *, int, Boolean);
120 static Tick pd_modify_year(Calendar *, int, Boolean);
121 static Boolean pd_set_start_date(Calendar *, Tick);
122 static Boolean pd_set_end_date(Calendar *, Tick);
123 static Boolean pd_set_max_start_date(Calendar *, Tick);
124 static Boolean pd_set_min_end_date(Calendar *, Tick);
125 static Boolean pd_set_report_type(Calendar *, int);
126 static Boolean pd_set_report_managed(Calendar *, int);
127 static Boolean pd_get_start_positions(Calendar *, int *, int *, int *);
128 static Boolean pd_get_end_positions(Calendar *, int *, int *, int *);
129 static void clearSetupData(_DtCmPrintData *);
130 static void createPrintShell(Calendar *);
131 static void report_error(Calendar *, char *, char *);
132
133 #ifdef GR_DEBUG
134 Boolean
135 inDebugMode(Calendar *c)
136 {
137   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
138   if (pd != (_DtCmPrintData *)NULL)
139     return XmToggleButtonGadgetGetState(pd->debugToggle);
140
141   return False;
142 }
143 #endif
144
145 static Boolean
146 pd_set_start_date(Calendar *c, Tick tick)
147 {
148   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
149   Props *p = (Props *)c->properties;
150   OrderingType ot = get_int_prop(p, CP_DATEORDERING);
151   SeparatorType st = get_int_prop(p, CP_DATESEPARATOR);
152   Arg args[5];
153   int nargs;
154
155   if (pd == (_DtCmPrintData *)NULL)
156     return False;
157
158   if (tick > get_eot())
159     tick = get_eot();
160
161   if (pd_get_report_type(c) == PR_WEEK_VIEW)
162   {
163     /* Week view - start at Monday. */
164     tick = first_dow(tick);
165   }
166
167   if (tick < get_bot())
168     tick = get_bot();
169
170   if (XtIsManaged(pd->from_day))
171   {
172     nargs = 0;
173     XtSetArg(args[nargs], XmNposition, dom(tick)); nargs++;
174     XtSetArg(args[nargs], XmNmaximumValue, monthlength(tick)); nargs++;
175     XtSetValues(pd->from_day, args, nargs);
176   }
177   if (XtIsManaged(pd->from_month))
178   {
179     XtSetArg(args[0], XmNposition, month(tick) - 1);
180     XtSetValues(pd->from_month, args, 1);
181   }
182   XtSetArg(args[0], XmNposition, year(tick));
183   XtSetValues(pd->from_year, args, 1);
184
185   return True;
186 }
187
188 static Boolean
189 pd_set_end_date(Calendar *c, Tick tick)
190 {
191   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
192   Props *p = (Props *)c->properties;
193   OrderingType ot = get_int_prop(p, CP_DATEORDERING);
194   SeparatorType st = get_int_prop(p, CP_DATESEPARATOR);
195   Arg args[5];
196   int nargs;
197
198   if (pd == (_DtCmPrintData *)NULL)
199     return False;
200
201   if (tick < get_bot())
202     tick = get_bot();
203
204   if (pd_get_report_type(c) == PR_WEEK_VIEW)
205   {
206     /* Week view - end on Sunday. */
207     tick = last_dow(tick);
208   }
209
210   if (tick > get_eot())
211     tick = get_eot();
212
213   if (XtIsManaged(pd->to_day))
214   {
215     nargs = 0;
216     XtSetArg(args[nargs], XmNposition, dom(tick)); nargs++;
217     XtSetArg(args[nargs], XmNmaximumValue, monthlength(tick)); nargs++;
218     XtSetValues(pd->to_day, args, nargs);
219   }
220   if (XtIsManaged(pd->to_month))
221   {
222     XtSetArg(args[0], XmNposition, month(tick) - 1);
223     XtSetValues(pd->to_month, args, 1);
224   }
225   XtSetArg(args[0], XmNposition, year(tick));
226   XtSetValues(pd->to_year, args, 1);
227
228   return True;
229 }
230
231 static Boolean
232 pd_set_max_start_date(Calendar *c, Tick tick)
233 {
234   Tick curTick = pd_get_start_date(c);
235
236   return (tick < curTick) ? pd_set_start_date(c, tick) : True;
237 }
238
239 static Boolean
240 pd_set_min_end_date(Calendar *c, Tick tick)
241 {
242   Tick curTick = pd_get_end_date(c);
243
244   return (tick > curTick) ? pd_set_end_date(c, tick) : True;
245 }
246
247 static Boolean
248 pd_set_report_type(Calendar *c, int reportType)
249 {
250   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
251   Widget optionMenu = (Widget)NULL;
252   Arg args[10];
253   int nargs;
254
255   if (pd == (_DtCmPrintData *)NULL)
256     return False;
257
258   if (reportType == pd->report_type)
259     return True;
260
261   nargs = 0;
262   XtSetArg(args[nargs], XmNsubMenuId, &optionMenu); nargs++;
263   XtGetValues(pd->report_type_option, args, nargs);
264
265   if (optionMenu != (Widget)NULL)
266   {
267     WidgetList optionChildren;
268     int nChildren = 0;
269
270     nargs = 0;
271     XtSetArg(args[nargs], XmNchildren, &optionChildren); nargs++;
272     XtSetArg(args[nargs], XmNnumChildren, &nChildren); nargs++;
273     XtGetValues(optionMenu, args, nargs);
274
275     if (nChildren > reportType)
276     {
277       nargs = 0;
278       XtSetArg(args[nargs], XmNmenuHistory,
279                optionChildren[reportType]); nargs++;
280       XtSetValues(pd->report_type_option, args, nargs);
281
282       return pd_set_report_managed(c, reportType);
283     }
284   }
285
286   return False;
287 }
288
289 static Boolean
290 pd_set_report_managed(Calendar *c, int reportType)
291 {
292   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
293   Arg args[10];
294   int nargs;
295
296   if (pd == (_DtCmPrintData *)NULL)
297     return False;
298
299   if (reportType == pd->report_type)
300     return True;
301
302   pd->report_type = reportType;
303
304   switch (reportType)
305   {
306   case PR_YEAR_VIEW:
307     XtManageChild(pd->from_year);
308     XtManageChild(pd->to_year);
309
310     XtUnmanageChild(pd->from_day);
311     XtUnmanageChild(pd->from_month);
312     XtUnmanageChild(pd->to_day);
313     XtUnmanageChild(pd->to_month);
314     break;
315
316   case PR_WEEK_VIEW:
317     XtManageChild(pd->from_year);
318     XtManageChild(pd->from_month);
319     XtManageChild(pd->from_day);
320     XtManageChild(pd->to_year);
321     XtManageChild(pd->to_month);
322     XtManageChild(pd->to_day);
323
324     nargs = 0;
325     XtSetArg(args[nargs], XmNeditable, False); nargs++;
326     XtSetArg(args[nargs], XmNcursorPositionVisible, False); nargs++;
327     XtSetValues(pd->from_day, args, nargs);
328     XtSetValues(pd->to_day, args, nargs);
329     break;
330
331   case PR_DAY_VIEW:
332   case PR_APPT_LIST:
333   case PR_TODO_LIST:
334     XtManageChild(pd->from_year);
335     XtManageChild(pd->from_month);
336     XtManageChild(pd->from_day);
337     XtManageChild(pd->to_year);
338     XtManageChild(pd->to_month);
339     XtManageChild(pd->to_day);
340
341     nargs = 0;
342     XtSetArg(args[nargs], XmNeditable, True); nargs++;
343     XtSetArg(args[nargs], XmNcursorPositionVisible, True); nargs++;
344     XtSetValues(pd->from_day, args, nargs);
345     XtSetValues(pd->to_day, args, nargs);
346     break;
347
348   default:
349   case PR_MONTH_VIEW:
350     XtManageChild(pd->from_year);
351     XtManageChild(pd->from_month);
352     XtManageChild(pd->to_year);
353     XtManageChild(pd->to_month);
354
355     XtUnmanageChild(pd->from_day);
356     XtUnmanageChild(pd->to_day);
357     break;
358   }
359
360   return True;
361 }
362
363 static Boolean
364 pd_get_start_positions(Calendar *c, int *m, int *d, int *y)
365 {
366   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
367   int dayPos = 1, monthPos = 0, yearPos;
368
369   if (pd == (_DtCmPrintData *)NULL)
370     return False;
371
372   if (XtIsManaged(pd->from_day))
373     XtVaGetValues(pd->from_day, XmNposition, &dayPos, NULL);
374   if (XtIsManaged(pd->from_month))
375     XtVaGetValues(pd->from_month, XmNposition, &monthPos, NULL);
376   XtVaGetValues(pd->from_year, XmNposition, &yearPos, NULL);
377
378   *m = monthPos;
379   *d = dayPos;
380   *y = yearPos;
381
382   return True;
383 }
384
385 static Boolean
386 pd_get_end_positions(Calendar *c, int *m, int *d, int *y)
387 {
388   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
389   int dayPos = 1, monthPos = 0, yearPos;
390
391   if (pd == (_DtCmPrintData *)NULL)
392     return False;
393
394   if (XtIsManaged(pd->to_day))
395     XtVaGetValues(pd->to_day, XmNposition, &dayPos, NULL);
396   if (XtIsManaged(pd->to_month))
397     XtVaGetValues(pd->to_month, XmNposition, &monthPos, NULL);
398   XtVaGetValues(pd->to_year, XmNposition, &yearPos, NULL);
399
400   *m = monthPos;
401   *d = dayPos;
402   *y = yearPos;
403
404   return True;
405 }
406
407 static void
408 from_modify_verify_cb(Widget w, XtPointer uDataP, XtPointer cbDataP)
409 {
410   Calendar *c = (Calendar *)uDataP;
411   XmSpinBoxCallbackStruct *cbStruct = (XmSpinBoxCallbackStruct *)cbDataP;
412   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
413   int newPos;
414   Tick newTick;
415
416   cbStruct->doit = False;
417
418   if (cbStruct->widget == pd->from_day)
419   {
420     newTick = pd_modify_day(c, cbStruct->reason, False);
421   }
422   else if (cbStruct->widget == pd->from_month)
423   {
424     newTick = pd_modify_month(c, cbStruct->reason, False);
425   }
426   else if (cbStruct->widget == pd->from_year)
427   {
428     newTick = pd_modify_year(c, cbStruct->reason, False);
429   }
430   else return;
431
432   if (pd_set_start_date(c, newTick) && pd_set_min_end_date(c, newTick))
433   {
434     int monthPos, dayPos, yearPos;
435
436     pd_get_start_positions(c, &monthPos, &dayPos, &yearPos);
437     if (cbStruct->widget == pd->from_day)
438       cbStruct->position = dayPos;
439     else if (cbStruct->widget == pd->from_month)
440       cbStruct->position = monthPos;
441     else cbStruct->position = yearPos;
442     cbStruct->doit = True;
443   }
444 }
445
446 static void
447 to_modify_verify_cb(Widget w, XtPointer uDataP, XtPointer cbDataP)
448 {
449   Calendar *c = (Calendar *)uDataP;
450   XmSpinBoxCallbackStruct *cbStruct = (XmSpinBoxCallbackStruct *)cbDataP;
451   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
452   Tick newTick;
453
454   cbStruct->doit = False;
455
456   if (cbStruct->widget == pd->to_day)
457   {
458     newTick = pd_modify_day(c, cbStruct->reason, True);
459   }
460   else if (cbStruct->widget == pd->to_month)
461   {
462     newTick = pd_modify_month(c, cbStruct->reason, True);
463   }
464   else if (cbStruct->widget == pd->to_year)
465   {
466     newTick = pd_modify_year(c, cbStruct->reason, True);
467   }
468   else return;
469
470   if (pd_set_end_date(c, newTick) && pd_set_max_start_date(c, newTick))
471   {
472     int monthPos, dayPos, yearPos;
473
474     pd_get_end_positions(c, &monthPos, &dayPos, &yearPos);
475     if (cbStruct->widget == pd->to_day)
476       cbStruct->position = dayPos;
477     else if (cbStruct->widget == pd->to_month)
478       cbStruct->position = monthPos;
479     else cbStruct->position = yearPos;
480     cbStruct->doit = True;
481   }
482 }
483
484 static void
485 spin_field_changed_cb(Widget field, XtPointer uData, XtPointer cbData)
486 {
487   char *newStr;
488   int curPos;
489   int newPos;
490   unsigned char sbcType;
491   int minValue;
492   int maxValue;
493   int nValues;
494   XmStringTable strings;
495   int cursorPosition;
496   Arg args[20];
497   int nargs;
498
499   nargs = 0;
500   XtSetArg(args[nargs], XmNspinBoxChildType, &sbcType); nargs++;
501   XtSetArg(args[nargs], XmNmaximumValue, &maxValue); nargs++;
502   XtSetArg(args[nargs], XmNminimumValue, &minValue); nargs++;
503   XtSetArg(args[nargs], XmNnumValues, &nValues); nargs++;
504   XtSetArg(args[nargs], XmNposition, &curPos); nargs++;
505   XtSetArg(args[nargs], XmNvalues, &strings); nargs++;
506   XtSetArg(args[nargs], XmNvalue, &newStr); nargs++;
507   XtSetArg(args[nargs], XmNcursorPosition, &cursorPosition); nargs++;
508   XtGetValues(field, args, nargs);
509
510   newPos = curPos;
511   if (sbcType == XmSTRING)
512   {
513     XmString xmString = XmStringCreateLocalized(newStr);
514
515     for (newPos = 0; newPos < nValues; newPos++)
516     {
517       if (XmStringCompare(xmString, strings[newPos]))
518         break;
519     }
520
521     if (newPos >= nValues)
522       newPos = curPos;
523
524     XmStringFree(xmString);
525   }
526   else if (sbcType == XmNUMERIC)
527   {
528     newPos = atoi(newStr);
529
530     if ((newPos < minValue) ||
531         (newPos > maxValue))
532       newPos = curPos;
533   }
534
535   if (newPos != curPos)
536   {
537     nargs = 0;
538     XtSetArg(args[nargs], XmNposition, newPos); nargs++;
539     XtSetValues(field, args, nargs);
540
541     /* After the above does its thing, restore original cursor position. */
542     nargs = 0;
543     XtSetArg(args[nargs], XmNcursorPosition, cursorPosition); nargs++;
544     XtSetValues(field, args, nargs);
545   }
546
547   XtFree(newStr);
548 }
549
550 static void
551 more_opts_cb(Widget w, XtPointer uData, XtPointer cbData)
552 {
553   Calendar *c = (Calendar *)uData;
554   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
555
556   _DtTurnOnHourGlass(c->frame);
557   _DtTurnOnHourGlass(pd->pdb);
558
559   show_print_props_pu(c);
560
561   _DtTurnOffHourGlass(pd->pdb);
562   _DtTurnOffHourGlass(c->frame);
563 }
564
565 static Tick
566 pd_modify_day(Calendar *c, int reason, Boolean isTo)
567 {
568   int monthPos, dayPos, yearPos;
569   int maxDay;
570   Tick tmpTick;
571   Tick curTick;
572   Tick newTick;
573   int reportType = pd_get_report_type(c);
574
575   if (isTo)
576   {
577     if (!pd_get_end_positions(c, &monthPos, &dayPos, &yearPos))
578       return 0;
579   }
580   else
581   {
582     if (!pd_get_start_positions(c, &monthPos, &dayPos, &yearPos))
583       return 0;
584   }
585
586   switch (reason)
587   {
588   case XmCR_SPIN_NEXT:
589     tmpTick = monthdayyear(monthPos + 1, 1, yearPos);
590     maxDay = monthlength(tmpTick);
591     if ((dayPos == 1) || (dayPos > maxDay))
592       dayPos = maxDay;
593     else dayPos--;
594     curTick = monthdayyear(monthPos + 1, dayPos, yearPos);
595     newTick = (reportType == PR_WEEK_VIEW) ?
596       nextweek(curTick) : nextday(curTick);
597     break;
598
599   case XmCR_SPIN_PRIOR:
600     tmpTick = monthdayyear(monthPos + 1, 1, yearPos);
601     maxDay = monthlength(tmpTick);
602     if (dayPos >= maxDay)
603       dayPos = 1;
604     else dayPos++;
605     curTick = monthdayyear(monthPos + 1, dayPos, yearPos);
606     newTick = (reportType == PR_WEEK_VIEW) ?
607       prevweek(curTick) : prevday(curTick);
608     break;
609
610   default:
611   case XmCR_SPIN_FIRST:
612     newTick = monthdayyear(monthPos + 1, 1, yearPos);
613     if (reportType == PR_WEEK_VIEW)
614     {
615       if (isTo)
616       {
617         /* We want the first Sunday in the month. */
618         newTick = last_dow(newTick);
619       }
620       else
621       {
622         /* We want the first Monday in the month. */
623         int dayOffset = (dow(newTick) + 6) % 7;
624
625         if (dayOffset > 0)
626           newTick = next_ndays(newTick, 7 - dayOffset);
627       }
628     }
629     break;
630
631   case XmCR_SPIN_LAST:
632     curTick = monthdayyear(monthPos + 1, 1, yearPos);
633     newTick = last_dom(curTick);
634     if (reportType == PR_WEEK_VIEW)
635     {
636       if (isTo)
637       {
638         /* We want the last Sunday in the month. */
639         int dayOffset = dow(newTick);
640
641         if (dayOffset > 0)
642           newTick = last_ndays(newTick, dayOffset);
643       }
644       else
645       {
646         /* We want the last Monday in the month. */
647         newTick = first_dow(newTick);
648       }
649     }
650     break;
651   }
652
653   return newTick;
654 }
655
656 static Tick
657 pd_modify_month(Calendar *c, int reason, Boolean isTo)
658 {
659   int monthPos, dayPos, yearPos;
660   int maxDay;
661   Tick tmpTick;
662   Tick curTick;
663   Tick newTick;
664   int reportType = pd_get_report_type(c);
665
666   if (isTo)
667   {
668     if (!pd_get_end_positions(c, &monthPos, &dayPos, &yearPos))
669       return 0;
670   }
671   else
672   {
673     if (!pd_get_start_positions(c, &monthPos, &dayPos, &yearPos))
674       return 0;
675   }
676
677   switch (reason)
678   {
679   case XmCR_SPIN_NEXT:
680     if (monthPos == 0)
681       monthPos = 11;
682     else monthPos--;
683
684     curTick = monthdayyear(monthPos + 1, dayPos, yearPos);
685     if (reportType == PR_WEEK_VIEW)
686       newTick = next_ndays(curTick, 4 * 7);
687     else
688     {
689       tmpTick = nextmonth(curTick);
690       maxDay = monthlength(tmpTick);
691       if (dayPos > maxDay)
692         dayPos = maxDay;
693       newTick = monthdayyear(month(tmpTick), dayPos, year(tmpTick));
694     }
695     break;
696
697   case XmCR_SPIN_PRIOR:
698     if (monthPos == 11)
699       monthPos = 0;
700     else monthPos++;
701
702     curTick = monthdayyear(monthPos + 1, dayPos, yearPos);
703     if (reportType == PR_WEEK_VIEW)
704       newTick = last_ndays(curTick, 4 * 7);
705     else
706     {
707       /* ... There is no prevmonth()! ... */
708       tmpTick = prev_nmonth(curTick, 1);
709       maxDay = monthlength(tmpTick);
710       if (dayPos > maxDay)
711         dayPos = maxDay;
712       newTick = monthdayyear(month(tmpTick), dayPos, year(tmpTick));
713     }
714     break;
715
716   default:
717   case XmCR_SPIN_FIRST:
718     newTick = monthdayyear(1, 1, yearPos);
719     if (reportType == PR_WEEK_VIEW)
720     {
721       if (isTo)
722       {
723         /* We want the first Sunday in the month. */
724         newTick = last_dow(newTick);
725       }
726       else
727       {
728         /* We want the first Monday in the month. */
729         int dayOffset = (dow(newTick) + 6) % 7;
730
731         if (dayOffset > 0)
732           newTick = next_ndays(newTick, 7 - dayOffset);
733       }
734     }
735     break;
736
737   case XmCR_SPIN_LAST:
738     newTick = monthdayyear(12, 31, yearPos);
739     if (reportType == PR_WEEK_VIEW)
740     {
741       if (isTo)
742       {
743         /* We want the last Sunday in the month. */
744         int dayOffset = dow(newTick);
745
746         if (dayOffset > 0)
747           newTick = last_ndays(newTick, dayOffset);
748       }
749       else
750       {
751         /* We want the last Monday in the month. */
752         newTick = first_dow(newTick);
753       }
754     }
755     break;
756   }
757
758   return newTick;
759 }
760
761 static Tick
762 pd_modify_year(Calendar *c, int reason, Boolean isTo)
763 {
764   int monthPos, dayPos, yearPos;
765   int maxDay;
766   Tick tmpTick;
767   Tick curTick;
768   Tick newTick;
769   int reportType = pd_get_report_type(c);
770
771   if (isTo)
772   {
773     if (!pd_get_end_positions(c, &monthPos, &dayPos, &yearPos))
774       return 0;
775   }
776   else
777   {
778     if (!pd_get_start_positions(c, &monthPos, &dayPos, &yearPos))
779       return 0;
780   }
781
782   switch (reason)
783   {
784   case XmCR_SPIN_NEXT:
785     yearPos--;
786
787     curTick = monthdayyear(monthPos + 1, dayPos, yearPos);
788     if (reportType == PR_WEEK_VIEW)
789       newTick = next_ndays(curTick, 52 * 7);
790     else
791     {
792       tmpTick = monthdayyear(monthPos + 1, 1, yearPos + 1);
793       maxDay = monthlength(tmpTick);
794       if (dayPos > maxDay)
795         dayPos = maxDay;
796       newTick = monthdayyear(monthPos + 1, dayPos, yearPos + 1);
797     }
798     break;
799
800   case XmCR_SPIN_PRIOR:
801     yearPos++;
802
803     curTick = monthdayyear(monthPos + 1, dayPos, yearPos);
804     if (reportType == PR_WEEK_VIEW)
805       newTick = last_ndays(curTick, 52 * 7);
806     else
807     {
808       tmpTick = monthdayyear(monthPos + 1, 1, yearPos - 1);
809       maxDay = monthlength(tmpTick);
810       if (dayPos > maxDay)
811         dayPos = maxDay;
812       newTick = monthdayyear(monthPos + 1, dayPos, yearPos - 1);
813     }
814     break;
815
816   default:
817   case XmCR_SPIN_FIRST:
818     yearPos = year(get_bot());
819     tmpTick = monthdayyear(monthPos + 1, 1, yearPos);
820     maxDay = monthlength(tmpTick);
821     if (dayPos > maxDay)
822       dayPos = maxDay;
823     newTick = monthdayyear(monthPos + 1, dayPos, yearPos);
824     break;
825
826   case XmCR_SPIN_LAST:
827     yearPos = year(get_eot());
828     tmpTick = monthdayyear(monthPos + 1, 1, yearPos);
829     maxDay = monthlength(tmpTick);
830     if (dayPos > maxDay)
831       dayPos = maxDay;
832     newTick = monthdayyear(monthPos + 1, dayPos, yearPos);
833     break;
834   }
835
836   return newTick;
837 }
838
839 /*
840  * post_print_dialog()
841  *
842  * Create and display the Print dialog.
843  */
844 void
845 post_print_dialog(
846         Calendar *c)
847 {
848   _DtCmPrintData *pd;
849
850   create_print_dialog(c);
851
852   /* display the dialog on-screen */
853   if ((pd = (_DtCmPrintData *)c->print_data) != (_DtCmPrintData *)NULL)
854   {
855     if (!XtIsManaged(pd->pdb))
856       XtManageChild(pd->pdb);
857     else XRaiseWindow(XtDisplay(pd->pdb),
858                       XtWindow(XtParent(pd->pdb)));
859   }
860 }
861
862 static void
863 clearSetupData(_DtCmPrintData *pd)
864 {
865   if (pd->setupDataValid)
866   {
867     DtPrintFreeSetupData(&pd->setupData);
868     pd->setupDataValid = False;
869   }
870
871   memset(&pd->setupData, 0, sizeof(DtPrintSetupData));
872 }
873
874 static void
875 createPrintShell(Calendar *c)
876 {
877 #if 0 && defined(PRINTING_SUPPORTED)
878   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
879
880 #ifdef GR_DEBUG
881   if (inDebugMode(c))
882   {
883     if (pd->printShell != (Widget)NULL)
884       XtDestroyWidget(pd->printShell);
885
886     pd->printShell = XmCreateDialogShell(c->frame, "Print",
887                                          0, NULL);
888   }
889   else
890 #endif
891   if (pd->printShell == (Widget)NULL)
892   {
893     pd->printShell =
894       XmPrintSetup(pd->pdb,
895                    XpGetScreenOfContext(pd->setupData.print_display,
896                                         pd->setupData.print_context),
897                    "Print", NULL, 0);
898
899     XtAddCallback(pd->printShell, XmNpdmNotificationCallback,
900                   pdm_notify_cb, (XtPointer)c);
901   }
902 #endif  /* PRINTING_SUPPORTED */
903 }
904
905 void
906 create_print_dialog(Calendar *c)
907 {
908         XmString         xmstr, day_view, week_view, month_view,
909                          year_view, appt_list, todo_list, view;
910         _DtCmPrintData  *pd;
911         char             fnamebuf[BUFSIZ];
912         char             *print_file;
913         char             *print_dir;
914         char             *title;
915         Arg              args[20];
916         int              nargs;
917         XmString         abbrevMonths[12];
918         int              maxMonthLen;
919         int              i;
920         int              reportType;
921         Widget           helpButton;
922
923         if ((pd = (_DtCmPrintData *)c->print_data) == NULL)
924         {
925           c->print_data = (caddr_t)XtMalloc(sizeof(_DtCmPrintData));
926           pd = (_DtCmPrintData *) c->print_data;
927
928           /* Initialize filename to dir+filename from props */
929           print_file = get_char_prop((Props *)c->properties,CP_PRINTFILENAME);
930           if (!print_file)
931             print_file = "";
932           print_dir = get_char_prop((Props *)c->properties,CP_PRINTDIRNAME);
933           if (!print_dir)
934             print_dir = "";
935           sprintf(fnamebuf, "%s/%s", print_dir, print_file);
936
937           title = XtNewString(catgets(c->DT_catd, 1, 728, "Calendar : Print"));
938           nargs = 0;
939           XtSetArg(args[nargs], XmNtitle, title); nargs++;
940           XtSetArg(args[nargs], XmNdeleteResponse, XmUNMAP); nargs++;
941           XtSetArg(args[nargs], DtNfileName, fnamebuf); nargs++;
942           XtSetArg(args[nargs], XmNautoUnmanage, False); nargs++;
943           XtSetArg(args[nargs], XmNdeleteResponse, XmDO_NOTHING); nargs++;
944           pd->pdb = DtCreatePrintSetupDialog(c->frame, "Calendar - Print",
945                                              args, nargs);
946           XtFree(title);
947
948           setup_quit_handler(XtParent(pd->pdb), cancel_cb, (XtPointer)c);
949
950           XtAddCallback(pd->pdb, DtNcancelCallback,
951                         cancel_cb, (XtPointer)c);
952           XtAddCallback(pd->pdb, DtNprintCallback,
953                         print_cb, (XtPointer)c);
954           XtAddCallback(pd->pdb, DtNclosePrintDisplayCallback,
955                         close_print_display_cb, (XtPointer)c);
956           XtAddCallback(pd->pdb, DtNsetupCallback,
957                         print_setup_cb, (XtPointer)c);
958
959           helpButton = XtNameToWidget(pd->pdb, "Help");
960           if (helpButton != (Widget)NULL)
961             XtAddCallback(helpButton, XmNactivateCallback,
962                           help_cb, (XtPointer)PRINT_HELP_BUTTON);
963           XtAddCallback(pd->pdb, XmNhelpCallback,
964                         help_cb, (XtPointer)PRINT_HELP_BUTTON);
965
966           nargs = 0;
967           XtSetArg(args[nargs], XmNfractionBase, 3); nargs++;
968           pd->form = XmCreateForm(pd->pdb, "RangeForm", args, nargs);
969
970           view = XmStringCreateLocalized(
971                         catgets(c->DT_catd, 1, 976, "Report Type:"));
972           day_view = XmStringCreateLocalized(
973                         catgets(c->DT_catd, 1, 977, "Day View"));
974           week_view = XmStringCreateLocalized(
975                         catgets(c->DT_catd, 1, 978, "Week View"));
976           month_view = XmStringCreateLocalized(
977                         catgets(c->DT_catd, 1, 979, "Month View"));
978           year_view = XmStringCreateLocalized(
979                         catgets(c->DT_catd, 1, 980, "Year View"));
980           appt_list = XmStringCreateLocalized(
981                         catgets(c->DT_catd, 1, 981, "Appointment List"));
982           todo_list = XmStringCreateLocalized(
983                         catgets(c->DT_catd, 1, 982, "To Do List"));
984
985           /*
986            * remember - this returns a RowColumn widget!
987            */
988           pd->report_type = PR_DAY_VIEW;
989           pd->report_type_option = XmVaCreateSimpleOptionMenu(pd->form,
990                 "TypeOptionMenu", view, 0,
991                 pd->report_type, report_option_cb,
992                 XmVaPUSHBUTTON,         day_view, NULL, NULL, NULL,
993                 XmVaPUSHBUTTON,         week_view, NULL, NULL, NULL,
994                 XmVaPUSHBUTTON,         month_view, NULL, NULL, NULL,
995                 XmVaPUSHBUTTON,         year_view, NULL, NULL, NULL,
996                 XmVaPUSHBUTTON,         appt_list, NULL, NULL, NULL,
997                 XmVaPUSHBUTTON,         todo_list, NULL, NULL, NULL,
998                 XmNorientation,         XmVERTICAL,
999                 XmNtopAttachment,       XmATTACH_FORM,
1000                 XmNtopOffset,           10,
1001                 XmNleftAttachment,      XmATTACH_POSITION,
1002                 XmNleftPosition,        1,
1003                 XmNleftOffset,          5,
1004                 XmNmarginWidth,         0,
1005                 XmNnavigationType,      XmTAB_GROUP,
1006                 NULL);
1007           XtManageChild(pd->report_type_option);
1008
1009           XmStringFree(day_view);
1010           XmStringFree(week_view);
1011           XmStringFree(month_view);
1012           XmStringFree(year_view);
1013           XmStringFree(appt_list);
1014           XmStringFree(todo_list);
1015           XmStringFree(view);
1016
1017           xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1,
1018                                                   731, "From:"));
1019           pd->from_label = XtVaCreateWidget("FromLabel",
1020                 xmLabelGadgetClass,
1021                 pd->form,
1022                 XmNlabelString,         xmstr,
1023                 XmNleftAttachment,      XmATTACH_POSITION,
1024                 XmNleftPosition,        0,
1025                 XmNleftOffset,          10,
1026                 XmNtopAttachment,       XmATTACH_OPPOSITE_WIDGET,
1027                 XmNtopWidget,           pd->report_type_option,
1028                 XmNtopOffset,           0,
1029                 NULL);
1030           XmStringFree(xmstr);
1031           XtManageChild(pd->from_label);
1032
1033           nargs = 0;
1034           XtSetArg(args[nargs], XmNleftAttachment,
1035                    XmATTACH_OPPOSITE_WIDGET); nargs++;
1036           XtSetArg(args[nargs], XmNleftWidget, pd->from_label); nargs++;
1037           XtSetArg(args[nargs], XmNleftOffset, 0); nargs++;
1038           XtSetArg(args[nargs], XmNtopAttachment, XmATTACH_WIDGET); nargs++;
1039           XtSetArg(args[nargs], XmNtopWidget, pd->from_label); nargs++;
1040           XtSetArg(args[nargs], XmNtopOffset, 4); nargs++;
1041           XtSetArg(args[nargs], XmNshadowThickness, 1); nargs++;
1042           pd->from_spin = XmCreateSpinBox(pd->form, "FromSpinBox",
1043                                           args, nargs);
1044           XtAddCallback(pd->from_spin, XmNmodifyVerifyCallback,
1045                         from_modify_verify_cb, (XtPointer)c);
1046
1047           nargs = 0;
1048           XtSetArg(args[nargs], XmNspinBoxChildType, XmNUMERIC); nargs++;
1049           XtSetArg(args[nargs], XmNminimumValue, 1); nargs++;
1050           XtSetArg(args[nargs], XmNmaximumValue, 31); nargs++;
1051           XtSetArg(args[nargs], XmNcolumns, 2); nargs++;
1052           XtSetArg(args[nargs], XmNmaxLength, 2); nargs++;
1053           XtSetArg(args[nargs], XmNposition, 1); nargs++;
1054           pd->from_day = XmCreateTextField(pd->from_spin, "FromDay",
1055                                            args, nargs);
1056           XtAddCallback(pd->from_day, XmNvalueChangedCallback,
1057                         spin_field_changed_cb, (XtPointer)NULL);
1058           XtManageChild(pd->from_day);
1059
1060           maxMonthLen = 0;
1061           for (i = 0; i < 12; i++)
1062           {
1063             abbrevMonths[i] = XmStringCreateLocalized(months2[i + 1]);
1064             if (cm_strlen(months2[i + 1]) > maxMonthLen)
1065               maxMonthLen = cm_strlen(months2[i + 1]);
1066           }
1067           nargs = 0;
1068           XtSetArg(args[nargs], XmNspinBoxChildType, XmSTRING); nargs++;
1069           XtSetArg(args[nargs], XmNnumValues, 12); nargs++;
1070           XtSetArg(args[nargs], XmNvalues, abbrevMonths); nargs++;
1071           XtSetArg(args[nargs], XmNcolumns, maxMonthLen); nargs++;
1072           XtSetArg(args[nargs], XmNmaxLength, maxMonthLen); nargs++;
1073           XtSetArg(args[nargs], XmNposition, 0); nargs++;
1074           pd->from_month = XmCreateTextField(pd->from_spin, "FromMonth",
1075                                              args, nargs);
1076           XtAddCallback(pd->from_month, XmNvalueChangedCallback,
1077                         spin_field_changed_cb, (XtPointer)NULL);
1078           XtManageChild(pd->from_month);
1079
1080           nargs = 0;
1081           XtSetArg(args[nargs], XmNspinBoxChildType, XmNUMERIC); nargs++;
1082           XtSetArg(args[nargs], XmNminimumValue,
1083                    year(get_bot())); nargs++;
1084           XtSetArg(args[nargs], XmNmaximumValue,
1085                    year(get_eot())); nargs++;
1086           XtSetArg(args[nargs], XmNcolumns, 4); nargs++;
1087           XtSetArg(args[nargs], XmNmaxLength, 4); nargs++;
1088           XtSetArg(args[nargs], XmNposition,
1089                    year(get_bot())); nargs++;
1090           XtSetArg(args[nargs], XmNwrap, False); nargs++;
1091           pd->from_year = XmCreateTextField(pd->from_spin, "FromYear",
1092                                             args, nargs);
1093           XtAddCallback(pd->from_year, XmNvalueChangedCallback,
1094                         spin_field_changed_cb, (XtPointer)NULL);
1095           XtManageChild(pd->from_year);
1096           XtManageChild(pd->from_spin);
1097
1098           xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1,
1099                                                   732, "To:"));
1100           pd->to_label = XtVaCreateWidget("ToLabel",
1101                 xmLabelGadgetClass,
1102                 pd->form,
1103                 XmNlabelString,         xmstr,
1104                 XmNleftAttachment,      XmATTACH_POSITION,
1105                 XmNleftPosition,        2,
1106                 XmNleftOffset,          10,
1107                 XmNtopAttachment,       XmATTACH_OPPOSITE_WIDGET,
1108                 XmNtopWidget,           pd->report_type_option,
1109                 XmNtopOffset,           0,
1110                 NULL);
1111           XmStringFree(xmstr);
1112           XtManageChild(pd->to_label);
1113
1114           nargs = 0;
1115           XtSetArg(args[nargs], XmNleftAttachment,
1116                    XmATTACH_OPPOSITE_WIDGET); nargs++;
1117           XtSetArg(args[nargs], XmNleftWidget, pd->to_label); nargs++;
1118           XtSetArg(args[nargs], XmNleftOffset, 0); nargs++;
1119           XtSetArg(args[nargs], XmNtopAttachment, XmATTACH_WIDGET); nargs++;
1120           XtSetArg(args[nargs], XmNtopWidget, pd->to_label); nargs++;
1121           XtSetArg(args[nargs], XmNtopOffset, 4); nargs++;
1122           XtSetArg(args[nargs], XmNshadowThickness, 1); nargs++;
1123           pd->to_spin = XmCreateSpinBox(pd->form, "ToSpinBox",
1124                                         args, nargs);
1125           XtAddCallback(pd->to_spin, XmNmodifyVerifyCallback,
1126                         to_modify_verify_cb, (XtPointer)c);
1127
1128           nargs = 0;
1129           XtSetArg(args[nargs], XmNspinBoxChildType, XmNUMERIC); nargs++;
1130           XtSetArg(args[nargs], XmNminimumValue, 1); nargs++;
1131           XtSetArg(args[nargs], XmNmaximumValue, 31); nargs++;
1132           XtSetArg(args[nargs], XmNcolumns, 2); nargs++;
1133           XtSetArg(args[nargs], XmNmaxLength, 2); nargs++;
1134           XtSetArg(args[nargs], XmNposition, 1); nargs++;
1135           pd->to_day = XmCreateTextField(pd->to_spin, "ToDay",
1136                                            args, nargs);
1137           XtAddCallback(pd->to_day, XmNvalueChangedCallback,
1138                         spin_field_changed_cb, (XtPointer)NULL);
1139           XtManageChild(pd->to_day);
1140
1141           nargs = 0;
1142           XtSetArg(args[nargs], XmNspinBoxChildType, XmSTRING); nargs++;
1143           XtSetArg(args[nargs], XmNnumValues, 12); nargs++;
1144           XtSetArg(args[nargs], XmNvalues, abbrevMonths); nargs++;
1145           XtSetArg(args[nargs], XmNcolumns, maxMonthLen); nargs++;
1146           XtSetArg(args[nargs], XmNmaxLength, maxMonthLen); nargs++;
1147           XtSetArg(args[nargs], XmNposition, 0); nargs++;
1148           pd->to_month = XmCreateTextField(pd->to_spin, "ToMonth",
1149                                            args, nargs);
1150           XtAddCallback(pd->to_month, XmNvalueChangedCallback,
1151                         spin_field_changed_cb, (XtPointer)NULL);
1152           XtManageChild(pd->to_month);
1153           for (i = 0; i < 12; i++)
1154             XmStringFree(abbrevMonths[i]);
1155
1156           nargs = 0;
1157           XtSetArg(args[nargs], XmNspinBoxChildType, XmNUMERIC); nargs++;
1158           XtSetArg(args[nargs], XmNminimumValue,
1159                    year(get_bot())); nargs++;
1160           XtSetArg(args[nargs], XmNmaximumValue,
1161                    year(get_eot())); nargs++;
1162           XtSetArg(args[nargs], XmNcolumns, 4); nargs++;
1163           XtSetArg(args[nargs], XmNmaxLength, 4); nargs++;
1164           XtSetArg(args[nargs], XmNposition,
1165                    year(get_bot())); nargs++;
1166           XtSetArg(args[nargs], XmNwrap, False); nargs++;
1167           pd->to_year = XmCreateTextField(pd->to_spin, "ToYear",
1168                                           args, nargs);
1169           XtAddCallback(pd->to_year, XmNvalueChangedCallback,
1170                         spin_field_changed_cb, (XtPointer)NULL);
1171           XtManageChild(pd->to_year);
1172           XtManageChild(pd->to_spin);
1173
1174           xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1,
1175                                                   679, "More..."));
1176           nargs = 0;
1177           XtSetArg(args[nargs], XmNlabelString, xmstr); nargs++;
1178           XtSetArg(args[nargs], XmNrightAttachment, XmATTACH_FORM); nargs++;
1179           XtSetArg(args[nargs], XmNrightOffset, 10); nargs++;
1180           XtSetArg(args[nargs], XmNtopAttachment, XmATTACH_WIDGET); nargs++;
1181           XtSetArg(args[nargs], XmNtopWidget, pd->to_spin); nargs++;
1182           XtSetArg(args[nargs], XmNtopOffset, 10); nargs++;
1183           pd->more_opts = XmCreatePushButtonGadget(pd->form, "MoreOpts",
1184                                                    args, nargs);
1185           XtAddCallback(pd->more_opts, XmNactivateCallback,
1186                         more_opts_cb, (XtPointer)c);
1187           XtManageChild(pd->more_opts);
1188           XmStringFree(xmstr);
1189
1190 #ifdef GR_DEBUG
1191           nargs = 0;
1192           XtSetArg(args[nargs], XmNleftAttachment, XmATTACH_FORM); nargs++;
1193           XtSetArg(args[nargs], XmNleftOffset, 10); nargs++;
1194           XtSetArg(args[nargs], XmNtopAttachment,
1195                    XmATTACH_OPPOSITE_WIDGET); nargs++;
1196           XtSetArg(args[nargs], XmNtopWidget, pd->more_opts); nargs++;
1197           XtSetArg(args[nargs], XmNtopOffset, 10); nargs++;
1198           pd->debugToggle = XmCreateToggleButtonGadget(pd->form, "Debug Mode",
1199                                                        args, nargs);
1200           XtManageChild(pd->debugToggle);
1201 #endif
1202
1203           XtManageChild(pd->form);
1204
1205           pd->setupDataValid = False;
1206           clearSetupData(pd);
1207           pd->printShell = (Widget)NULL;
1208           pd->badAllocError = False;
1209         }
1210
1211         /* Set report type and dates according to current view/day. */
1212         switch (c->view->glance) {
1213         case dayGlance : reportType = PR_DAY_VIEW; break;
1214         case weekGlance : reportType = PR_WEEK_VIEW; break;
1215         case yearGlance : reportType = PR_YEAR_VIEW; break;
1216         default:
1217         case monthGlance : reportType = PR_MONTH_VIEW; break;
1218         }
1219
1220         pd_set_report_type(c, reportType);
1221
1222         pd_set_start_date(c, c->view->date);
1223         pd_set_end_date(c, c->view->date);
1224 }
1225
1226 /*
1227  * Close dialog
1228  */
1229 static void
1230 cancel_cb(Widget w, XtPointer data, XtPointer ignore)
1231 {
1232   Calendar *c = (Calendar *)data;
1233   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
1234
1235   XtUnmanageChild(pd->pdb);
1236 }
1237
1238 static void
1239 report_error(Calendar *c, char *title, char *errText)
1240 {
1241   Props_pu *pu = (Props_pu *)c->properties_pu;
1242   char *label;
1243
1244   label = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
1245
1246   dialog_popup(c->frame,
1247                DIALOG_TITLE, title,
1248                DIALOG_TEXT, errText,
1249                BUTTON_IDENT, 1, label,
1250                DIALOG_IMAGE, pu->xm_error_pixmap,
1251                NULL);
1252
1253   XtFree(label);
1254 }
1255
1256 static void
1257 pdm_notify_cb(Widget w, XtPointer uData, XtPointer cbData)
1258 {
1259 #if 0 && defined(PRINTING_SUPPORTED)
1260   XmPrintShellCallbackStruct *cbStruct =
1261     (XmPrintShellCallbackStruct *)cbData;
1262   Calendar *c = (Calendar *)uData;
1263   char *errText = (char *)NULL;
1264   char *title;
1265
1266   switch (cbStruct->reason)
1267   {
1268   case XmCR_PDM_NONE:
1269   case XmCR_PDM_START_ERROR:
1270   case XmCR_PDM_EXIT_ERROR:
1271     errText = XtNewString(catgets(c->DT_catd, 1, 1112, pdmErrorText));
1272     break;
1273
1274   default:
1275     break;
1276   }
1277
1278   if (errText)
1279   {
1280     title = XtNewString(catgets(c->DT_catd, 1, 1111, setupErrorTitle));
1281
1282     report_error(c, title, errText);
1283
1284     XtFree(title);
1285     XtFree(errText);
1286   }
1287 #endif  /* PRINTING_SUPPORTED */
1288 }
1289
1290 /*
1291  * Called when print dialog box's print display is closed.
1292  */
1293 static void
1294 close_print_display_cb(Widget w, XtPointer uData, XtPointer cbData)
1295 {
1296   Calendar *c = (Calendar *)uData;
1297   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
1298
1299   if (pd != (_DtCmPrintData *)NULL)
1300   {
1301     /* Destroy printShell associated with Display, if any. */
1302     if (pd->printShell != (Widget)NULL)
1303     {
1304       XtDestroyWidget(pd->printShell);
1305       pd->printShell = (Widget)NULL;
1306     }
1307
1308     clearSetupData(pd);
1309   }
1310 }
1311
1312 /*
1313  * Print callback: do the deed!
1314  */
1315 static void
1316 print_cb(Widget w, XtPointer data, XtPointer cbDataP)
1317 {
1318    Calendar *c = (Calendar *)data;
1319    _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
1320    DtPrintSetupCallbackStruct *cbStruct =
1321      (DtPrintSetupCallbackStruct *)cbDataP;
1322
1323    clearSetupData(pd);
1324    DtPrintCopySetupData(&pd->setupData, cbStruct->print_data);
1325    pd->setupDataValid = True;
1326
1327    _DtTurnOnHourGlass(c->frame);
1328    print_report(c);
1329    _DtTurnOffHourGlass(c->frame);
1330
1331    /* Leave setupDataValid=True for quick print! */
1332 }
1333
1334 static void
1335 print_setup_cb(Widget w, XtPointer uData, XtPointer cbData)
1336 {
1337 #if 0 && defined(PRINTING_SUPPORTED)
1338   Calendar *c = (Calendar *)uData;
1339   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
1340   DtPrintSetupCallbackStruct *cbStruct =
1341     (DtPrintSetupCallbackStruct *)cbData;
1342
1343   clearSetupData(pd);
1344   DtPrintCopySetupData(&pd->setupData, cbStruct->print_data);
1345   pd->setupDataValid = True;
1346
1347 #ifdef GR_DEBUG
1348   /* Force debug mode off. */
1349   if (inDebugMode(c))
1350     XmToggleButtonGadgetSetState(pd->debugToggle, False, False);
1351 #endif
1352
1353   createPrintShell(c);
1354
1355   if (XmPrintPopupPDM(pd->printShell, w) != XmPDM_NOTIFY_SUCCESS)
1356   {
1357     char *errText = XtNewString(catgets(c->DT_catd, 1, 1112,
1358                                         pdmErrorText));
1359     char *title = XtNewString(catgets(c->DT_catd, 1, 1111, setupErrorTitle));
1360
1361     report_error(c, title, errText);
1362
1363     XtFree(title);
1364     XtFree(errText);
1365   }
1366
1367   clearSetupData(pd);
1368 #endif  /* PRINTING_SUPPORTED */
1369 }
1370
1371 /*
1372  * print_report: dispatch the view-specific output routine
1373  */
1374 void
1375 print_report(Calendar *c)
1376 {
1377   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
1378   Props         *p = (Props *) c->properties;
1379   Props_pu      *pu = (Props_pu *) c->properties_pu;
1380   int           r = pd_get_report_type(c);
1381   OrderingType  ot = get_int_prop(p, CP_DATEORDERING);
1382   SeparatorType st = get_int_prop(p, CP_DATESEPARATOR);
1383   Tick          start_date = pd_get_start_date(c);
1384   Tick          end_date = pd_get_end_date(c);
1385   char *text = (char *)NULL;
1386
1387   if ((start_date == DATE_BBOT) || (end_date == DATE_BBOT) || 
1388       (start_date == DATE_AEOT) || (end_date == DATE_BBOT))
1389   {
1390     text = XtNewString(catgets(c->DT_catd, 1, 892,
1391         "The dates for printing must be between 1969 and 2038."));
1392   }
1393   else if (start_date <= 0)
1394   {
1395     text = XtNewString(catgets(c->DT_catd, 1, 894,
1396                                "Malformed \"From\" date"));
1397   }
1398   else if (end_date <= 0)
1399   {
1400     text = XtNewString(catgets(c->DT_catd, 1, 896,
1401                                "Malformed \"To\" date"));
1402   }
1403   else if (start_date > end_date)
1404   {
1405     text = XtNewString(catgets(c->DT_catd, 1, 898,
1406 "The \"To\" date for printing must be after the \"From\" date for printing"));
1407   }
1408
1409   if (text)
1410   {
1411     char *title = XtNewString(catgets(c->DT_catd, 1, 736, printErrorTitle));
1412
1413     report_error(c, title, text);
1414
1415     XtFree(text);
1416     XtFree(title);
1417     return;
1418   }
1419
1420   if (pd == (_DtCmPrintData *)NULL)
1421     return;
1422
1423   if (!pd->setupDataValid)
1424   {
1425     if (DtPrintFillSetupData(pd->pdb, &pd->setupData) != DtPRINT_SUCCESS)
1426     {
1427       /*
1428        * NOTE: DtPrintFillSetupData() displays an error dialog if
1429        * it is unsuccessful; no need to display our own.
1430        */
1431       return;
1432     }
1433
1434     pd->setupDataValid = True;
1435   }
1436
1437   if (XtIsManaged(pd->pdb))
1438     _DtTurnOnHourGlass(XtParent(pd->pdb));
1439
1440   createPrintShell(c);
1441
1442   switch(r)
1443   {
1444   case PR_YEAR_VIEW:
1445     print_std_year_range(year(start_date), year(end_date));
1446     break;
1447   default:
1448   case PR_MONTH_VIEW:
1449     print_month_range(c, start_date, end_date);
1450     break;
1451   case PR_WEEK_VIEW:
1452     print_week_range(c, start_date, end_date);
1453     break;
1454   case PR_DAY_VIEW:
1455     print_day_range(c, start_date, end_date);
1456     break;
1457   case PR_APPT_LIST:
1458     x_print_list_range(c, CSA_TYPE_EVENT, (int) c->view->glance,
1459                        start_date, end_date);
1460     break;
1461   case PR_TODO_LIST:
1462     x_print_list_range(c, CSA_TYPE_TODO, (int) VIEW_ALL,
1463                        start_date, end_date);
1464     break;
1465   }
1466
1467 #ifdef GR_DEBUG
1468   if (inDebugMode(c))
1469   {
1470     XtDestroyWidget(pd->printShell);
1471     pd->printShell = (Widget)NULL;
1472   }
1473 #endif
1474
1475   if (XtIsManaged(pd->pdb))
1476   {
1477     _DtTurnOffHourGlass(XtParent(pd->pdb));
1478     XtUnmanageChild(pd->pdb);
1479   }
1480
1481   /* Keep setupDataValid=True for future QuickPrint operations. */
1482 }
1483
1484 /*
1485  * report_option_cb
1486  *
1487  * callback for report-type option menu.
1488  * Here we just store the button number of the selected
1489  * button in the print_data structure, to make life easy
1490  * when the print callback is invoked.
1491  */
1492 static void
1493 report_option_cb(Widget w, XtPointer client_data, XtPointer call_data)
1494 {
1495   int choice = (int) (intptr_t) client_data;
1496   Calendar *c = calendar;
1497
1498   pd_set_report_managed(c, choice);
1499
1500   pd_set_start_date(c, pd_get_start_date(c));
1501   pd_set_end_date(c, pd_get_end_date(c));
1502 }
1503
1504 char *
1505 pd_get_printer_name(Calendar *c)
1506 {
1507   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
1508
1509   if ((pd == (_DtCmPrintData *)NULL) ||
1510       (!pd->setupDataValid) ||
1511       pd_print_to_file(c))
1512     return (char *)NULL;
1513
1514   return pd->setupData.printer_name ?
1515     XtNewString(pd->setupData.printer_name) : (char *)NULL;
1516 }
1517
1518 int
1519 pd_get_copies(Calendar *c)
1520 {
1521   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
1522   int nCopies = 0;
1523
1524   if (pd == (_DtCmPrintData *)NULL)
1525     return 0;
1526
1527   XtVaGetValues(pd->pdb, DtNcopies, &nCopies, NULL);
1528   return nCopies;
1529 }
1530
1531 Tick
1532 pd_get_start_date(Calendar *c)
1533 {
1534   int dayPos, monthPos, yearPos;
1535
1536   if (!pd_get_start_positions(c, &monthPos, &dayPos, &yearPos))
1537     return 0;
1538
1539   return monthdayyear(monthPos + 1, dayPos, yearPos);
1540 }
1541
1542 Tick
1543 pd_get_end_date(Calendar *c)
1544 {
1545   int dayPos, monthPos, yearPos;
1546
1547   if (!pd_get_end_positions(c, &monthPos, &dayPos, &yearPos))
1548     return 0;
1549
1550   return monthdayyear(monthPos + 1, dayPos, yearPos);
1551 }
1552
1553 char *
1554 pd_get_print_options(Calendar *c)
1555 {
1556   return XtNewString("");
1557 }
1558
1559 Boolean
1560 pd_print_to_file(Calendar *c)
1561 {
1562   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
1563
1564   if ((pd == (_DtCmPrintData *)NULL) ||
1565       (!pd->setupDataValid))
1566     return False;
1567
1568   return pd->setupData.destination == DtPRINT_TO_FILE;
1569 }
1570
1571 char *
1572 pd_get_file_name(Calendar *c)
1573 {
1574   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
1575
1576   if ((pd == (_DtCmPrintData *)NULL) ||
1577       (!pd->setupDataValid) ||
1578       !pd_print_to_file(c))
1579     return (char *)NULL;
1580
1581   return pd->setupData.dest_info ?
1582     XtNewString(pd->setupData.dest_info) : (char *)NULL;
1583 }
1584
1585 int
1586 pd_get_report_type(Calendar *c)
1587 {
1588   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
1589
1590   if (pd == (_DtCmPrintData *)NULL)
1591     return PR_MONTH_VIEW;
1592
1593   return pd->report_type;
1594 }
1595
1596 Widget
1597 pd_get_print_shell(Calendar *c)
1598 {
1599   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
1600
1601   if (pd == (_DtCmPrintData *)NULL)
1602     return (Widget)NULL;
1603
1604   return pd->printShell;
1605 }
1606
1607 Display *
1608 pd_get_print_display(Calendar *c)
1609 {
1610   Widget printShell = pd_get_print_shell(c);
1611
1612   if (printShell == (Widget)NULL)
1613       return (Display *)NULL;
1614
1615   return XtDisplay(printShell);
1616 }
1617
1618 void
1619 pd_set_bad_alloc_error(Calendar *c, Boolean errorOn)
1620 {
1621   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
1622
1623   if (pd != (_DtCmPrintData *)NULL)
1624       pd->badAllocError = errorOn;
1625 }
1626
1627 Boolean
1628 pd_get_bad_alloc_error(Calendar *c)
1629 {
1630   _DtCmPrintData *pd = (_DtCmPrintData *)c->print_data;
1631
1632   if (pd != (_DtCmPrintData *)NULL)
1633       return pd->badAllocError;
1634       
1635   return False;
1636 }