Merge branch 'linux1'
[oweals/cde.git] / cde / programs / dtcm / dtcm / x_graphics.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 librararies 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: x_graphics.c /main/15 1996/11/25 10:29:30 rswiston $ */
24 /*
25  * (c) Copyright 1996 Digital Equipment Corporation.
26  * (c) Copyright 1996 Hewlett-Packard Company.
27  * (c) Copyright 1996 International Business Machines Corp.
28  * (c) Copyright 1996 Sun Microsystems, Inc.
29  * (c) Copyright 1996 Novell, Inc. 
30  * (c) Copyright 1996 FUJITSU LIMITED.
31  * (c) Copyright 1996 Hitachi.
32  */
33
34 #include <EUSCompat.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <limits.h>
38 #include <ctype.h>
39 #include <locale.h>
40 #ifdef SVR4
41 #include <unistd.h>
42 #endif /* SVR4 */
43 #include <sys/stat.h>
44 #include <sys/param.h>
45 #include "util.h"
46 #include "calendar.h"
47 #include "timeops.h"
48 #include "datefield.h"
49 #include "props.h"
50 #include "props_pu.h"
51 #include "x_graphics.h"
52 #include "todo.h"
53 #include "cm_i18n.h"
54 #include "dayglance.h"
55 #include "format.h"
56 #include "deskset.h"
57 #include "print.h"
58
59 #include <X11/Intrinsic.h>
60 #include <X11/extensions/Print.h>
61
62 #include <Xm/Xm.h>
63 #include <Xm/DialogS.h>
64 #include <Xm/DrawingA.h>
65 #include <Xm/Print.h>
66
67 #define XOS_USE_XT_LOCKING
68 #define X_INCLUDE_TIME_H
69 #if defined(linux)
70 #undef SVR4
71 #endif
72 #include <X11/Xos_r.h>
73
74 /*
75  *  There is currently a defect in the X Print Server which
76  *  causes the print shell to be created with dimensions 1x1
77  *  instead of the dimensions appropriate to the X Print Server.
78  *  Until this is corrected, defining SHELL_SIZE_BUG will
79  *  cause dtcm to size the print shell to 8.5"x11.0".
80  */
81 #define SHELL_SIZE_BUG 1
82
83 #define BUFFERSIZE 512
84 #define DAYS_IN_WEEK 7
85 #define WEEK_DAYS 5
86 #define WEEKEND_DAYS 2
87 #define INTERVALS_PER_DAY 96 /* 4 15-minute intervals per hour * 24 hours */
88
89 #define VMARGIN(gInfo) (2 * gInfo->normalWd)
90 #define HMARGIN(gInfo) (4 * gInfo->normalWd)
91 #define TODO_HINDENT 10
92 #define TODO_VINDENT 10
93
94 /* Day View fonts */
95 enum
96 {
97   DV_TITLE_FONT = 0,
98   DV_HEADER_FONT,
99   DV_APPT_FONT,
100   DV_TIME_FONT,
101   DV_NUM_FONTS
102 };
103 static String dvFonts[DV_NUM_FONTS];
104
105 /* Week View fonts */
106 enum
107 {
108   WV_TITLE_FONT = 0,
109   WV_HEADER_FONT,
110   WV_APPT_FONT,
111   WV_DAY_FONT,
112   WV_BOX_FONT,
113   WV_NUM_FONTS
114 };
115 static String wvFonts[WV_NUM_FONTS];
116
117 /* Month View fonts */
118 enum
119 {
120   MV_TITLE_FONT = 0,
121   MV_HEADER_FONT,
122   MV_APPT_FONT,
123   MV_DAY_FONT,
124   MV_DATE_FONT,
125   MV_TINY_TITLE_FONT,
126   MV_TINY_DAY_FONT,
127   MV_TINY_DATE_FONT,
128   MV_NUM_FONTS
129 };
130 static String mvFonts[MV_NUM_FONTS];
131
132 /* Year View fonts */
133 enum
134 {
135   YV_TITLE_FONT = 0,
136   YV_HEADER_FONT,
137   YV_TINY_TITLE_FONT,
138   YV_TINY_DAY_FONT,
139   YV_TINY_DATE_FONT,
140   YV_NUM_FONTS
141 };
142 static String yvFonts[YV_NUM_FONTS];
143
144 /* Appt View fonts */
145 enum
146 {
147   AV_TITLE_FONT = 0,
148   AV_HEADER_FONT,
149   AV_APPT_FONT,
150   AV_ITEM_FONT,
151   AV_TINY_TITLE_FONT,
152   AV_TINY_DAY_FONT,
153   AV_TINY_DATE_FONT,
154   AV_NUM_FONTS
155 };
156 static String avFonts[AV_NUM_FONTS];
157
158 /* ToDo View fonts */
159 enum
160 {
161   TV_TITLE_FONT = 0,
162   TV_HEADER_FONT,
163   TV_APPT_FONT,
164   TV_ITEM_FONT,
165   TV_TINY_TITLE_FONT,
166   TV_TINY_DAY_FONT,
167   TV_TINY_DATE_FONT,
168   TV_NUM_FONTS
169 };
170 static String tvFonts[TV_NUM_FONTS];
171
172 #ifdef GR_DEBUG
173 typedef struct _PrintResources
174 {
175   Pixel lightGrayPixel;
176   Pixel darkGrayPixel;
177 } PrintResources;
178 #endif
179
180 /*
181  *  Unfortunately, the dt-application fonts don't support all the point
182  *  sizes we'd like.  We use the closest approximation.
183  */
184 #ifdef GR_DEBUG
185 static char bold40PtFont[] =
186   "-*-times-bold-r-normal-*-0-[80 0 0 40]-0-0-p-0-*-*:";
187 static char bold30PtFont[] =
188   "-*-times-bold-r-normal-*-0-300-0-0-p-0-*-*:";
189 static char bold20PtFont[] =
190   "-*-times-bold-r-normal-*-0-200-0-0-p-0-*-*:";
191 static char bold16PtFont[] =
192   "-*-times-bold-r-normal-*-0-160-0-0-p-0-*-*:";
193 static char bold14PtFont[] =
194   "-*-times-bold-r-normal-*-0-140-0-0-p-0-*-*:";
195 static char bold12PtFont[] =
196   "-*-times-bold-r-normal-*-0-120-0-0-p-0-*-*:";
197 static char bold10PtFont[] =
198   "-*-times-bold-r-normal-*-0-100-0-0-p-0-*-*:";
199 static char bold9PtFont[] =
200   "-*-times-bold-r-normal-*-0-90-0-0-p-0-*-*:";
201 static char bold7PtFont[] =
202   "-*-times-bold-r-normal-*-0-70-0-0-p-0-*-*:";
203
204 static char helv10PtFont[] =
205   "-*-helvetica-medium-r-normal-*-0-100-0-0-p-0-*-*:";
206 static char helv9PtFont[] =
207   "-*-helvetica-medium-r-normal-*-0-90-0-0-p-0-*-*:";
208 static char helv8PtFont[] =
209   "-*-helvetica-medium-r-normal-*-0-80-0-0-p-0-*-*:";
210
211 static char cour12PtFont[] =
212   "-*-courier-medium-r-normal-*-0-120-0-0-m-0-*-*:";
213 static char cour7PtFont[] =
214   "-*-courier-medium-r-normal-*-0-70-0-0-m-0-*-*:";
215 #else
216 static char bold40PtFont[] =
217   "-dt-application-bold-r-normal-serif-0-[80 0 0 40]-0-0-p-0-*-*:";
218 static char bold30PtFont[] =
219   "-dt-application-bold-r-normal-serif-0-300-0-0-p-0-*-*:";
220 static char bold20PtFont[] =
221   "-dt-application-bold-r-normal-serif-0-200-0-0-p-0-*-*:";
222 static char bold16PtFont[] =
223   "-dt-application-bold-r-normal-serif-0-160-0-0-p-0-*-*:";
224 static char bold14PtFont[] =
225   "-dt-application-bold-r-normal-serif-0-140-0-0-p-0-*-*:";
226 static char bold12PtFont[] =
227   "-dt-application-bold-r-normal-serif-0-120-0-0-p-0-*-*:";
228 static char bold10PtFont[] =
229   "-dt-application-bold-r-normal-serif-0-100-0-0-p-0-*-*:";
230 static char bold9PtFont[] =
231   "-dt-application-bold-r-normal-serif-0-90-0-0-p-0-*-*:";
232 static char bold7PtFont[] =
233   "-dt-application-bold-r-normal-serif-0-70-0-0-p-0-*-*:";
234
235 static char helv10PtFont[] =
236   "-dt-application-medium-r-normal-sans-0-100-0-0-p-0-*-*:";
237 static char helv9PtFont[] =
238   "-dt-application-medium-r-normal-sans-0-90-0-0-p-0-*-*:";
239 static char helv8PtFont[] =
240   "-dt-application-medium-r-normal-sans-0-80-0-0-p-0-*-*:";
241
242 static char cour12PtFont[] =
243   "-dt-application-medium-r-normal-serif-0-120-0-0-m-0-*-*:";
244 static char cour7PtFont[] =
245   "-dt-application-medium-r-normal-serif-0-70-0-0-m-0-*-*:";
246 #endif
247
248 static XtResource dvDefaultResources[] =
249 {
250   {"dvpTitleFont", "PrintTitleFont", XmRString, sizeof(String),
251      sizeof(String) * DV_TITLE_FONT, XmRImmediate,
252      (XtPointer)bold16PtFont},
253   {"dvpHeaderFont", "PrintHeaderFont", XmRString, sizeof(String),
254      sizeof(String) * DV_HEADER_FONT, XmRImmediate,
255      (XtPointer)bold9PtFont},
256   {"dvpApptFont", "PrintApptFont", XmRString, sizeof(String),
257      sizeof(String) * DV_APPT_FONT, XmRImmediate,
258      (XtPointer)helv10PtFont},
259   {"dvpTimeFont", "PrintTimeFont", XmRString, sizeof(String),
260      sizeof(String) * DV_TIME_FONT, XmRImmediate,
261      (XtPointer)bold10PtFont}
262 };
263
264 static XtResource wvDefaultResources[] =
265 {
266   {"wvpTitleFont", "PrintTitleFont", XmRString, sizeof(String),
267      sizeof(String) * WV_TITLE_FONT, XmRImmediate,
268      (XtPointer)bold16PtFont},
269   {"wvpHeaderFont", "PrintHeaderFont", XmRString, sizeof(String),
270      sizeof(String) * WV_HEADER_FONT, XmRImmediate,
271      (XtPointer)bold9PtFont},
272   {"wvpApptFont", "PrintApptFont", XmRString, sizeof(String),
273      sizeof(String) * WV_APPT_FONT, XmRImmediate,
274      (XtPointer)helv9PtFont},
275   {"wvpDayFont", "PrintDayFont", XmRString, sizeof(String),
276      sizeof(String) * WV_DAY_FONT, XmRImmediate,
277      (XtPointer)bold12PtFont},
278   {"wvpBoxFont", "PrintBoxFont", XmRString, sizeof(String),
279      sizeof(String) * WV_BOX_FONT, XmRImmediate,
280      (XtPointer)bold12PtFont}
281 };
282
283 static XtResource mvDefaultResources[] =
284 {
285   {"mvpTitleFont", "PrintTitleFont", XmRString, sizeof(String),
286      sizeof(String) * MV_TITLE_FONT, XmRImmediate,
287      (XtPointer)bold30PtFont},
288   {"mvpHeaderFont", "PrintHeaderFont", XmRString, sizeof(String),
289      sizeof(String) * MV_HEADER_FONT, XmRImmediate,
290      (XtPointer)bold9PtFont},
291   {"mvpApptFont", "PrintApptFont", XmRString, sizeof(String),
292      sizeof(String) * MV_APPT_FONT, XmRImmediate,
293      (XtPointer)helv8PtFont},
294   {"mvpDayFont", "PrintDayFont", XmRString, sizeof(String),
295      sizeof(String) * MV_DAY_FONT, XmRImmediate,
296      (XtPointer)bold14PtFont},
297   {"mvpDateFont", "PrintDateFont", XmRString, sizeof(String),
298      sizeof(String) * MV_DATE_FONT, XmRImmediate,
299      (XtPointer)bold20PtFont},
300   {"mvpTinyTitleFont", "PrintTinyTitleFont", XmRString, sizeof(String),
301      sizeof(String) * MV_TINY_TITLE_FONT, XmRImmediate,
302      (XtPointer)bold10PtFont},
303   {"mvpTinyDayFont", "PrintTinyDayFont", XmRString, sizeof(String),
304      sizeof(String) * MV_TINY_DAY_FONT, XmRImmediate,
305      (XtPointer)cour7PtFont},
306   {"mvpTinyDateFont", "PrintTinyDateFont", XmRString, sizeof(String),
307      sizeof(String) * MV_TINY_DATE_FONT, XmRImmediate,
308      (XtPointer)bold7PtFont}
309 };
310
311 static XtResource yvDefaultResources[] =
312 {
313   {"yvpTitleFont", "PrintTitleFont", XmRString, sizeof(String),
314      sizeof(String) * YV_TITLE_FONT, XmRImmediate,
315      (XtPointer)bold40PtFont},
316   {"yvpHeaderFont", "PrintHeaderFont", XmRString, sizeof(String),
317      sizeof(String) * YV_HEADER_FONT, XmRImmediate,
318      (XtPointer)bold9PtFont},
319   {"yvpTinyTitleFont", "PrintTinyTitleFont", XmRString, sizeof(String),
320      sizeof(String) * YV_TINY_TITLE_FONT, XmRImmediate,
321      (XtPointer)bold16PtFont},
322   {"yvpTinyDayFont", "PrintTinyDayFont", XmRString, sizeof(String),
323      sizeof(String) * YV_TINY_DAY_FONT, XmRImmediate,
324      (XtPointer)cour12PtFont},
325   {"yvpTinyDateFont", "PrintTinyDateFont", XmRString, sizeof(String),
326      sizeof(String) * YV_TINY_DATE_FONT, XmRImmediate,
327      (XtPointer)bold12PtFont}
328 };
329
330 static XtResource avDefaultResources[] =
331 {
332   {"avpTitleFont", "PrintTitleFont", XmRString, sizeof(String),
333      sizeof(String) * AV_TITLE_FONT, XmRImmediate,
334      (XtPointer)bold16PtFont},
335   {"avpHeaderFont", "PrintHeaderFont", XmRString, sizeof(String),
336      sizeof(String) * AV_HEADER_FONT, XmRImmediate,
337      (XtPointer)bold9PtFont},
338   {"avpApptFont", "PrintApptFont", XmRString, sizeof(String),
339      sizeof(String) * AV_APPT_FONT, XmRImmediate,
340      (XtPointer)helv10PtFont},
341   {"avpItemFont", "PrintItemFont", XmRString, sizeof(String),
342      sizeof(String) * AV_ITEM_FONT, XmRImmediate,
343      (XtPointer)bold10PtFont},
344   {"avpTinyTitleFont", "PrintTinyTitleFont", XmRString, sizeof(String),
345      sizeof(String) * AV_TINY_TITLE_FONT, XmRImmediate,
346      (XtPointer)bold16PtFont},
347   {"avpTinyDayFont", "PrintTinyDayFont", XmRString, sizeof(String),
348      sizeof(String) * AV_TINY_DAY_FONT, XmRImmediate,
349      (XtPointer)cour12PtFont},
350   {"avpTinyDateFont", "PrintTinyDateFont", XmRString, sizeof(String),
351      sizeof(String) * AV_TINY_DATE_FONT, XmRImmediate,
352      (XtPointer)bold12PtFont}
353 };
354
355 static XtResource tvDefaultResources[] =
356 {
357   {"tvpTitleFont", "PrintTitleFont", XmRString, sizeof(String),
358      sizeof(String) * TV_TITLE_FONT, XmRImmediate,
359      (XtPointer)bold16PtFont},
360   {"tvpHeaderFont", "PrintHeaderFont", XmRString, sizeof(String),
361      sizeof(String) * TV_HEADER_FONT, XmRImmediate,
362      (XtPointer)bold9PtFont},
363   {"tvpApptFont", "PrintApptFont", XmRString, sizeof(String),
364      sizeof(String) * TV_APPT_FONT, XmRImmediate,
365      (XtPointer)helv10PtFont},
366   {"tvpItemFont", "PrintItemFont", XmRString, sizeof(String),
367      sizeof(String) * TV_ITEM_FONT, XmRImmediate,
368      (XtPointer)bold10PtFont},
369   {"tvpTinyTitleFont", "PrintTinyTitleFont", XmRString, sizeof(String),
370      sizeof(String) * TV_TINY_TITLE_FONT, XmRImmediate,
371      (XtPointer)bold16PtFont},
372   {"tvpTinyDayFont", "PrintTinyDayFont", XmRString, sizeof(String),
373      sizeof(String) * TV_TINY_DAY_FONT, XmRImmediate,
374      (XtPointer)cour12PtFont},
375   {"tvpTinyDateFont", "PrintTinyDateFont", XmRString, sizeof(String),
376      sizeof(String) * TV_TINY_DATE_FONT, XmRImmediate,
377      (XtPointer)bold12PtFont}
378 };
379
380 #ifdef GR_DEBUG
381 static XtResource displayResources[] =
382 {
383   {"lightGrayPixel", "LightGrayPixel", XmRPixel, sizeof(Pixel),
384      XtOffsetOf(PrintResources, lightGrayPixel), XmRString,
385      "yellow"},
386   {"darkGrayPixel", "DarkGrayPixel", XmRPixel, sizeof(Pixel),
387      XtOffsetOf(PrintResources, darkGrayPixel), XmRString,
388      "red"}
389 };
390
391 static PrintResources printResources;
392 #endif
393
394 typedef int CMFontEnum;
395
396 enum {
397   LEFT_AT_X = 1,
398   CENTER_AT_X = 2,
399   RIGHT_AT_X = 4,
400   TOP_AT_Y = 8,
401   CENTER_AT_Y = 16,
402   BOTTOM_AT_Y = 32
403 };
404
405 typedef struct _CMFontInfo
406 {
407   CMFontEnum fontEnum;
408   XmFontList fontList;
409 } CMFontInfo;
410
411 typedef struct _CMDayInfo
412 {
413   int curX1, curY1;
414   int curX2, curY2;
415   int tab1;
416   int boxHt;
417   int boxWd;
418   int line1;
419 } CMDayInfo;
420
421 typedef struct _CMToDoInfo
422 {
423   int outerX1, outerY1;
424   int innerX1, innerY1;
425   int innerX2, innerY2;
426   int outerX2, outerY2;
427   int boxX1, boxY1;
428   int boxX2, boxY2;
429   int lineX, lineY;
430 } CMToDoInfo;
431
432 typedef struct _CMWeekInfo
433 {
434   int curX1, curY1;
435   int curX2, curY2;
436   int tab1;
437   int boxHt;
438   int boxWd;
439   int lineX;
440   int lineY;
441   int lineMaxY;
442   int schedBoxX1, schedBoxY1;
443   int schedBoxX2, schedBoxY2;
444   char schedBucket[INTERVALS_PER_DAY];
445 } CMWeekInfo;
446
447 typedef struct _CMMonthInfo
448 {
449   int curX1, curY1;
450   int boxWd, boxHt;
451   int tab1;
452   int nRows;
453   int lineX, lineY;
454   int lastX;
455   int lineMaxX, lineMaxY;
456 } CMMonthInfo;
457
458 typedef struct _CMGraphicsInfo
459 {
460   Widget drawingArea;
461   GC gc;
462   Calendar *c;
463   int reportType;
464
465   char timestamp[BUFFERSIZE];
466   Boolean reverseVideo;
467   Pixel fg, bg;
468   Pixmap lightPixmap, darkPixmap;
469
470   double hscale;
471   double vscale;
472
473   /* Scaled line thicknesses */
474   int thinWd;
475   int normalWd;
476   int thickWd;
477
478   int leftMarginX;
479   int rightMarginX;
480   int topMarginY;
481   int bottomMarginY;
482
483   CMFontInfo *fontInfo;
484   int nFonts;
485   CMFontInfo *curFont;
486
487   union
488   {
489       CMDayInfo dayInfo;
490       CMToDoInfo toDoInfo;
491       CMWeekInfo weekInfo;
492       CMMonthInfo monthInfo;
493   } u;
494
495 } CMGraphicsInfo;
496
497 static void local_dayname(Calendar *, char **, int);
498 static void local_dayname3(Calendar *, char **, int);
499 static char *get_report_type_string(CMGraphicsInfo *);
500 static void filePrintDoneCB(Display *, XPContext, XPGetDocStatus,
501                             XPointer);
502 static void filePrintReportStatus(Calendar *, Boolean);
503 static void showBadAllocError(Calendar *);
504
505 /* X Graphics stuff. */
506 static void x_print_string(CMGraphicsInfo *, char *, int, int, int);
507 static void x_fill_light_box(CMGraphicsInfo *, int, int, int, int, int);
508 static void x_fill_dark_box(CMGraphicsInfo *, int, int, int, int, int);
509 static void x_fill_black_box(CMGraphicsInfo *, int, int, int, int);
510 static void x_fill_box(CMGraphicsInfo *, int, int, int, int, Pixmap, int);
511 static void x_draw_box(CMGraphicsInfo *, int, int, int, int, int);
512 static void x_draw_line(CMGraphicsInfo *, int, int, int, int, int);
513 static void x_set_clip_box(CMGraphicsInfo *, int, int, int, int);
514 static void x_unset_clip_box(CMGraphicsInfo *);
515
516 /* X Font stuff. */
517 static Boolean x_load_font(CMGraphicsInfo *, CMFontInfo *, char *);
518
519 /* CM Font stuff. */
520 static Boolean cm_load_font(CMGraphicsInfo *, CMFontEnum, char *);
521 static void cm_load_font_error(CMGraphicsInfo *, char *);
522 static void cm_release_fonts(CMGraphicsInfo *);
523 static Boolean cm_set_font(CMGraphicsInfo *, CMFontEnum);
524 static CMFontInfo *cm_find_font(CMGraphicsInfo *, CMFontEnum);
525 static void cm_font_extents(CMGraphicsInfo *, CMFontInfo *, int *, int *);
526 static int cm_font_height(CMGraphicsInfo *, CMFontInfo *);
527 static int cm_font_width(CMGraphicsInfo *, CMFontInfo *);
528 static int cm_string_width(CMGraphicsInfo *, CMFontInfo *, char *);
529 static void cm_reverse_video(CMGraphicsInfo *, Boolean);
530
531 static CMFontEnum cm_get_title_enum(CMGraphicsInfo *);
532 static CMFontEnum cm_get_header_enum(CMGraphicsInfo *);
533 static CMFontEnum cm_get_tiny_title_enum(CMGraphicsInfo *);
534 static CMFontEnum cm_get_tiny_day_enum(CMGraphicsInfo *);
535 static CMFontEnum cm_get_tiny_date_enum(CMGraphicsInfo *);
536 static void cm_adjust_margins(CMGraphicsInfo *);
537 static int cm_cvt_margin(CMGraphicsInfo *, Props_op, int);
538 static void cm_print_header_string(CMGraphicsInfo *, Props_op,
539                                    char *, char *,
540                                    char *, char *);
541
542 /* Day/Week View stuff */
543 static void cm_print_time(CMGraphicsInfo *, char *, Glance);
544 static void cm_print_appt_text(CMGraphicsInfo *, char *, int, Glance);
545 static void cm_print_text(CMGraphicsInfo *, char *, int, Glance);
546 static void cm_week_sched_update(CMGraphicsInfo *,
547                                  Dtcm_appointment *, Props *);
548 static int cm_week_sched_box_indent(CMGraphicsInfo *);
549
550 /* ToDo/Appt. View stuff */
551 static void cm_set_todo_text_clipping(CMGraphicsInfo *);
552 static void cm_unset_todo_text_clipping(CMGraphicsInfo *);
553 static void cm_print_todo_text(CMGraphicsInfo *, char *, CSA_sint32,
554                                CSA_sint32, int);
555 static int cm_tiny_month_height(CMGraphicsInfo *, int);
556 static void cm_print_todo_months(CMGraphicsInfo *, time_t);
557 static int cm_count_appts(CMGraphicsInfo *, CSA_entry_handle *,
558                           int, CSA_sint32, int);
559 static void cm_get_todo_lines_per_page(CMGraphicsInfo *, CSA_sint32,
560                                        int *, int *);
561 static void cm_todo_outline(CMGraphicsInfo *, Boolean);
562
563 /* Month View stuff */
564 static void cm_print_month_time(CMGraphicsInfo *, char *);
565 static void cm_print_month_text(CMGraphicsInfo *, char *, int);
566 static void cm_std_month_dates(CMGraphicsInfo *, int, int, int,
567                                int, int, int, int);
568 static void cm_std_month_weekdays(CMGraphicsInfo *, int, int, int, int);
569
570 #ifdef GR_DEBUG
571 static void tmpFn(Widget, XtPointer, XtPointer);
572 static void tmpSpin(Widget);
573 static Boolean tmpFlag;
574
575 static void
576 tmpSpin(Widget w)
577 {
578   XEvent event;
579   XtAppContext appContext;
580
581   tmpFlag = False;
582   appContext = XtWidgetToApplicationContext(w);
583   while (!tmpFlag)
584   {
585     XtAppNextEvent(appContext, &event);
586     XtDispatchEvent(&event);
587   }
588 }
589
590 static void
591 tmpFn(Widget w, XtPointer uData, XtPointer cbData)
592 {
593   XmDrawingAreaCallbackStruct *cbStruct =
594     (XmDrawingAreaCallbackStruct *)cbData;
595
596   if (cbStruct->reason == XmCR_EXPOSE)
597   {
598     if (cbStruct->event->xexpose.count != 0)
599       return;
600   }
601   else
602   {
603     if (cbStruct->event->type != ButtonPress)
604       return;
605   }
606
607   tmpFlag = True;
608 }
609 #endif
610
611 static void
612 x_print_string(CMGraphicsInfo *gInfo, char *str, int x, int y, int flags)
613 {
614   Widget w = gInfo->drawingArea;
615   GC gc = gInfo->gc;
616   XmFontList fontList = (XmFontList)NULL;
617   XmString xmString;
618   Dimension textWd, textHt;
619   int textX, textY;
620   int xFlags, yFlags;
621   XmStringDirection xmStringDirection;
622   Arg args[10];
623   int nargs;
624
625   nargs = 0;
626   XtSetArg(args[nargs], XmNstringDirection, &xmStringDirection); nargs++;
627   XtGetValues(w, args, nargs);
628
629   if ((gInfo->nFonts == 0) ||
630       (gInfo->curFont == (CMFontInfo *)NULL))
631   {
632     nargs = 0;
633     XtSetArg(args[nargs], XmNlabelFontList, &fontList); nargs++;
634     XtGetValues(XtParent(w), args, nargs);
635   }
636   else
637   {
638     fontList = gInfo->curFont->fontList;
639   }
640
641   xmString = XmStringCreateLocalized(str);
642   XmStringExtent(fontList, xmString, &textWd, &textHt);
643
644   xFlags = (flags & (LEFT_AT_X | CENTER_AT_X | RIGHT_AT_X));
645   yFlags = (flags & (TOP_AT_Y | CENTER_AT_Y | BOTTOM_AT_Y));
646
647   switch (xFlags)
648   {
649   default:
650   case LEFT_AT_X:
651     textX = x;
652     break;
653
654   case CENTER_AT_X:
655     textX = x - (textWd/2);
656     break;
657
658   case RIGHT_AT_X:
659     textX = x - textWd + 1;
660     break;
661   }
662   if (xmStringDirection == XmSTRING_DIRECTION_R_TO_L)
663     textX += textWd;
664
665   switch (yFlags)
666   {
667   default:
668   case TOP_AT_Y:
669     textY = y;
670     break;
671
672   case CENTER_AT_Y:
673     textY = y - (textHt/2);
674     break;
675
676   case BOTTOM_AT_Y:
677     textY = y - textHt;
678     break;
679   }
680
681   XSetForeground(XtDisplay(w), gc, gInfo->fg);
682   XmStringDraw(XtDisplay(w), XtWindow(w), fontList, xmString,
683                gc, textX, textY, textWd, XmALIGNMENT_BEGINNING,
684                xmStringDirection, NULL);
685   XmStringFree(xmString);
686 }
687
688 static void
689 x_fill_light_box(CMGraphicsInfo *gInfo, int x1, int y1, int x2, int y2,
690                  int lineWidth)
691 {
692 #ifdef GR_DEBUG
693   Widget w = gInfo->drawingArea;
694   GC gc = gInfo->gc;
695   int fillX, fillY;
696   int fillWd, fillHt;
697
698   XSetForeground(XtDisplay(w), gc, printResources.lightGrayPixel);
699
700   fillX = x1;
701   fillY = y1;
702   fillWd = x2 - x1 + 1;
703   fillHt = y2 - y1 + 1;
704   XFillRectangle(XtDisplay(w), XtWindow(w), gc, fillX, fillY, fillWd, fillHt);
705
706   if (lineWidth > 0)
707     x_draw_box(gInfo, x1, y1, x2, y2, lineWidth);
708 #else
709   static char lightStippleData[] = {0x10, 0x00, 0x01, 0x00};
710
711   if (gInfo->lightPixmap == None)
712   {
713     Widget w = gInfo->drawingArea;
714     Arg args[10];
715     int nargs;
716     unsigned long fg, bg;
717     int depth;
718     int lightStippleWd = 8;
719     int lightStippleHt = 4;
720
721     if (gInfo->reverseVideo)
722     {
723       fg = gInfo->bg;
724       bg = gInfo->fg;
725     }
726     else
727     {
728       fg = gInfo->fg;
729       bg = gInfo->bg;
730     }
731
732     nargs = 0;
733     XtSetArg(args[nargs], XmNdepth, &depth); nargs++;
734     XtGetValues(w, args, nargs);
735
736     gInfo->lightPixmap =
737       XCreatePixmapFromBitmapData(XtDisplay(w), XtWindow(w),
738                                   lightStippleData,
739                                   lightStippleWd, lightStippleHt,
740                                   fg, bg, depth);
741   }
742
743   x_fill_box(gInfo, x1, y1, x2, y2, gInfo->lightPixmap, lineWidth);
744 #endif
745 }
746
747 static void
748 x_fill_dark_box(CMGraphicsInfo *gInfo, int x1, int y1, int x2, int y2,
749                 int lineWidth)
750 {
751 #ifdef GR_DEBUG
752   Widget w = gInfo->drawingArea;
753   GC gc = gInfo->gc;
754   int fillX, fillY;
755   int fillWd, fillHt;
756
757   XSetForeground(XtDisplay(w), gc, printResources.darkGrayPixel);
758
759   fillX = x1;
760   fillY = y1;
761   fillWd = x2 - x1 + 1;
762   fillHt = y2 - y1 + 1;
763   XFillRectangle(XtDisplay(w), XtWindow(w), gc, fillX, fillY, fillWd, fillHt);
764
765   if (lineWidth > 0)
766     x_draw_box(gInfo, x1, y1, x2, y2, lineWidth);
767 #else
768   static char darkStippleData[] = {0x11, 0xaa, 0x44, 0xaa};
769
770   if (gInfo->darkPixmap == None)
771   {
772     Widget w = gInfo->drawingArea;
773     Arg args[10];
774     int nargs;
775     unsigned long fg, bg;
776     int depth;
777     int darkStippleWd = 8;
778     int darkStippleHt = 4;
779
780     if (gInfo->reverseVideo)
781     {
782       fg = gInfo->bg;
783       bg = gInfo->fg;
784     }
785     else
786     {
787       fg = gInfo->fg;
788       bg = gInfo->bg;
789     }
790
791     nargs = 0;
792     XtSetArg(args[nargs], XmNdepth, &depth); nargs++;
793     XtGetValues(w, args, nargs);
794
795     gInfo->darkPixmap =
796       XCreatePixmapFromBitmapData(XtDisplay(w), XtWindow(w),
797                                   darkStippleData,
798                                   darkStippleWd, darkStippleHt,
799                                   fg, bg, depth);
800   }
801
802   x_fill_box(gInfo, x1, y1, x2, y2, gInfo->darkPixmap, lineWidth);
803 #endif
804 }
805
806 static void
807 x_fill_black_box(CMGraphicsInfo *gInfo, int x1, int y1, int x2, int y2)
808 {
809   x_fill_box(gInfo, x1, y1, x2, y2, None, 0);
810 }
811
812 static void
813 x_fill_box(CMGraphicsInfo *gInfo, int x1, int y1,
814            int x2, int y2, Pixmap stipple, int lineWidth)
815 {
816   Widget w = gInfo->drawingArea;
817   GC gc = gInfo->gc;
818   int fillX, fillY;
819   int fillWd, fillHt;
820
821   XSetForeground(XtDisplay(w), gc, gInfo->fg);
822   XSetBackground(XtDisplay(w), gc, gInfo->bg);
823
824   if (stipple != None)
825   {
826     XSetTile(XtDisplay(w), gc, stipple);
827     XSetFillStyle(XtDisplay(w), gc, FillTiled);
828   }
829
830   fillX = x1;
831   fillY = y1;
832   fillWd = x2 - x1 + 1;
833   fillHt = y2 - y1 + 1;
834   XFillRectangle(XtDisplay(w), XtWindow(w), gc, fillX, fillY, fillWd, fillHt);
835
836   if (stipple != None)
837     XSetFillStyle(XtDisplay(w), gc, FillSolid);
838
839   if (lineWidth > 0)
840     x_draw_box(gInfo, x1, y1, x2, y2, lineWidth);
841 }
842
843 static void
844 x_draw_box(CMGraphicsInfo *gInfo, int x1, int y1,
845            int x2, int y2, int lineWidth)
846 {
847   Widget w = gInfo->drawingArea;
848   GC gc = gInfo->gc;
849   XGCValues newGCValues;
850
851   if (lineWidth == 0)
852     lineWidth = 1;
853
854   newGCValues.line_width = lineWidth;
855   newGCValues.foreground = gInfo->fg;
856   XChangeGC(XtDisplay(w), gc, GCForeground | GCLineWidth, &newGCValues);
857
858 #ifdef NEVER
859   /* X centers thick lines; we want them wholly within specified rectangle. */
860   if (lineWidth > 1)
861   {
862     int ulOffset = lineWidth / 2;
863     int lrOffset = (lineWidth - 1) / 2;
864
865     x1 += ulOffset;
866     y1 += ulOffset;
867     x2 -= lrOffset;
868     y2 -= lrOffset;
869   }
870 #endif
871
872   XDrawRectangle(XtDisplay(w), XtWindow(w),
873                  gc, x1, y1, x2 - x1, y2 - y1);
874 }
875
876 static void
877 x_draw_line(CMGraphicsInfo *gInfo, int x1, int y1,
878             int x2, int y2, int lineWidth)
879 {
880   Widget w = gInfo->drawingArea;
881   GC gc = gInfo->gc;
882   XGCValues newGCValues;
883
884   if (lineWidth == 0)
885     lineWidth = 1;
886
887   newGCValues.line_width = lineWidth;
888   newGCValues.foreground = gInfo->fg;
889   XChangeGC(XtDisplay(w), gc, GCForeground | GCLineWidth, &newGCValues);
890
891   XDrawLine(XtDisplay(w), XtWindow(w),
892             gc, x1, y1, x2, y2);
893 }
894
895 static void
896 x_set_clip_box(CMGraphicsInfo *gInfo, int x1, int y1, int x2, int y2)
897 {
898   XRectangle rect;
899   Widget w = gInfo->drawingArea;
900
901   rect.x = x1;
902   rect.y = y1;
903   rect.width = x2 - x1;
904   rect.height = y2 - y1;
905
906   XSetClipRectangles(XtDisplay(w), gInfo->gc, 0, 0, &rect, 1, YXBanded);
907 }
908
909 static void
910 x_unset_clip_box(CMGraphicsInfo *gInfo)
911 {
912   Widget w = gInfo->drawingArea;
913
914   XSetClipMask(XtDisplay(w), gInfo->gc, None);
915 }
916
917 static Boolean
918 x_load_font(CMGraphicsInfo *gInfo, CMFontInfo *fInfo, char *fontPattern)
919 {
920   Widget w = gInfo->drawingArea;
921   XrmValue fromValue;
922   XrmValue toValue;
923   XmFontList fontList = (XmFontList)NULL;
924
925   if (fInfo->fontList != (XmFontList)NULL)
926       return False;
927
928   fromValue.addr = (XPointer)fontPattern;
929   fromValue.size = strlen(fontPattern);
930
931   toValue.addr = (XPointer)&fontList;
932   toValue.size = sizeof(XmFontList);
933
934 #ifdef GR_DEBUG
935   {
936     char *tmpPtr = XtNewString(fontPattern);
937     int i;
938
939     for (i = 0; tmpPtr[i] != '\0'; i++)
940     {
941       if ((i > 0) &&
942           (tmpPtr[i] == '0') &&
943           (tmpPtr[i - 1] == '-') &&
944           (tmpPtr[i + 1] == '-'))
945         tmpPtr[i] = '*';
946     }
947     fromValue.addr = (XPointer)tmpPtr;
948   }
949 #endif /* GR_DEBUG */
950
951   /*
952    * :( XtConvertAndStore() doesn't return False even when the specified
953    * font cannot be found; Motif plugs in a default font and issues a
954    * warning to stderr.
955    */
956   XtConvertAndStore(w, XmRString, &fromValue, XmRFontList, &toValue);
957
958 #ifdef GR_DEBUG
959   XtFree((char *)fromValue.addr);
960 #endif
961
962   fInfo->fontList = fontList;
963   return True;
964 }
965
966 static Boolean
967 cm_load_font(CMGraphicsInfo *gInfo, CMFontEnum fontEnum,
968              char *fontPattern)
969 {
970   int i;
971   CMFontInfo *fInfo = cm_find_font(gInfo, fontEnum);
972
973   if (fInfo != (CMFontInfo *)NULL)
974     /* It's a no-no to try to load a font more than once! */
975     return False;
976
977   fInfo = (CMFontInfo *)XtRealloc((char *)gInfo->fontInfo,
978                                   sizeof(CMFontInfo) * (gInfo->nFonts + 1));
979   if (fInfo == (CMFontInfo *)NULL)
980     return False;
981   gInfo->fontInfo = fInfo;
982
983   fInfo = &(gInfo->fontInfo[gInfo->nFonts]);
984   fInfo->fontEnum = fontEnum;
985   fInfo->fontList = (XmFontList)NULL;
986
987   if (!x_load_font(gInfo, fInfo, fontPattern))
988   {
989     cm_load_font_error(gInfo, fontPattern);
990     return False;
991   }
992
993   gInfo->nFonts++;
994   return True;
995 }
996
997 static void
998 cm_load_font_error(CMGraphicsInfo *gInfo, char *fontPattern)
999 {
1000   Calendar *c = gInfo->c;
1001   Props_pu *pu = (Props_pu *)c->properties_pu;
1002   char *errFmt;
1003   char *errText;
1004   char *title;
1005   char *label;
1006
1007   errFmt = catgets(c->DT_catd, 1, 1119,
1008                    "Warning - Unable to load font %s.");
1009   errText = (char *)XtMalloc((strlen(errFmt) + strlen(fontPattern) + 1) *
1010                              sizeof(char));
1011   sprintf(errText, errFmt, fontPattern);
1012   label = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
1013   title = XtNewString(catgets(c->DT_catd, 1, 1118,
1014                               "Calendar : Warning - Print"));
1015
1016   dialog_popup(c->frame,
1017                DIALOG_TITLE, title,
1018                DIALOG_TEXT, errText,
1019                BUTTON_IDENT, 1, label,
1020                DIALOG_IMAGE, pu->xm_warning_pixmap,
1021                NULL);
1022
1023   XtFree(label);
1024   XtFree(title);
1025   XtFree(errText);
1026 }
1027
1028 static void
1029 cm_release_fonts(CMGraphicsInfo *gInfo)
1030 {
1031   XtFree((char *)gInfo->fontInfo);
1032   gInfo->fontInfo = (CMFontInfo *)NULL;
1033   gInfo->nFonts = 0;
1034 }
1035
1036 static Boolean
1037 cm_set_font(CMGraphicsInfo *gInfo, CMFontEnum fontEnum)
1038 {
1039   CMFontInfo *fInfo;
1040
1041   if ((gInfo->curFont == (CMFontInfo *)NULL) ||
1042       (gInfo->curFont->fontEnum != fontEnum))
1043   {
1044     if ((fInfo = cm_find_font(gInfo, fontEnum)) == (CMFontInfo *)NULL)
1045       return False;
1046
1047     gInfo->curFont = fInfo;
1048   }
1049
1050   return True;
1051 }
1052
1053 static CMFontInfo *
1054 cm_find_font(CMGraphicsInfo *gInfo, CMFontEnum fontEnum)
1055 {
1056   int i;
1057
1058   for (i = 0; i < gInfo->nFonts; i++)
1059   {
1060     if (gInfo->fontInfo[i].fontEnum == fontEnum)
1061       return &(gInfo->fontInfo[i]);
1062   }
1063
1064   return (CMFontInfo *)NULL;
1065 }
1066
1067 static void
1068 cm_font_extents(CMGraphicsInfo *gInfo, CMFontInfo *fInfo, int *wd, int *ht)
1069 {
1070   int maxHt = 0;
1071   int maxWd = 0;
1072
1073   if ((gInfo != (CMGraphicsInfo *)NULL) &&
1074       (fInfo != (CMFontInfo *)NULL))
1075   {
1076     XmFontContext fontContext;
1077
1078     if (XmFontListInitFontContext(&fontContext, fInfo->fontList))
1079     {
1080       XmFontListEntry fontListEntry;
1081       XFontSet fontSet;
1082       XFontStruct *fontStruct;
1083       XtPointer fontEntryFont;
1084       XmFontType fontType;
1085       XFontSetExtents *fontSetExtents;
1086       int thisWd, thisHt;
1087
1088       while ((fontListEntry = XmFontListNextEntry(fontContext))
1089              != (XmFontListEntry)NULL)
1090       {
1091         fontEntryFont = XmFontListEntryGetFont(fontListEntry, &fontType);
1092         if (fontType == XmFONT_IS_FONT)
1093         {
1094           fontStruct = (XFontStruct *)fontEntryFont;
1095           thisWd = fontStruct->max_bounds.rbearing -
1096             fontStruct->min_bounds.lbearing;
1097           thisHt = fontStruct->ascent + fontStruct->descent;
1098         }
1099         else if (fontType == XmFONT_IS_FONTSET)
1100         {
1101           fontSet = (XFontSet)fontEntryFont;
1102           fontSetExtents = XExtentsOfFontSet(fontSet);
1103           thisWd = fontSetExtents->max_logical_extent.width;
1104           thisHt = fontSetExtents->max_logical_extent.height;
1105         }
1106         else continue;
1107
1108         if (thisWd > maxWd)
1109           maxWd = thisWd;
1110         if (thisHt > maxHt)
1111           maxHt = thisHt;
1112       }
1113
1114       XmFontListFreeFontContext(fontContext);
1115     }
1116   }
1117
1118   *wd = (maxWd > 0) ? maxWd : 8;
1119   *ht = (maxHt > 0) ? maxHt : 13;
1120 }
1121
1122 static int
1123 cm_font_height(CMGraphicsInfo *gInfo, CMFontInfo *fInfo)
1124 {
1125   int wd, ht;
1126
1127   cm_font_extents(gInfo, fInfo, &wd, &ht);
1128   return ht;
1129 }
1130
1131 static int
1132 cm_font_width(CMGraphicsInfo *gInfo, CMFontInfo *fInfo)
1133 {
1134   int wd, ht;
1135
1136   cm_font_extents(gInfo, fInfo, &wd, &ht);
1137   return wd;
1138 }
1139
1140 static int
1141 cm_string_width(CMGraphicsInfo *gInfo, CMFontInfo *fInfo, char *str)
1142 {
1143   if ((gInfo != (CMGraphicsInfo *)NULL) &&
1144       (fInfo != (CMFontInfo *)NULL) &&
1145       (str != (char *)NULL))
1146   {
1147     XmString xmStr;
1148     Dimension textWd;
1149     Dimension textHt;
1150     XmFontList fontList = fInfo->fontList;
1151
1152     xmStr = XmStringCreateLocalized(str);
1153     XmStringExtent(fontList, xmStr, &textWd, &textHt);
1154     XmStringFree(xmStr);
1155
1156     return textWd;
1157   }
1158
1159   return 0;
1160 }
1161
1162 static void
1163 cm_reverse_video(CMGraphicsInfo *gInfo, Boolean enabled)
1164 {
1165   if (gInfo->reverseVideo != enabled)
1166   {
1167     Pixel tmp;
1168
1169     tmp = gInfo->fg;
1170     gInfo->fg = gInfo->bg;
1171     gInfo->bg = tmp;
1172
1173     gInfo->reverseVideo = enabled;
1174   }
1175 }
1176
1177 static CMFontEnum
1178 cm_get_title_enum(CMGraphicsInfo *gInfo)
1179 {
1180   switch (gInfo->reportType)
1181   {
1182   case PR_DAY_VIEW:
1183     return DV_TITLE_FONT;
1184
1185   case PR_WEEK_VIEW:
1186     return WV_TITLE_FONT;
1187
1188   default:
1189   case PR_MONTH_VIEW:
1190     return MV_TITLE_FONT;
1191
1192   case PR_YEAR_VIEW:
1193     return YV_TITLE_FONT;
1194
1195   case PR_APPT_LIST:
1196     return AV_TITLE_FONT;
1197
1198   case PR_TODO_LIST:
1199     return TV_TITLE_FONT;
1200   }
1201 }
1202
1203 static CMFontEnum
1204 cm_get_header_enum(CMGraphicsInfo *gInfo)
1205 {
1206   switch (gInfo->reportType)
1207   {
1208   case PR_DAY_VIEW:
1209     return DV_HEADER_FONT;
1210
1211   case PR_WEEK_VIEW:
1212     return WV_HEADER_FONT;
1213
1214   default:
1215   case PR_MONTH_VIEW:
1216     return MV_HEADER_FONT;
1217
1218   case PR_YEAR_VIEW:
1219     return YV_HEADER_FONT;
1220
1221   case PR_APPT_LIST:
1222     return AV_HEADER_FONT;
1223
1224   case PR_TODO_LIST:
1225     return TV_HEADER_FONT;
1226   }
1227 }
1228
1229 static CMFontEnum
1230 cm_get_tiny_title_enum(CMGraphicsInfo *gInfo)
1231 {
1232   switch (gInfo->reportType)
1233   {
1234   default:
1235   case PR_MONTH_VIEW:
1236     return MV_TINY_TITLE_FONT;
1237
1238   case PR_YEAR_VIEW:
1239     return YV_TINY_TITLE_FONT;
1240
1241   case PR_APPT_LIST:
1242     return AV_TINY_TITLE_FONT;
1243
1244   case PR_TODO_LIST:
1245     return TV_TINY_TITLE_FONT;
1246   }
1247 }
1248
1249 static CMFontEnum
1250 cm_get_tiny_day_enum(CMGraphicsInfo *gInfo)
1251 {
1252   switch (gInfo->reportType)
1253   {
1254   default:
1255   case PR_MONTH_VIEW:
1256     return MV_TINY_DAY_FONT;
1257
1258   case PR_YEAR_VIEW:
1259     return YV_TINY_DAY_FONT;
1260
1261   case PR_APPT_LIST:
1262     return AV_TINY_DAY_FONT;
1263
1264   case PR_TODO_LIST:
1265     return TV_TINY_DAY_FONT;
1266   }
1267 }
1268
1269 static CMFontEnum
1270 cm_get_tiny_date_enum(CMGraphicsInfo *gInfo)
1271 {
1272   switch (gInfo->reportType)
1273   {
1274   default:
1275   case PR_MONTH_VIEW:
1276     return MV_TINY_DATE_FONT;
1277
1278   case PR_YEAR_VIEW:
1279     return YV_TINY_DATE_FONT;
1280
1281   case PR_APPT_LIST:
1282     return AV_TINY_DATE_FONT;
1283
1284   case PR_TODO_LIST:
1285     return TV_TINY_DATE_FONT;
1286   }
1287 }
1288
1289 static void
1290 cm_adjust_margins(CMGraphicsInfo *gInfo)
1291 {
1292   CMFontInfo *fInfo;
1293   CMFontEnum titleFont, headerFont;
1294
1295   titleFont = cm_get_title_enum(gInfo);
1296   headerFont = cm_get_header_enum(gInfo);
1297
1298   /*
1299    * Assume MonthFont and StampFont have been
1300    * set as required for header and footer.
1301    */
1302   if ((fInfo = cm_find_font(gInfo, titleFont)) != (CMFontInfo *)NULL)
1303     gInfo->topMarginY += cm_font_height(gInfo, fInfo);
1304
1305   if ((fInfo = cm_find_font(gInfo, headerFont)) != (CMFontInfo *)NULL)
1306     gInfo->bottomMarginY -= VMARGIN(gInfo) + cm_font_height(gInfo, fInfo);
1307 }
1308
1309 static int
1310 cm_cvt_margin(CMGraphicsInfo *gInfo, Props_op prop, int defaultVal)
1311 {
1312   Widget w = gInfo->drawingArea;
1313   Props *p = (Props *) gInfo->c->properties;
1314   XtEnum badCvt;
1315   int returnVal;
1316
1317   /* PostScript dimensions are the same vertically as horizontally. */
1318   returnVal = XmConvertStringToUnits(XtScreen(w),
1319                                      get_char_prop(p, prop),
1320                                      XmHORIZONTAL,
1321                                      XmPIXELS,
1322                                      &badCvt);
1323
1324   return badCvt ? defaultVal : returnVal;
1325 }
1326
1327 static void
1328 cm_print_time(CMGraphicsInfo *gInfo, char *str, Glance view)
1329 {
1330   cm_print_text(gInfo, str, (view == dayGlance) ? 0 : 2, view);
1331 }
1332
1333 static void
1334 cm_print_appt_text(CMGraphicsInfo *gInfo, char *str,
1335                    int indentAmt, Glance view)
1336 {
1337   char *to = NULL;
1338   unsigned long to_len = 0;
1339   unsigned long _len;
1340
1341   _len = strlen(str);
1342   _converter_( str, _len, &to, &to_len );
1343   if ( ( to != NULL ) && ( to_len != 0 ) )
1344     str = to;
1345
1346   cm_print_text(gInfo, str, indentAmt, view);
1347 }
1348
1349 static void
1350 cm_print_text(CMGraphicsInfo *gInfo, char *str,
1351               int indentAmt, Glance view)
1352 {
1353   int textX, textY;
1354   int clipX1, clipX2;
1355
1356   switch (view)
1357   {
1358   case dayGlance:
1359     cm_set_font(gInfo, DV_APPT_FONT);
1360
1361     /* Make sure the text fits in the box. */
1362     if (gInfo->u.dayInfo.line1 + cm_font_height(gInfo, gInfo->curFont) +
1363         VMARGIN(gInfo) <= gInfo->u.dayInfo.curY1 - (gInfo->normalWd / 2))
1364     {
1365       textX = gInfo->u.dayInfo.curX1 + gInfo->u.dayInfo.tab1 + HMARGIN(gInfo) +
1366         (indentAmt * cm_font_width(gInfo, gInfo->curFont));
1367       textY = gInfo->u.dayInfo.line1;
1368       clipX1 = textX;
1369       clipX2 = gInfo->u.dayInfo.curX1 + gInfo->u.dayInfo.boxWd -
1370         ((gInfo->normalWd / 2) + 1) - HMARGIN(gInfo);
1371
1372       gInfo->u.dayInfo.line1 += cm_font_height(gInfo, gInfo->curFont);
1373       break;
1374     }
1375     return;
1376
1377   case weekGlance:
1378     cm_set_font(gInfo, WV_APPT_FONT);
1379
1380     /* Make sure the text fits in the box. */
1381     if (gInfo->u.weekInfo.lineY + cm_font_height(gInfo, gInfo->curFont) +
1382         VMARGIN(gInfo) <= gInfo->u.weekInfo.lineMaxY - (gInfo->thickWd / 2))
1383     {
1384       textX = gInfo->u.weekInfo.lineX +
1385         (gInfo->normalWd / 2) + HMARGIN(gInfo) +
1386         (indentAmt * cm_font_width(gInfo, gInfo->curFont));
1387       textY = gInfo->u.weekInfo.lineY;
1388       clipX1 = textX;
1389       clipX2 = gInfo->u.weekInfo.lineX +
1390         (gInfo->u.weekInfo.boxWd / WEEK_DAYS) -
1391           ((gInfo->normalWd / 2) + 1) - HMARGIN(gInfo);
1392
1393       gInfo->u.weekInfo.lineY += cm_font_height(gInfo, gInfo->curFont);
1394       break;
1395     }
1396     return;
1397
1398   default:
1399     return;
1400   }
1401
1402   if (clipX2 > clipX1)
1403   {
1404     x_set_clip_box(gInfo, clipX1, gInfo->topMarginY,
1405                    clipX2, gInfo->bottomMarginY - 1);
1406     x_print_string(gInfo, str, textX, textY, LEFT_AT_X | TOP_AT_Y);
1407     x_unset_clip_box(gInfo);
1408   }
1409 }
1410
1411 static void
1412 cm_week_sched_update(CMGraphicsInfo *gInfo, Dtcm_appointment *appt, Props *p)
1413 {
1414   /*
1415    * In order to draw appts in the sched box,  all appts for a day are
1416    * mapped into a array, and then drawn later.  The array has
1417    * 96 elements, and represents the 96 15-minute segements
1418    * available between the day boundaries
1419    */
1420   int begin_t = get_int_prop(p, CP_DAYBEGIN);
1421   int end_t = get_int_prop(p, CP_DAYEND);
1422   Tick  tick;
1423   Tick  end_tick = 0;
1424   int i, start, end;
1425   int end_slider;
1426
1427   _csa_iso8601_to_tick(appt->time->value->item.date_time_value, &tick);
1428   if (appt->end_time)
1429     _csa_iso8601_to_tick(appt->end_time->value->item.date_time_value,
1430                          &end_tick);
1431
1432   /*
1433    * Determine the last element in the sched_buckets array which
1434    * corresponds to this time range.
1435    */
1436
1437   end_slider = (end_t - begin_t) * 4;
1438
1439   /* 
1440    * Figure where the begin and end times should be in the array.
1441    */
1442   start = ((hour(tick) - begin_t) * 4) + (minute(tick) / 15);
1443   if (end_tick)
1444     end = start + ((end_tick - tick) * 4 / 3600);
1445   else
1446     end = start;
1447
1448   /*
1449    * Make sure that the appointment starts/ends within the visible
1450    * time range.
1451    */
1452   if (start < 0) start = 0;
1453   if (end < 0) end = 0;
1454   if (start > end_slider) start = end_slider;
1455   if (end > end_slider) end = end_slider;
1456
1457   /* 
1458    * Only map if some portion of time is between day boundaries.
1459    */
1460   if ((start < 0 && end < 0) || 
1461       (start >= end_slider && end >= end_slider))
1462     return;
1463
1464   /* 
1465    * Mark the blocks of time affected in the array.
1466    */
1467   for (i = start; i < end; i++)
1468     gInfo->u.weekInfo.schedBucket[i]++;
1469 }
1470
1471 static int
1472 cm_week_sched_box_indent(CMGraphicsInfo *gInfo)
1473 {
1474   CMFontInfo *fInfo = cm_find_font(gInfo, WV_DAY_FONT);
1475   static char *baselineStr = "24";
1476
1477   return cm_string_width(gInfo, fInfo, baselineStr) + HMARGIN(gInfo) +
1478     gInfo->thickWd;
1479 }
1480
1481 static void
1482 cm_set_todo_text_clipping(CMGraphicsInfo *gInfo)
1483 {
1484   x_set_clip_box(gInfo,
1485                  gInfo->u.toDoInfo.innerX1,
1486                  gInfo->u.toDoInfo.innerY1,
1487                  gInfo->u.toDoInfo.boxX2 -
1488                  ((gInfo->thickWd / 2) + 1) - HMARGIN(gInfo),
1489                  gInfo->u.toDoInfo.boxY2 -
1490                  ((gInfo->thickWd / 2) + 1));
1491 }
1492
1493 static void
1494 cm_unset_todo_text_clipping(CMGraphicsInfo *gInfo)
1495 {
1496   x_unset_clip_box(gInfo);
1497 }
1498
1499 static void
1500 cm_print_todo_text(CMGraphicsInfo *gInfo, char *str1, CSA_sint32 as,
1501                    CSA_sint32 appt_type, int items)
1502 {
1503   char buf[20];
1504   char *str;
1505   int textX, textY;
1506   int fontHt;
1507   int i, digitWd, maxDigitWd;
1508   int indent;
1509   Boolean isTodo = (appt_type == CSA_TYPE_TODO);
1510
1511   cm_set_font(gInfo, isTodo ? TV_ITEM_FONT : AV_ITEM_FONT);
1512   maxDigitWd = 0;
1513   for (i = 0; i <= 9; i++)
1514   {
1515     sprintf(buf, "%d", i);
1516     if ((digitWd = cm_string_width(gInfo, gInfo->curFont, buf)) > maxDigitWd)
1517       maxDigitWd = digitWd;
1518   }
1519
1520   sprintf(buf, "%d.", items);
1521
1522   indent = strlen(buf);
1523   if (indent < 4)
1524     indent = 4;
1525   textX = gInfo->u.toDoInfo.lineX + (indent * maxDigitWd);
1526   textY = gInfo->u.toDoInfo.lineY;
1527   x_print_string(gInfo, buf, textX, textY,
1528                  RIGHT_AT_X | TOP_AT_Y);
1529   textX += maxDigitWd + HMARGIN(gInfo);
1530
1531   cm_set_font(gInfo, isTodo ? TV_APPT_FONT : AV_APPT_FONT);
1532   fontHt = cm_font_height(gInfo, gInfo->curFont);
1533
1534   if (isTodo)
1535   {
1536     /* draw check box */
1537     x_draw_box(gInfo,
1538                textX + (gInfo->normalWd / 2) + 1,
1539                textY + (gInfo->normalWd / 2) + 1,
1540                textX + fontHt - ((gInfo->normalWd + 1) / 2),
1541                textY + fontHt - ((gInfo->normalWd + 1) / 2),
1542                gInfo->normalWd);
1543
1544     /* add check to box */
1545     if (as == CSA_STATUS_COMPLETED)
1546     {
1547       x_draw_line(gInfo,
1548                   textX + (fontHt / 4),
1549                   textY + (fontHt / 2),
1550                   textX + (fontHt / 2),
1551                   textY + fontHt - ((gInfo->normalWd + 3) / 2),
1552                   gInfo->normalWd);
1553       x_draw_line(gInfo,
1554                   textX + (fontHt / 2),
1555                   textY + fontHt - ((gInfo->normalWd + 3) / 2),
1556                   textX + ((5 * fontHt) / 4),
1557                   textY + (gInfo->normalWd / 2) + 1,
1558                   gInfo->normalWd);
1559     }
1560     textX += ((5 * fontHt) / 4) + maxDigitWd + HMARGIN(gInfo);
1561   }
1562
1563   {
1564     char *to = NULL;
1565     unsigned long to_len = 0;
1566     unsigned long _len;
1567
1568     _len = strlen(str1);
1569     _converter_( str1, _len, &to, &to_len );
1570     if ( ( to != NULL ) && ( to_len != 0 ) )
1571       str1 = to;
1572   }
1573
1574   str = euc_to_octal(str1);
1575
1576   x_print_string(gInfo, str, textX, textY, LEFT_AT_X | TOP_AT_Y);
1577   gInfo->u.toDoInfo.lineY += fontHt;
1578 }
1579
1580 static int
1581 cm_tiny_month_height(CMGraphicsInfo *gInfo, int spacing)
1582 {
1583   int monthBoxHt;
1584   CMFontInfo *fInfo;
1585
1586   /*
1587    * Month boxes need to be tall enough for:
1588    *  1 MonthFont, 1 DayFont, 6 DateFonts
1589    */
1590   fInfo = cm_find_font(gInfo, cm_get_tiny_title_enum(gInfo));
1591   monthBoxHt = cm_font_height(gInfo, fInfo) + (2 * spacing);
1592
1593   fInfo = cm_find_font(gInfo, cm_get_tiny_day_enum(gInfo));
1594   monthBoxHt += spacing + cm_font_height(gInfo, fInfo);
1595
1596   fInfo = cm_find_font(gInfo, cm_get_tiny_date_enum(gInfo));
1597   monthBoxHt += 6 * (spacing + cm_font_height(gInfo, fInfo));
1598
1599   return monthBoxHt;
1600 }
1601
1602 static void
1603 cm_print_todo_months(CMGraphicsInfo *gInfo, time_t end_time)
1604 {
1605   int x1, y1, x2, y2, lastX, mon, yr;
1606   int monthBoxWd;
1607   int tlOff = (gInfo->thickWd + 1) / 2;
1608   int brOff = (gInfo->thickWd / 2) + 1;
1609
1610   mon = month(end_time);
1611   yr = year(end_time);
1612
1613   x1 = gInfo->u.toDoInfo.boxX1;
1614   lastX = gInfo->u.toDoInfo.boxX2;
1615   monthBoxWd = lastX - x1;
1616   y1 = gInfo->u.toDoInfo.boxY1;
1617   x2 = x1 + (monthBoxWd / 3);
1618   y2 = gInfo->u.toDoInfo.boxY2;
1619
1620   x_draw_line(gInfo, x2, y1, x2, y2, gInfo->thickWd);
1621   if ((mon - 1) == 0)
1622     x_print_month((void *)gInfo, 12, yr - 1,
1623                   x1 + tlOff, y1 + tlOff,
1624                   x2 - brOff, y2 - brOff, VMARGIN(gInfo));
1625   else
1626     x_print_month((void *)gInfo, mon - 1, yr,
1627                   x1 + tlOff, y1 + tlOff,
1628                   x2 - brOff, y2 - brOff, VMARGIN(gInfo));
1629
1630   x1 = x2;
1631   x2 = gInfo->u.toDoInfo.boxX1 + ((2 * monthBoxWd) / 3);
1632   x_draw_line(gInfo, x2, y1, x2, y2, gInfo->thickWd);
1633   x_print_month((void *)gInfo, mon, yr,
1634                 x1 + tlOff, y1 + tlOff,
1635                 x2 - brOff, y2 - brOff, VMARGIN(gInfo));
1636
1637   x1 = x2;
1638   x2 = lastX;
1639   if ((mon + 1) > 12)
1640     x_print_month((void *)gInfo, 1, yr + 1,
1641                   x1 + tlOff, y1 + tlOff,
1642                   x2 - brOff, y2 - brOff, VMARGIN(gInfo));
1643   else
1644     x_print_month((void *)gInfo, mon + 1, yr,
1645                   x1 + tlOff, y1 + tlOff,
1646                   x2 - brOff, y2 - brOff, VMARGIN(gInfo));
1647 }
1648
1649 static int
1650 cm_count_appts(CMGraphicsInfo *gInfo, CSA_entry_handle *list, int a_total,
1651                CSA_sint32 appt_type, int vf)
1652 {
1653   int                   i, meoval;
1654   boolean_t             skip_appt;
1655   CSA_return_code       stat;
1656   Dtcm_appointment      *appt;
1657   Calendar              *c = gInfo->c;
1658   Props                 *p = (Props*)c->properties;
1659   Tick                  start_tick;
1660   int                   apptCount = 0;
1661
1662   meoval = get_int_prop(p, CP_PRINTPRIVACY);
1663
1664   appt = allocate_appt_struct(appt_read,
1665                               c->general->version,
1666                               CSA_ENTRY_ATTR_CLASSIFICATION_I,
1667                               CSA_ENTRY_ATTR_TYPE_I,
1668                               CSA_ENTRY_ATTR_STATUS_I,
1669                               CSA_ENTRY_ATTR_START_DATE_I,
1670                               CSA_ENTRY_ATTR_SUMMARY_I,
1671                               CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,
1672                               CSA_ENTRY_ATTR_END_DATE_I,
1673                               NULL);
1674   for (i = 0; i < a_total; i++)
1675   {
1676     stat = query_appt_struct(c->cal_handle, list[i], appt);
1677     if (stat != CSA_SUCCESS)
1678     {
1679       free_appt_struct(&appt);
1680       return;
1681     }
1682     skip_appt = B_FALSE;
1683
1684     if ((privacy_set(appt) == CSA_CLASS_PUBLIC) &&
1685         !(meoval & PRINT_PUBLIC))
1686       skip_appt = B_TRUE;
1687     else if ((privacy_set(appt) == CSA_CLASS_CONFIDENTIAL) &&
1688              !(meoval & PRINT_SEMIPRIVATE))
1689       skip_appt = B_TRUE;
1690     else if ((privacy_set(appt) == CSA_CLASS_PRIVATE) &&
1691              !(meoval & PRINT_PRIVATE))
1692       skip_appt = B_TRUE;
1693
1694     if ((appt_type == CSA_TYPE_TODO) &&
1695         ((appt->type->value->item.sint32_value != CSA_TYPE_TODO)
1696          ||
1697          ((vf == VIEW_PENDING) &&
1698           (appt->state->value->item.sint32_value ==
1699            CSA_STATUS_COMPLETED)) ||
1700          ((vf == VIEW_COMPLETED) &&
1701           (appt->state->value->item.sint32_value ==
1702            CSA_X_DT_STATUS_ACTIVE))))
1703       skip_appt = B_TRUE;
1704
1705     if ((appt_type == CSA_TYPE_EVENT) &&
1706         (appt->type->value->item.sint32_value != CSA_TYPE_EVENT))
1707       skip_appt = B_TRUE;
1708
1709     if (!skip_appt)
1710       apptCount++;
1711   }
1712
1713   return apptCount;
1714 }
1715
1716 static void
1717 cm_get_todo_lines_per_page(CMGraphicsInfo *gInfo, CSA_sint32 apptType,
1718                            int *linesFullPageP,
1719                            int *linesPartialPageP)
1720 {
1721   CMFontInfo *fInfo =
1722     cm_find_font(gInfo, (apptType == CSA_TYPE_TODO) ?
1723                  TV_APPT_FONT : AV_APPT_FONT);
1724   int fontHt = cm_font_height(gInfo, fInfo);
1725
1726   *linesFullPageP = (gInfo->u.toDoInfo.boxY2 - gInfo->u.toDoInfo.innerY1 -
1727                      gInfo->thickWd - (2 * VMARGIN(gInfo))) / fontHt;
1728   *linesPartialPageP = (gInfo->u.toDoInfo.innerY2 - gInfo->u.toDoInfo.innerY1 -
1729                         gInfo->thickWd - (2 * VMARGIN(gInfo))) / fontHt;
1730 }
1731
1732 static void
1733 cm_todo_outline(CMGraphicsInfo *gInfo, Boolean lastPage)
1734 {
1735         x_fill_dark_box(gInfo, gInfo->u.toDoInfo.outerX1,
1736                         gInfo->u.toDoInfo.outerY1,
1737                         gInfo->u.toDoInfo.outerX2,
1738                         gInfo->u.toDoInfo.outerY2,
1739                         gInfo->thickWd);
1740
1741         if (lastPage)
1742         {
1743           /* Appts box. */
1744           x_fill_light_box(gInfo,
1745                            gInfo->u.toDoInfo.innerX1,
1746                            gInfo->u.toDoInfo.innerY1,
1747                            gInfo->u.toDoInfo.innerX2,
1748                            gInfo->u.toDoInfo.innerY2,
1749                            gInfo->thickWd);
1750
1751           /* Months box. */
1752           x_fill_light_box(gInfo,
1753                            gInfo->u.toDoInfo.boxX1,
1754                            gInfo->u.toDoInfo.boxY1,
1755                            gInfo->u.toDoInfo.boxX2,
1756                            gInfo->u.toDoInfo.boxY2,
1757                            gInfo->thickWd);
1758         }
1759         else
1760         {
1761           /* Appts box. */
1762           x_fill_light_box(gInfo,
1763                            gInfo->u.toDoInfo.innerX1,
1764                            gInfo->u.toDoInfo.innerY1,
1765                            gInfo->u.toDoInfo.boxX2,
1766                            gInfo->u.toDoInfo.boxY2,
1767                            gInfo->thickWd);
1768         }
1769 }
1770
1771 static void
1772 cm_print_month_time(CMGraphicsInfo *gInfo, char *str)
1773 {
1774   int textX, textY;
1775   int clipX1, clipX2;
1776   static char *baselineTime = "24:00";
1777
1778   cm_set_font(gInfo, MV_APPT_FONT);
1779
1780   /* Make sure the text fits in the box. */
1781   if (gInfo->u.monthInfo.lineY + cm_font_height(gInfo, gInfo->curFont) +
1782       VMARGIN(gInfo) <= gInfo->u.monthInfo.lineMaxY - (gInfo->normalWd / 2))
1783   {
1784     /* Time is right-justified. */
1785     textX = gInfo->u.monthInfo.lineX + (gInfo->normalWd / 2) +
1786       HMARGIN(gInfo) + cm_string_width(gInfo, gInfo->curFont, baselineTime);
1787     gInfo->u.monthInfo.lastX = textX;
1788     textY = gInfo->u.monthInfo.lineY;
1789     clipX1 = gInfo->u.monthInfo.lineX + (gInfo->normalWd / 2) + HMARGIN(gInfo);
1790     clipX2 = gInfo->u.monthInfo.lineMaxX -
1791       (gInfo->normalWd / 2) - HMARGIN(gInfo);
1792
1793     if (clipX2 > clipX1)
1794     {
1795       x_set_clip_box(gInfo, clipX1, gInfo->u.monthInfo.lineY,
1796                      clipX2, gInfo->u.monthInfo.lineMaxY);
1797       x_print_string(gInfo, str, textX, textY, RIGHT_AT_X | TOP_AT_Y);
1798       x_unset_clip_box(gInfo);
1799     }
1800   }
1801 }
1802
1803 static void
1804 cm_print_month_text(CMGraphicsInfo *gInfo, char *str, int indentAmt)
1805 {
1806   int textX, textY;
1807   int clipX1, clipX2;
1808
1809   cm_set_font(gInfo, MV_APPT_FONT);
1810
1811   /* Make sure the text fits in the box. */
1812   if (gInfo->u.monthInfo.lineY + cm_font_height(gInfo, gInfo->curFont) +
1813       VMARGIN(gInfo) <= gInfo->u.monthInfo.lineMaxY - (gInfo->normalWd / 2))
1814   {
1815     textX = gInfo->u.monthInfo.lastX + (gInfo->normalWd / 2) + HMARGIN(gInfo);
1816     textY = gInfo->u.monthInfo.lineY;
1817     clipX1 = textX;
1818     clipX2 = gInfo->u.monthInfo.lineMaxX -
1819       (gInfo->normalWd / 2) - HMARGIN(gInfo);
1820
1821     if (clipX2 > clipX1)
1822     {
1823       x_set_clip_box(gInfo, clipX1, gInfo->u.monthInfo.lineY,
1824                      clipX2, gInfo->u.monthInfo.lineMaxY);
1825       x_print_string(gInfo, str, textX, textY, LEFT_AT_X | TOP_AT_Y);
1826       x_unset_clip_box(gInfo);
1827     }
1828
1829     gInfo->u.monthInfo.lineY += cm_font_height(gInfo, gInfo->curFont);
1830   }
1831 }
1832
1833 static void
1834 cm_std_month_weekdays(CMGraphicsInfo *gInfo, int colWd,
1835                       int x1, int y1, int x2)
1836 {
1837   char *day_of_week[DAYS_IN_WEEK];
1838   int extraWd;
1839   int boxWd;
1840   int i;
1841   int indent;
1842
1843   for (i = 0; i < DAYS_IN_WEEK; i++)
1844     local_dayname(gInfo->c, &day_of_week[i], i);
1845
1846   x1 += HMARGIN(gInfo);
1847   x2 -= HMARGIN(gInfo);
1848   boxWd = x2 - x1;
1849   extraWd = boxWd - (DAYS_IN_WEEK * colWd);
1850   if (extraWd < 0)
1851   {
1852     extraWd = 0;
1853     colWd = boxWd / DAYS_IN_WEEK;
1854   }
1855
1856   /* --- print std month weekdays --- */
1857   cm_set_font(gInfo, cm_get_tiny_day_enum(gInfo));
1858   for (i = 0; i < DAYS_IN_WEEK; i++)
1859   {
1860     indent = i + 1;
1861     x_print_string(gInfo, day_of_week[i],
1862                    x1 + (indent * colWd) + ((indent * extraWd) /
1863                                             (DAYS_IN_WEEK + 1)),
1864                    y1, RIGHT_AT_X | TOP_AT_Y);
1865   }
1866
1867   for (i = 0; i < DAYS_IN_WEEK; i++)
1868     free(day_of_week[i]);
1869 }
1870
1871 static void
1872 cm_std_month_dates(CMGraphicsInfo *gInfo, int first_dom, int monlen,
1873                    int colWd, int x1, int y1, int x2, int spacing)
1874 {
1875   int i;
1876   int dateX, dateY;
1877   int extraWd;
1878   int boxWd;
1879   int indent;
1880   char dateStr[3];
1881   int fontHt;
1882
1883   cm_set_font(gInfo, cm_get_tiny_date_enum(gInfo));
1884   fontHt = cm_font_height(gInfo, gInfo->curFont);
1885
1886   x1 += HMARGIN(gInfo);
1887   x2 -= HMARGIN(gInfo);
1888   boxWd = x2 - x1;
1889   extraWd = boxWd - (DAYS_IN_WEEK * colWd);
1890   if (extraWd < 0)
1891   {
1892     extraWd = 0;
1893     colWd = boxWd / DAYS_IN_WEEK;
1894   }
1895
1896   for (i = 0; i < monlen; i++, first_dom++)
1897   {
1898     indent = (first_dom % DAYS_IN_WEEK) + 1;
1899     dateX = x1 + (indent * colWd) + ((indent * extraWd) /
1900                                      (DAYS_IN_WEEK + 1));
1901     dateY = y1 + ((first_dom / DAYS_IN_WEEK) * (spacing + fontHt));
1902     sprintf(dateStr, "%d", i + 1);
1903     x_print_string(gInfo, dateStr,
1904                    dateX, dateY, RIGHT_AT_X | TOP_AT_Y);
1905   }
1906 }
1907
1908 static void
1909 cm_print_header_string(CMGraphicsInfo *gInfo, Props_op printOp,
1910                        char *timeStamp, char *userId,
1911                        char *pageStr, char *reportTypeStr)
1912 {
1913   Props *p = (Props *)gInfo->c->properties;
1914   int xPos, yPos, posFlags;
1915   int hdrType;
1916   char *str;
1917
1918   hdrType = get_int_prop(p, printOp);
1919
1920   switch (hdrType)
1921   {
1922   case POP_HDR_DATE:
1923     str = timeStamp;
1924     break;
1925
1926   case POP_HDR_USER_ID:
1927     str = userId;
1928     break;
1929
1930   case POP_HDR_PAGE_NUMBER:
1931     str = pageStr;
1932     break;
1933
1934   case POP_HDR_REPORT_TYPE:
1935     str = reportTypeStr;
1936     break;
1937
1938   default:
1939     /* Nothing to print. */
1940     return;
1941   }
1942
1943   switch (printOp)
1944   {
1945   case CP_PRINTLHEADER:
1946     xPos = gInfo->leftMarginX;
1947     yPos = gInfo->topMarginY;
1948     posFlags = LEFT_AT_X | TOP_AT_Y;
1949     break;
1950
1951   case CP_PRINTRHEADER:
1952     xPos = gInfo->rightMarginX - 1;
1953     yPos = gInfo->topMarginY;
1954     posFlags = RIGHT_AT_X | TOP_AT_Y;
1955     break;
1956
1957   case CP_PRINTLFOOTER:
1958     xPos = gInfo->leftMarginX;
1959     if (gInfo->reportType == PR_WEEK_VIEW)
1960       xPos += cm_week_sched_box_indent(gInfo);
1961     yPos = gInfo->bottomMarginY + VMARGIN(gInfo);
1962     posFlags = LEFT_AT_X | TOP_AT_Y;
1963     break;
1964
1965   case CP_PRINTRFOOTER:
1966     xPos = gInfo->rightMarginX - 1;
1967     yPos = gInfo->bottomMarginY + VMARGIN(gInfo);
1968     posFlags = RIGHT_AT_X | TOP_AT_Y;
1969     break;
1970
1971   default:
1972     return;
1973   }
1974
1975   cm_set_font(gInfo, cm_get_header_enum(gInfo));
1976   x_print_string(gInfo, str, xPos, yPos, posFlags);
1977 }
1978
1979 static void
1980 local_dayname(Calendar *c, char **array_place, int dayNum)
1981 {
1982   char *source;
1983   char *str;
1984   char *to = NULL;
1985   unsigned long to_len = 0;
1986   unsigned long _len;
1987   static char *defaultDays[DAYS_IN_WEEK] =
1988   {
1989     "S", "M", "T", "W", "T", "F", "S"
1990   };
1991   static int dayCatIndex[DAYS_IN_WEEK] =
1992   {
1993     497, 491, 492, 493, 494, 495, 496
1994   };
1995
1996   source = catgets(c->DT_catd, 1,
1997                    dayCatIndex[dayNum], defaultDays[dayNum]);
1998
1999   _len = strlen( source );
2000   _converter_( source, _len, &to, &to_len );
2001   if ( ( to != NULL ) && ( to_len != 0 ) ) {
2002     str = euc_to_octal(to);
2003   } else {
2004     str = euc_to_octal(source);
2005   }
2006
2007   *array_place = (char *)malloc(sizeof(char) * (cm_strlen(str) + 1));
2008   cm_strcpy(*array_place, str);
2009 }
2010
2011 static void
2012 local_dayname3(Calendar *c, char **array_place, int dayNum)
2013 {
2014   char *source;
2015   char *str;
2016   char *to = NULL;
2017   unsigned long to_len = 0;
2018   unsigned long _len;
2019   static char *defaultDays[DAYS_IN_WEEK] =
2020   {
2021     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
2022   };
2023   static int dayCatIndex[DAYS_IN_WEEK] =
2024   {
2025     480, 481, 482, 483, 484, 485, 486
2026   };
2027
2028   source = catgets(c->DT_catd, 1,
2029                    dayCatIndex[dayNum], defaultDays[dayNum]);
2030
2031   _len = strlen( source );
2032   _converter_( source, _len, &to, &to_len );
2033   if ( ( to != NULL ) && ( to_len != 0 ) ) {
2034     str = euc_to_octal(to);
2035   } else {
2036     str = euc_to_octal(source);
2037   }
2038
2039   *array_place = (char *)malloc(sizeof(char) * (cm_strlen(str) + 1));
2040   cm_strcpy(*array_place, str);
2041 }
2042
2043 static char *
2044 get_report_type_string(CMGraphicsInfo *gInfo)
2045 {
2046   Calendar *c = gInfo->c;
2047   int reportType = gInfo->reportType;
2048   static char *defaultStrs[] =
2049   {
2050     "Day view by Calendar Manager",
2051     "Week view by Calendar Manager",
2052     "Month view by Calendar Manager",
2053     "Year view by Calendar Manager",
2054     "Appt List by Calendar Manager",
2055     "To Do List by Calendar Manager"
2056   };
2057   static int catIndex[] =
2058   {
2059     469, 490, 477, 507, 474, 473
2060   };
2061   static char *reportStrs[] =
2062   {
2063     NULL, NULL, NULL, NULL, NULL, NULL
2064   };
2065
2066   if ((reportType < 0) || (reportType >= XtNumber(defaultStrs)))
2067     return "";
2068
2069   if (reportStrs[reportType] == (char *)NULL)
2070   {
2071     char *str;
2072     char *to = NULL;
2073     unsigned long to_len = 0;
2074     unsigned long _len;
2075
2076     str = catgets(c->DT_catd, 1, catIndex[reportType],
2077                   defaultStrs[reportType]);
2078
2079     _len = strlen( str );
2080     _converter_( str, _len, &to, &to_len );
2081     if ( ( to != NULL ) && ( to_len != 0 ) ) {
2082       str = to;
2083     }
2084     str = euc_to_octal(str);
2085
2086     reportStrs[reportType] = cm_strdup(str);
2087   }
2088
2089   return reportStrs[reportType];
2090 }
2091
2092 static void
2093 filePrintDoneCB(Display *dsp, XPContext context, XPGetDocStatus status,
2094                 XPointer uData)
2095 {
2096   Calendar *c = (Calendar *)uData;
2097
2098   if (pd_get_bad_alloc_error(c))
2099   {
2100       showBadAllocError(c);
2101       pd_set_bad_alloc_error(c, False);
2102   }
2103   else
2104       filePrintReportStatus(c, (status == XPGetDocFinished));
2105 }
2106
2107 static void
2108 filePrintReportStatus(Calendar *c, Boolean ok)
2109 {
2110   Props_pu *pu = (Props_pu *)c->properties_pu;
2111   char *errText;
2112   char *title;
2113   char *label;
2114   Pixmap pixmap;
2115
2116   label = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
2117   if (!ok)
2118   {
2119     errText = XtNewString(catgets(c->DT_catd, 1, 1115,
2120                                   "Error - unable to print to file."));
2121     title = XtNewString(catgets(c->DT_catd, 1, 1114,
2122                                 "Calendar : Error - Print To File"));
2123     pixmap = pu->xm_error_pixmap;
2124   }
2125   else
2126   {
2127     errText = XtNewString(catgets(c->DT_catd, 1, 1117,
2128                                   "Print to file has completed."));
2129     title = XtNewString(catgets(c->DT_catd, 1, 1116,
2130                                 "Calendar : Print To File"));
2131     pixmap = pu->xm_info_pixmap;
2132   }
2133
2134   dialog_popup(c->frame,
2135                DIALOG_TITLE, title,
2136                DIALOG_TEXT, errText,
2137                BUTTON_IDENT, 1, label,
2138                DIALOG_IMAGE, pixmap,
2139                NULL);
2140
2141   XtFree(label);
2142   XtFree(title);
2143   XtFree(errText);
2144 }
2145
2146 static void
2147 showBadAllocError(Calendar *c)
2148 {
2149   Props_pu *pu = (Props_pu *)c->properties_pu;
2150   char *errText;
2151   char *title;
2152   char *label;
2153   Pixmap pixmap;
2154
2155   label = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
2156   errText = XtNewString(catgets(c->DT_catd, 1, 1122,
2157                                 "Print job failed.\n\n\
2158 The X Print Server is temporarily out of resources."));
2159   title = XtNewString(catgets(c->DT_catd, 1, 1121,
2160                                 "Calendar : Print Server Error"));
2161   pixmap = pu->xm_error_pixmap;
2162
2163   dialog_popup(c->frame,
2164                DIALOG_TITLE, title,
2165                DIALOG_TEXT, errText,
2166                BUTTON_IDENT, 1, label,
2167                DIALOG_IMAGE, pixmap,
2168                NULL);
2169
2170   XtFree(label);
2171   XtFree(title);
2172   XtFree(errText);
2173 }
2174
2175 void *
2176 x_open_file(Calendar *c)
2177 {
2178   CMGraphicsInfo        *gInfo;
2179   Widget                drawingArea;
2180   Tick          t;
2181   struct tm     *tm;
2182   Arg           args[10];
2183   int           nargs;
2184   unsigned int  gcMask = GCFont | GCForeground | GCBackground |
2185     GCTile | GCFillStyle | GCLineWidth;
2186   Widget printShell;
2187   WidgetList shellChildren;
2188 #ifdef SHELL_SIZE_BUG
2189   Dimension shellWd = 0, shellHt = 0;
2190 #endif /* SHELL_SIZE_BUG */
2191   int nChildren;
2192   static Boolean getResources = True;
2193   _Xltimeparams localtime_buf;
2194
2195   if (getResources)
2196   {
2197     XtGetApplicationResources(c->frame, (XtPointer)&dvFonts,
2198                               dvDefaultResources, XtNumber(dvDefaultResources),
2199                               NULL, 0);
2200     XtGetApplicationResources(c->frame, (XtPointer)&wvFonts,
2201                               wvDefaultResources, XtNumber(wvDefaultResources),
2202                               NULL, 0);
2203     XtGetApplicationResources(c->frame, (XtPointer)&mvFonts,
2204                               mvDefaultResources, XtNumber(mvDefaultResources),
2205                               NULL, 0);
2206     XtGetApplicationResources(c->frame, (XtPointer)&yvFonts,
2207                               yvDefaultResources, XtNumber(yvDefaultResources),
2208                               NULL, 0);
2209     XtGetApplicationResources(c->frame, (XtPointer)&avFonts,
2210                               avDefaultResources, XtNumber(avDefaultResources),
2211                               NULL, 0);
2212     XtGetApplicationResources(c->frame, (XtPointer)&tvFonts,
2213                               tvDefaultResources, XtNumber(tvDefaultResources),
2214                               NULL, 0);
2215     getResources = False;
2216   }
2217
2218   if ((printShell = pd_get_print_shell(c)) == (Widget)NULL)
2219     return (void *)NULL;
2220
2221   if ((gInfo = (CMGraphicsInfo *)XtMalloc(sizeof(CMGraphicsInfo)))
2222       == (CMGraphicsInfo *)NULL)
2223     return (void *)NULL;
2224
2225 #ifdef GR_DEBUG
2226   XtGetApplicationResources(printShell, (XtPointer)&printResources,
2227                             displayResources, XtNumber(displayResources),
2228                             NULL, 0);
2229 #endif
2230
2231 #ifdef GR_DEBUG
2232   if (!inDebugMode(c))
2233   {
2234 #endif
2235     if (pd_print_to_file(c))
2236     {
2237       char *fileName = pd_get_file_name(c);
2238
2239       /* Protocol says XpStartJob() MUST be called before XmPrintToFile() */
2240       XpStartJob(XtDisplay(printShell), XPGetData);
2241
2242       XFlush(XtDisplay(printShell));
2243
2244       if (!XmPrintToFile(XtDisplay(printShell), fileName,
2245                          filePrintDoneCB, (XtPointer)c))
2246       {
2247           XpCancelJob(XtDisplay(printShell), False);
2248
2249           XtFree(fileName);
2250           XtFree((char *)gInfo);
2251
2252           filePrintReportStatus(c, False);
2253
2254           return (void *)NULL;
2255       }
2256       XtFree(fileName);
2257     }
2258     else
2259     {
2260       XpStartJob(XtDisplay(printShell), XPSpool);
2261     }
2262 #ifdef GR_DEBUG
2263   }
2264 #endif
2265
2266   nargs = 0;
2267 #ifdef SHELL_SIZE_BUG
2268   XtSetArg(args[nargs], XmNwidth, &shellWd); nargs++;
2269   XtSetArg(args[nargs], XmNheight, &shellHt); nargs++;
2270 #endif /* SHELL_SIZE_BUG */
2271   XtSetArg(args[nargs], XmNchildren, &shellChildren); nargs++;
2272   XtSetArg(args[nargs], XmNnumChildren, &nChildren); nargs++;
2273   XtGetValues(printShell, args, nargs);
2274
2275 #ifdef SHELL_SIZE_BUG
2276   if ((shellWd < 10) || (shellHt < 10))
2277   {
2278     shellWd = XmConvertUnits(printShell, XmHORIZONTAL, Xm1000TH_INCHES,
2279                              PAGE_WIDTH, XmPIXELS);
2280     shellHt = XmConvertUnits(printShell, XmVERTICAL, Xm1000TH_INCHES,
2281                              PAGE_HEIGHT, XmPIXELS);
2282
2283     nargs = 0;
2284     XtSetArg(args[nargs], XmNwidth, shellWd); nargs++;
2285     XtSetArg(args[nargs], XmNheight, shellHt); nargs++;
2286     XtSetValues(printShell, args, nargs);
2287   }
2288 #endif /* SHELL_SIZE_BUG */
2289
2290   if (nChildren == 0)
2291   {
2292     nargs = 0;
2293     XtSetArg(args[nargs], XmNunitType, XmPIXELS); nargs++;
2294 #ifdef GR_DEBUG
2295     if (!inDebugMode(c))
2296     {
2297 #endif
2298       XtSetArg(args[nargs], XmNbackground,
2299                WhitePixelOfScreen(XtScreen(printShell))); nargs++;
2300 #ifdef GR_DEBUG
2301     }
2302 #endif
2303     drawingArea = XmCreateDrawingArea(printShell, "PrintArea",
2304                                       args, nargs);
2305   }
2306   else
2307     drawingArea = shellChildren[0];
2308
2309 #ifdef GR_DEBUG
2310   if (inDebugMode(c))
2311     XtAddCallback(drawingArea, XmNinputCallback,
2312                   tmpFn, (XtPointer)NULL);
2313 #endif
2314
2315   gInfo->drawingArea = drawingArea;
2316   gInfo->gc = XtAllocateGC(drawingArea, 0, 0, NULL, gcMask, 0);
2317   gInfo->c = c;
2318   gInfo->reportType = PR_MONTH_VIEW; /* Set properly in x_init_*() */
2319
2320   gInfo->fontInfo = gInfo->curFont = (CMFontInfo *)NULL;
2321   gInfo->nFonts = 0;
2322
2323   gInfo->reverseVideo = False;
2324   gInfo->fg = BlackPixelOfScreen(XtScreen(drawingArea));
2325   gInfo->bg = WhitePixelOfScreen(XtScreen(drawingArea));
2326 #ifdef GR_DEBUG
2327   nargs = 0;
2328   XtSetArg(args[nargs], XmNforeground, &(gInfo->fg)); nargs++;
2329   XtSetArg(args[nargs], XmNbackground, &(gInfo->bg)); nargs++;
2330   XtGetValues(drawingArea, args, nargs);
2331 #endif
2332   gInfo->lightPixmap = None;
2333   gInfo->darkPixmap = None;
2334
2335   /* set up time stamp */
2336   /* STRING_EXTRACTION SUNW_DESKSET_CM_MSG
2337    * The following string is the date/time format used in printing out
2338    * calendar views.  This is the locale's date and time.  If this string
2339    * is to be translated, please refer to the man pages for strftime()
2340    * for various format strings.
2341    */
2342   t = now();
2343   tm = _XLocaltime(&t, localtime_buf);
2344   strftime(gInfo->timestamp, BUFFERSIZE, "%x %I:%M %p", tm);
2345
2346   {
2347     char *to = NULL;
2348     unsigned long to_len = 0;
2349     unsigned long _len;
2350
2351     _len = strlen( gInfo->timestamp );
2352     _converter_( gInfo->timestamp, _len, &to, &to_len );
2353     if ( ( to != NULL ) && ( to_len != 0 ) )
2354       strncpy( gInfo->timestamp, to,
2355               ( BUFFERSIZE > to_len ) ? to_len : BUFFERSIZE - 1 );
2356   }
2357
2358   return (void *)gInfo;
2359 }
2360
2361 void
2362 x_print_file(void *gInfoP, Calendar *c)
2363 {
2364   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
2365   Display *dsp = XtDisplay(gInfo->drawingArea);
2366
2367 #ifdef GR_DEBUG
2368   if (!inDebugMode(c))
2369 #endif
2370   {
2371     XpEndJob(dsp);
2372
2373     /* Make sure we know about a BadAlloc if it happens. */
2374     XSync(XtDisplay(gInfo->drawingArea), FALSE);
2375   }
2376
2377   if (pd_get_bad_alloc_error(c) &&
2378       (!pd_print_to_file(c)))
2379   {
2380     showBadAllocError(c);
2381     pd_set_bad_alloc_error(c, False);
2382   }
2383
2384   if (gInfo->lightPixmap != None)
2385     XFreePixmap(dsp, gInfo->lightPixmap);
2386   if (gInfo->darkPixmap != None)
2387     XFreePixmap(dsp, gInfo->darkPixmap);
2388
2389   XtReleaseGC(gInfo->drawingArea, gInfo->gc);
2390
2391   cm_release_fonts(gInfo);
2392
2393   XtFree((char *)gInfo);
2394 }
2395
2396 void
2397 x_init_printer(void *gInfoP, short orientation)
2398 {
2399   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
2400   Widget w = gInfo->drawingArea;
2401   Arg args[10];
2402   int nargs;
2403   unsigned int pageWd, pageHt;
2404   int baseWd, baseHt;
2405   int rMargin, bMargin;
2406   int inchWd;
2407   Dimension daWd, daHt;
2408
2409 #ifdef GR_DEBUG
2410   if (inDebugMode(gInfo->c))
2411   {
2412     XtAddCallback(w, XmNexposeCallback,
2413                   tmpFn, (XtPointer)NULL);
2414   }
2415   else
2416 #endif
2417     XpStartPage(XtDisplay(w), XtWindow(XtParent(w)));
2418
2419   /* XpStartPage() sets the shell width/height correctly. */
2420   nargs = 0;
2421   XtSetArg(args[nargs], XmNwidth, &daWd); nargs++;
2422   XtSetArg(args[nargs], XmNheight, &daHt); nargs++;
2423   XtGetValues(XtParent(w), args, nargs);
2424
2425   if (XtIsRealized(w))
2426   {
2427     XClearArea(XtDisplay(w), XtWindow(w), 0, 0, 0, 0,
2428 #ifdef GR_DEBUG
2429                inDebugMode(gInfo->c)
2430 #else
2431                True
2432 #endif
2433                );
2434   }
2435   else
2436   {
2437     nargs = 0;
2438     XtSetArg(args[nargs], XmNwidth, daWd); nargs++;
2439     XtSetArg(args[nargs], XmNheight, daHt); nargs++;
2440     XtSetValues(w, args, nargs);
2441     XtManageChild(w);
2442   }
2443
2444 #ifdef GR_DEBUG
2445   if (inDebugMode(gInfo->c))
2446   {
2447     tmpSpin(w);
2448
2449     XtRemoveCallback(w, XmNexposeCallback,
2450                      tmpFn, (XtPointer)NULL);
2451
2452     /* Now that window is displayed, get its actual size, */
2453     /* since the Window Manager may have modified it. */
2454     nargs = 0;
2455     XtSetArg(args[nargs], XmNwidth, &daWd); nargs++;
2456     XtSetArg(args[nargs], XmNheight, &daHt); nargs++;
2457     XtGetValues(XtParent(w), args, nargs);
2458   }
2459 #endif
2460
2461   /* Get margins from properties. */
2462   inchWd = XmConvertUnits(w, XmHORIZONTAL, Xm1000TH_INCHES,
2463                           XINCH, XmPIXELS);
2464   gInfo->leftMarginX = cm_cvt_margin(gInfo, CP_PRINTLMARGIN, inchWd);
2465   gInfo->topMarginY = cm_cvt_margin(gInfo, CP_PRINTTMARGIN, inchWd);
2466   rMargin = cm_cvt_margin(gInfo, CP_PRINTRMARGIN, inchWd);
2467   bMargin = cm_cvt_margin(gInfo, CP_PRINTBMARGIN, inchWd);
2468
2469   gInfo->rightMarginX = daWd - rMargin;
2470   gInfo->bottomMarginY = daHt - bMargin;
2471
2472   pageWd = XmConvertUnits(w, XmHORIZONTAL, XmPIXELS,
2473                           daWd, Xm1000TH_INCHES);
2474   pageHt = XmConvertUnits(w, XmVERTICAL, XmPIXELS,
2475                           daHt, Xm1000TH_INCHES);
2476   if (orientation == PORTRAIT)
2477   {
2478     baseWd = PAGE_WIDTH;
2479     baseHt = PAGE_HEIGHT;
2480   }
2481   else
2482   {
2483     baseWd = PAGE_HEIGHT;
2484     baseHt = PAGE_WIDTH;
2485   }
2486
2487   gInfo->hscale = (double)pageWd / (double)baseWd;
2488   gInfo->vscale = (double)pageHt / (double)baseHt;
2489
2490   /* Scaled line widths: .25pt, 1pt, 2pt. */
2491   gInfo->thinWd = XmConvertUnits(w, XmHORIZONTAL, Xm100TH_POINTS,
2492                                  25, XmPIXELS);
2493   if (gInfo->thinWd < 1)
2494     gInfo->thinWd = 1;
2495   gInfo->normalWd = XmConvertUnits(w, XmHORIZONTAL, Xm100TH_POINTS,
2496                                    100, XmPIXELS);
2497   if (gInfo->normalWd < 1)
2498     gInfo->normalWd = 1;
2499   gInfo->thickWd = XmConvertUnits(w, XmHORIZONTAL, Xm100TH_POINTS,
2500                                   200, XmPIXELS);
2501   if (gInfo->thickWd < 1)
2502     gInfo->thickWd = 1;
2503 }
2504
2505 void
2506 x_init_day(void *gInfoP, int timeslots)
2507 {
2508   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
2509   CMFontInfo *fInfo;
2510
2511   gInfo->reportType = PR_DAY_VIEW;
2512
2513   /* Load day fonts */
2514   if (gInfo->nFonts == 0)
2515   {
2516     int i;
2517
2518     for (i = 0; i < DV_NUM_FONTS; i++)
2519       cm_load_font(gInfo, i, dvFonts[i]);
2520
2521     /* Set curFont to first loaded font. */
2522     gInfo->curFont = gInfo->fontInfo;
2523   }
2524
2525   cm_adjust_margins(gInfo);
2526
2527   fInfo = cm_find_font(gInfo, DV_TIME_FONT);
2528   gInfo->u.dayInfo.tab1 = (cm_font_height(gInfo, fInfo) * 2) + gInfo->normalWd;
2529
2530   gInfo->u.dayInfo.curX1 = gInfo->leftMarginX + (gInfo->normalWd / 2);
2531   gInfo->u.dayInfo.curX2 = (gInfo->leftMarginX + gInfo->rightMarginX) / 2;
2532   fInfo = cm_find_font(gInfo, DV_HEADER_FONT);
2533   gInfo->u.dayInfo.curY1 =
2534     gInfo->topMarginY + (gInfo->normalWd / 2) + cm_font_height(gInfo, fInfo) +
2535       VMARGIN(gInfo) + gInfo->u.dayInfo.tab1;
2536   gInfo->u.dayInfo.curY2 = gInfo->u.dayInfo.curY1;
2537
2538   gInfo->u.dayInfo.boxHt =
2539     (gInfo->bottomMarginY - ((gInfo->normalWd + 1) / 2) -
2540      gInfo->u.dayInfo.curY1) / timeslots;
2541   gInfo->u.dayInfo.boxWd =
2542     gInfo->u.dayInfo.curX2 - gInfo->u.dayInfo.curX1;
2543
2544   gInfo->u.dayInfo.line1 = 0;
2545 }
2546
2547 int
2548 x_get_day_lines_per_page(void *gInfoP)
2549 {
2550   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
2551   CMFontInfo *fInfo = cm_find_font(gInfo, DV_APPT_FONT);
2552
2553   return (gInfo->u.dayInfo.boxHt - gInfo->normalWd - (2 * VMARGIN(gInfo))) /
2554     cm_font_height(gInfo, fInfo);
2555 }
2556
2557 int
2558 x_get_week_lines_per_page(void *gInfoP)
2559 {
2560   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
2561   CMFontInfo *fInfo = cm_find_font(gInfo, DV_APPT_FONT);
2562
2563   return (gInfo->u.weekInfo.boxHt - gInfo->u.weekInfo.tab1 -
2564           ((gInfo->normalWd + 1) / 2) -
2565           (gInfo->thickWd / 2) - (2 * VMARGIN(gInfo))) /
2566             cm_font_height(gInfo, fInfo);
2567 }
2568
2569 void
2570 x_print_header(void *gInfoP, char *buf, int pageNum, int numPages)
2571 {
2572   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
2573   Calendar *c = gInfo->c;
2574   char *str;
2575   char str2[BUFFERSIZE];
2576   char pageStr[BUFFERSIZE];
2577   char *timeStamp;
2578   char *userId;
2579   char *reportTypeStr;
2580
2581   /* --- print header info at top --- */
2582   if (buf != (char *)NULL)
2583   {
2584     cm_set_font(gInfo, cm_get_title_enum(gInfo));
2585     {
2586       char *to = NULL;
2587       unsigned long to_len = 0;
2588       unsigned long _len;
2589
2590       _len = strlen( buf );
2591       _converter_( buf, _len, &to, &to_len );
2592       if ( ( to != NULL ) && ( to_len != 0 ) ) {
2593         str = euc_to_octal(to);
2594       } else {
2595         str = euc_to_octal(buf);
2596       }
2597     }
2598     x_print_string(gInfo, str,
2599                    (gInfo->rightMarginX + gInfo->leftMarginX) / 2,
2600                    gInfo->topMarginY,
2601                    CENTER_AT_X | BOTTOM_AT_Y);
2602   }
2603
2604   /* Get header/footer strings ready. */
2605   timeStamp = gInfo->timestamp;
2606   userId = c->view->current_calendar;
2607   reportTypeStr = get_report_type_string(gInfo);
2608
2609   if (numPages == 0)
2610     numPages++;
2611
2612   /* print creation notice at bottom */ 
2613   cm_strcpy(str2, catgets(c->DT_catd, 1, 468, "Page"));
2614   {
2615     char *to = NULL;
2616     unsigned long to_len = 0;
2617     unsigned long _len;
2618
2619     _len = strlen( str2 );
2620     _converter_( str2, _len, &to, &to_len );
2621     if ( ( to != NULL ) && ( to_len != 0 ) ) {
2622       strncpy( str2, to,
2623               ( BUFFERSIZE > to_len ) ? to_len : BUFFERSIZE );
2624     }
2625   }
2626   cm_strcpy(str2, euc_to_octal(str2));
2627
2628   str = catgets(c->DT_catd, 1, 476, "of");
2629   {
2630     char *to = NULL;
2631     unsigned long to_len = 0;
2632     unsigned long _len;
2633
2634     _len = strlen( str );
2635     _converter_( str, _len, &to, &to_len );
2636     if ( ( to != NULL ) && ( to_len != 0 ) ) {
2637       str = to;
2638     }
2639   }
2640
2641   sprintf(pageStr, "%s %d %s %d", str2, pageNum, str, numPages);
2642
2643   /* Header/footer strings are all set - print 'em! */
2644   cm_print_header_string(gInfo, CP_PRINTLHEADER,
2645                          timeStamp, userId, pageStr, reportTypeStr);
2646   cm_print_header_string(gInfo, CP_PRINTRHEADER,
2647                          timeStamp, userId, pageStr, reportTypeStr);
2648   cm_print_header_string(gInfo, CP_PRINTLFOOTER,
2649                          timeStamp, userId, pageStr, reportTypeStr);
2650   cm_print_header_string(gInfo, CP_PRINTRFOOTER,
2651                          timeStamp, userId, pageStr, reportTypeStr);
2652 }
2653
2654 void
2655 x_day_header (void *gInfoP)
2656 {
2657   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
2658   CMFontInfo *fInfo;
2659   char *str;
2660   Calendar *c = gInfo->c;
2661   int dayBoxVOffset;
2662   int midX;
2663
2664   fInfo = cm_find_font(gInfo, DV_HEADER_FONT);
2665   dayBoxVOffset = (gInfo->normalWd / 2) +
2666     cm_font_height(gInfo, fInfo) + VMARGIN(gInfo);
2667
2668   /* --- print Morning/Afternoon boxes --- */
2669   cm_set_font(gInfo, DV_TIME_FONT);
2670
2671   x_fill_light_box(gInfo, gInfo->u.dayInfo.curX1,
2672                    gInfo->topMarginY + dayBoxVOffset,
2673                    gInfo->rightMarginX - ((gInfo->normalWd + 1) / 2),
2674                    gInfo->topMarginY + dayBoxVOffset + gInfo->u.dayInfo.tab1,
2675                    gInfo->normalWd);
2676
2677   x_fill_dark_box(gInfo, gInfo->u.dayInfo.curX1,
2678                   gInfo->topMarginY + dayBoxVOffset,
2679                   gInfo->u.dayInfo.curX1 + gInfo->u.dayInfo.tab1,
2680                   gInfo->topMarginY + dayBoxVOffset + gInfo->u.dayInfo.tab1,
2681                   gInfo->normalWd);
2682
2683   midX = gInfo->u.dayInfo.curX2;
2684   x_fill_dark_box(gInfo, midX,
2685                   gInfo->topMarginY + dayBoxVOffset,
2686                   midX + gInfo->u.dayInfo.tab1,
2687                   gInfo->topMarginY + dayBoxVOffset + gInfo->u.dayInfo.tab1,
2688                   gInfo->normalWd);
2689
2690   str = catgets(c->DT_catd, 1, 470, "Morning");
2691
2692   {
2693     char *to = NULL;
2694     unsigned long to_len = 0;
2695     unsigned long _len;
2696
2697     _len = strlen( str );
2698     _converter_( str, _len, &to, &to_len );
2699     if ( ( to != NULL ) && ( to_len != 0 ) ) {
2700       str = to;
2701     }
2702   }
2703
2704   x_print_string(gInfo, str,
2705                  (gInfo->u.dayInfo.curX1 + gInfo->u.dayInfo.tab1 + midX) / 2,
2706                  gInfo->topMarginY + dayBoxVOffset +
2707                  (gInfo->u.dayInfo.tab1 / 2),
2708                  CENTER_AT_X | CENTER_AT_Y);
2709
2710   str = catgets(c->DT_catd, 1, 471, "Afternoon");
2711
2712   {
2713     char *to = NULL;
2714     unsigned long to_len = 0;
2715     unsigned long _len;
2716
2717     _len = strlen( str );
2718     _converter_( str, _len, &to, &to_len );
2719     if ( ( to != NULL ) && ( to_len != 0 ) ) {
2720       str = to;
2721     }
2722   }
2723
2724   str = euc_to_octal(str);
2725   x_print_string(gInfo, str,
2726                  (midX + gInfo->u.dayInfo.tab1 + gInfo->rightMarginX
2727                   - ((gInfo->normalWd + 1) / 2)) / 2,
2728                  gInfo->topMarginY + dayBoxVOffset +
2729                  (gInfo->u.dayInfo.tab1 / 2),
2730                  CENTER_AT_X | CENTER_AT_Y);
2731 }
2732
2733 void
2734 x_day_timeslots(void *gInfoP, int i, Boolean more)
2735 {
2736   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
2737
2738   char hourbuf[6];
2739   char modbuf[6];
2740   Calendar *c = gInfo->c;
2741
2742   sprintf (hourbuf, "%d", (morning(i) || (i == 12)) ? i : (i - 12) );
2743   sprintf (modbuf, "%s", morning(i) ? catgets(c->DT_catd, 1, 4, "am") :
2744            catgets(c->DT_catd, 1, 3, "pm"));
2745
2746   /* --- print hourly boxes for appt entries --- */
2747   if (i == 12)
2748   {
2749     gInfo->u.dayInfo.curX1 = gInfo->u.dayInfo.curX2;
2750     gInfo->u.dayInfo.curY1 = gInfo->u.dayInfo.curY2;
2751
2752     /* boxWd may be off by a pixel - set here to ensure correctness. */
2753     gInfo->u.dayInfo.boxWd =
2754       gInfo->rightMarginX - ((gInfo->normalWd + 1) / 2) -
2755         gInfo->u.dayInfo.curX1;
2756   }
2757
2758   x_draw_box(gInfo, gInfo->u.dayInfo.curX1, gInfo->u.dayInfo.curY1,
2759              gInfo->u.dayInfo.curX1 + gInfo->u.dayInfo.boxWd,
2760              gInfo->u.dayInfo.curY1 + gInfo->u.dayInfo.boxHt,
2761              gInfo->normalWd);
2762   x_fill_light_box(gInfo, gInfo->u.dayInfo.curX1,
2763                    gInfo->u.dayInfo.curY1,
2764                    gInfo->u.dayInfo.curX1 + gInfo->u.dayInfo.tab1,
2765                    gInfo->u.dayInfo.curY1 + gInfo->u.dayInfo.boxHt,
2766                    gInfo->normalWd);
2767
2768   cm_set_font(gInfo, DV_TIME_FONT);
2769
2770   x_print_string(gInfo, hourbuf,
2771                  gInfo->u.dayInfo.curX1 + (gInfo->u.dayInfo.tab1 / 2),
2772                  gInfo->u.dayInfo.curY1 + (gInfo->u.dayInfo.boxHt / 2) -
2773                  (VMARGIN(gInfo) / 2),
2774                  CENTER_AT_X | BOTTOM_AT_Y);
2775
2776   x_print_string(gInfo, modbuf,
2777                  gInfo->u.dayInfo.curX1 + (gInfo->u.dayInfo.tab1 / 2),
2778                  gInfo->u.dayInfo.curY1 + (gInfo->u.dayInfo.boxHt / 2) +
2779                  (VMARGIN(gInfo) / 2),
2780                  CENTER_AT_X | TOP_AT_Y);
2781
2782   if (more)
2783     x_print_string(gInfo, "*",
2784                    gInfo->u.dayInfo.curX1 + (gInfo->u.dayInfo.tab1 / 2),
2785                    gInfo->u.dayInfo.curY1 + (gInfo->u.dayInfo.boxHt / 2) +
2786                    cm_font_height(gInfo, gInfo->curFont) + VMARGIN(gInfo),
2787                    CENTER_AT_X | TOP_AT_Y);
2788
2789   gInfo->u.dayInfo.line1 = gInfo->u.dayInfo.curY1 +
2790     ((gInfo->normalWd + 1) / 2) + VMARGIN(gInfo);
2791   gInfo->u.dayInfo.curY1 += gInfo->u.dayInfo.boxHt;
2792 }
2793
2794 Boolean
2795 x_print_multi_appts(void *gInfoP,
2796         CSA_entry_handle *list,
2797         int a_total,
2798         int num_page,
2799         Glance view)
2800 {
2801   /*
2802    * This routine is used to print appointments for day and week
2803    * views.  The parm "view" is used to differentiate
2804    * who is printing, and personalize the print for that view.
2805    */
2806
2807   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
2808   int           indented, indentAmt, multlines=TRUE;
2809   Lines         *lines, *lp;    
2810   char          buf1[128], buf2[257];
2811   Calendar      *c = gInfo->c;  
2812   Props         *pr = (Props*)c->properties;
2813   int           meoval = get_int_prop(pr, CP_PRINTPRIVACY);
2814   int           dt = get_int_prop(pr, CP_DEFAULTDISP);
2815   int           i, j, start, maxlines, pos = 1, line_counter = 0;
2816   Boolean       new_appt = FALSE;
2817   CSA_return_code       stat;
2818   Dtcm_appointment      *appt;
2819
2820   if (view == weekGlance)
2821     maxlines = x_get_week_lines_per_page(gInfoP);
2822   else if (view == dayGlance)
2823     maxlines = x_get_day_lines_per_page(gInfoP);
2824   else maxlines = 1;
2825
2826   start = ((num_page - 1) * maxlines) + 1;
2827
2828   appt = allocate_appt_struct(appt_read,
2829                               c->general->version,
2830                               CSA_ENTRY_ATTR_CLASSIFICATION_I,
2831                               CSA_ENTRY_ATTR_START_DATE_I,
2832                               CSA_ENTRY_ATTR_SUMMARY_I,
2833                               CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,
2834                               CSA_ENTRY_ATTR_END_DATE_I,
2835                               NULL);
2836   for (j = 0; j < a_total; j++) {
2837     stat = query_appt_struct(c->cal_handle, list[j], appt);
2838     if (stat != CSA_SUCCESS) {
2839       free_appt_struct(&appt);
2840       return False;
2841     }
2842
2843     if ((privacy_set(appt) == CSA_CLASS_PUBLIC) && !(meoval & PRINT_PUBLIC))
2844       continue;
2845     if ((privacy_set(appt) == CSA_CLASS_CONFIDENTIAL) &&
2846         !(meoval & PRINT_SEMIPRIVATE))
2847       continue;
2848     if ((privacy_set(appt) == CSA_CLASS_PRIVATE) &&
2849         !(meoval & PRINT_PRIVATE))
2850       continue;
2851
2852     lp = lines = text_to_lines(appt->what->value->item.string_value,
2853                                multlines ? 10 : 1);
2854     new_appt = TRUE;
2855
2856     /* skip past lines already printed */
2857     if (pos < start) {
2858       if (showtime_set(appt)) {
2859         if (new_appt)
2860           for (i = 1; i <= num_page; i++)
2861             if (pos == (maxlines * i))
2862               start--;
2863         pos++;
2864       }
2865       while ((lines != NULL) && (pos < start)) {
2866         pos++;
2867         new_appt = FALSE;
2868         lines = lines->next;
2869       }
2870       if (pos < start) {
2871         continue;
2872       }
2873     }
2874
2875     /* skip last line if it's a time */
2876     if (showtime_set(appt)) {
2877       if (line_counter == (maxlines - 1)) {
2878         free_appt_struct(&appt);
2879         return(FALSE);
2880       }
2881     }
2882
2883     /* HH:MM xm - HH:MM xm format */
2884     format_line2(appt, buf1, buf2, dt);
2885
2886     indented = (*buf1 != NULL);
2887     indentAmt = (view == dayGlance) ? 0 : 1;
2888     if (indented)
2889       indentAmt += 2;
2890
2891     /* only print if appt text found */
2892     if (lines != NULL && lines->s != NULL) {
2893       if ((indented) && (new_appt)) {
2894         line_counter++;
2895         if ((line_counter > maxlines) && (lines != NULL)) {
2896           free_appt_struct(&appt);
2897           return(FALSE);
2898         }
2899
2900         cm_print_time (gInfo, buf1, view);
2901       }
2902
2903       cm_print_appt_text (gInfo, lines->s, indentAmt, view);
2904       line_counter++;
2905       if ((line_counter > maxlines) && (lines != NULL)) {
2906         free_appt_struct(&appt);
2907         return(FALSE);
2908       }
2909
2910       lines = lines->next;
2911       while (lines != NULL) {
2912         line_counter++;
2913         if ((line_counter > maxlines) && (lines != NULL)) {
2914           free_appt_struct(&appt);
2915           return(FALSE);
2916         }
2917
2918         cm_print_appt_text (gInfo, lines->s, indentAmt, view);
2919         lines = lines->next;
2920       }
2921     }
2922     destroy_lines(lp);
2923     if (view == weekGlance)
2924       cm_week_sched_update(gInfo, appt, pr);
2925     new_appt = FALSE;
2926   }
2927   free_appt_struct(&appt);
2928   return(TRUE);
2929 }
2930
2931 void
2932 x_finish_printer(void *gInfoP)
2933 {
2934   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
2935   Widget w = gInfo->drawingArea;
2936
2937 #ifdef GR_DEBUG
2938   if (inDebugMode(gInfo->c))
2939     tmpSpin(w);
2940   else
2941 #endif
2942     XpEndPage(XtDisplay(w));
2943 }
2944
2945 void
2946 x_print_list_range(Calendar *c, CSA_sint32 appt_type, int item_data,
2947                    Tick start_tick, Tick end_tick)
2948 {
2949         char            buf[MAXNAMELEN], buf2[MAXNAMELEN];
2950         void            *xp;
2951         Props           *p = (Props *)c->properties;
2952         Glance          glance;
2953         todo_view_op    todo_view = VIEW_ALL;
2954         OrderingType    ot = get_int_prop(p, CP_DATEORDERING);
2955         time_t          start, end;
2956         CSA_return_code stat;
2957         CSA_entry_handle *list;
2958         CSA_attribute *range_attrs;
2959         CSA_enum *ops;
2960         int i;
2961         CSA_uint32 a_total;
2962
2963         if ((xp = x_open_file(c)) == (void *)NULL)
2964           return;
2965
2966         if (appt_type ==  CSA_TYPE_TODO) {
2967                 todo_view = (todo_view_op)item_data;
2968                 glance = c->view->glance;
2969         } else
2970                 glance = (Glance)item_data;
2971
2972         x_init_printer(xp, PORTRAIT);
2973         x_init_list(xp);
2974
2975         memset(buf, '\0', MAXNAMELEN);
2976         memset(buf2, '\0', MAXNAMELEN);
2977
2978         start = lowerbound(start_tick);
2979         end = nextday(end_tick) - 1;
2980
2981         format_date(start + 1, ot, buf2, 1, 0, 0);
2982
2983         if (appt_type == CSA_TYPE_TODO)
2984                 sprintf(buf, catgets(c->DT_catd, 1, 899,
2985                                      "To Do List Beginning: %s"), buf2);
2986         else
2987                 sprintf(buf, catgets(c->DT_catd, 1, 900,
2988                                      "Appt List Beginning: %s"), buf2);
2989
2990         setup_range(&range_attrs, &ops, &i, start, end, appt_type,
2991                     NULL, B_FALSE, c->general->version);
2992         stat = csa_list_entries(c->cal_handle, i, range_attrs,
2993                                 ops, &a_total, &list, NULL);
2994         if (stat != CSA_SUCCESS) {
2995                 return;
2996         }
2997
2998         x_print_todo(xp, list, a_total, appt_type,
2999                      (start_tick != end_tick), todo_view, end, buf);
3000
3001         csa_free(list);
3002
3003         x_finish_printer(xp);
3004         x_print_file(xp, c);
3005 }
3006
3007 void
3008 x_init_list(void *gInfoP)
3009 {
3010   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3011   CMFontInfo *fInfo;
3012   int hIndent;
3013   int vIndent;
3014
3015   /* We can ONLY get here printing via dialog - printData is valid. */
3016   gInfo->reportType = pd_get_report_type(gInfo->c);
3017
3018   /* Load list fonts */
3019   if (gInfo->nFonts == 0)
3020   {
3021     int i;
3022
3023     if (gInfo->reportType == PR_APPT_LIST)
3024     {
3025       for (i = 0; i < AV_NUM_FONTS; i++)
3026         cm_load_font(gInfo, i, avFonts[i]);
3027     }
3028     else
3029     {
3030       for (i = 0; i < TV_NUM_FONTS; i++)
3031         cm_load_font(gInfo, i, tvFonts[i]);
3032     }
3033
3034     /* Set curFont to first loaded font. */
3035     gInfo->curFont = gInfo->fontInfo;
3036   }
3037
3038   cm_adjust_margins(gInfo);
3039
3040   cm_set_font(gInfo, cm_get_header_enum(gInfo));
3041
3042   hIndent = TODO_HINDENT * gInfo->hscale * gInfo->normalWd;
3043   vIndent = TODO_VINDENT * gInfo->vscale * gInfo->normalWd;
3044   gInfo->u.toDoInfo.outerX1 = gInfo->leftMarginX + (gInfo->thickWd / 2);
3045   gInfo->u.toDoInfo.outerY1 = gInfo->topMarginY + (gInfo->thickWd / 2) +
3046     cm_font_height(gInfo, gInfo->curFont) + VMARGIN(gInfo);
3047   gInfo->u.toDoInfo.innerX1 = gInfo->u.toDoInfo.outerX1 + hIndent;
3048   gInfo->u.toDoInfo.innerY1 = gInfo->u.toDoInfo.outerY1 + vIndent;
3049   gInfo->u.toDoInfo.outerX2 =
3050     gInfo->rightMarginX - ((gInfo->thickWd + 1) / 2);
3051   gInfo->u.toDoInfo.outerY2 =
3052     gInfo->bottomMarginY - ((gInfo->thickWd + 1) / 2);
3053   gInfo->u.toDoInfo.boxX2 = gInfo->u.toDoInfo.outerX2 - hIndent;
3054   gInfo->u.toDoInfo.boxY2 = gInfo->u.toDoInfo.outerY2 - vIndent;
3055   gInfo->u.toDoInfo.boxX1 = gInfo->u.toDoInfo.innerX1;
3056   gInfo->u.toDoInfo.boxY1 = gInfo->u.toDoInfo.boxY2 -
3057     cm_tiny_month_height(gInfo, VMARGIN(gInfo)) - gInfo->thickWd;
3058   gInfo->u.toDoInfo.innerX2 = gInfo->u.toDoInfo.boxX2;
3059   gInfo->u.toDoInfo.innerY2 = gInfo->u.toDoInfo.boxY1 - vIndent;
3060
3061   gInfo->u.toDoInfo.lineX =
3062     gInfo->u.toDoInfo.innerX1 + ((gInfo->thickWd + 1) / 2) + HMARGIN(gInfo);
3063   gInfo->u.toDoInfo.lineY =
3064     gInfo->u.toDoInfo.innerY1 + ((gInfo->thickWd + 1) / 2) + VMARGIN(gInfo);
3065 }
3066
3067 void
3068 x_print_todo(void *gInfoP, CSA_entry_handle *list, int a_total, 
3069              CSA_sint32 appt_type, Boolean showDate, int vf,
3070              time_t end_time, char *buf)
3071 {
3072         CMGraphicsInfo  *gInfo = (CMGraphicsInfo *)gInfoP;
3073         int             i, items_per_page = 0, meoval;
3074         char            buf3[BUFFERSIZE], buf2[BUFFERSIZE], buf1[BUFFERSIZE];
3075         int             total_items = 0;
3076         boolean_t       skip_appt;
3077         CSA_return_code stat;
3078         Dtcm_appointment *appt;
3079         Calendar        *c = gInfo->c;
3080         Props           *p = (Props*)c->properties;
3081         DisplayType     dt = get_int_prop(p, CP_DEFAULTDISP);
3082         OrderingType    ot = get_int_prop(p, CP_DATEORDERING);
3083         SeparatorType   st = get_int_prop(p, CP_DATESEPARATOR);
3084         Tick            start_tick;
3085         int             linesFullPage, linesPartialPage;
3086         int             numAppts, numPages, curPage;
3087
3088         curPage = 1;
3089         cm_get_todo_lines_per_page(gInfo, appt_type, &linesFullPage,
3090                                    &linesPartialPage);
3091         numAppts = cm_count_appts(gInfo, list, a_total, appt_type, vf);
3092         for (numPages = 1, numAppts -= linesPartialPage;
3093              numAppts > 0;
3094              numPages++)
3095           numAppts -= linesFullPage;
3096         x_print_header(gInfoP, buf, curPage, numPages);
3097         cm_todo_outline(gInfo, curPage == numPages);
3098         cm_set_todo_text_clipping(gInfo);
3099
3100         meoval = get_int_prop(p, CP_PRINTPRIVACY);
3101         buf1[0] = buf2[0] = buf3[0] = '\0';
3102
3103         appt = allocate_appt_struct(appt_read,
3104                                     c->general->version,
3105                                     CSA_ENTRY_ATTR_CLASSIFICATION_I,
3106                                     CSA_ENTRY_ATTR_TYPE_I,
3107                                     CSA_ENTRY_ATTR_STATUS_I,
3108                                     CSA_ENTRY_ATTR_START_DATE_I,
3109                                     CSA_ENTRY_ATTR_SUMMARY_I,
3110                                     CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,
3111                                     CSA_ENTRY_ATTR_END_DATE_I,
3112                                     NULL);
3113         for (i = 0; i < a_total; i++)
3114         {
3115           stat = query_appt_struct(c->cal_handle, list[i], appt);
3116           if (stat != CSA_SUCCESS)
3117           {
3118             free_appt_struct(&appt);
3119             return;
3120           }
3121           skip_appt = B_FALSE;
3122
3123           if ((privacy_set(appt) == CSA_CLASS_PUBLIC) &&
3124               !(meoval & PRINT_PUBLIC))
3125             skip_appt = B_TRUE;
3126           else if ((privacy_set(appt) == CSA_CLASS_CONFIDENTIAL) &&
3127                    !(meoval & PRINT_SEMIPRIVATE))
3128             skip_appt = B_TRUE;
3129           else if ((privacy_set(appt) == CSA_CLASS_PRIVATE) &&
3130                    !(meoval & PRINT_PRIVATE))
3131             skip_appt = B_TRUE;
3132
3133           if ((appt_type == CSA_TYPE_TODO) &&
3134               ((appt->type->value->item.sint32_value != CSA_TYPE_TODO)
3135                ||
3136                ((vf == VIEW_PENDING) &&
3137                 (appt->state->value->item.sint32_value ==
3138                  CSA_STATUS_COMPLETED)) ||
3139                ((vf == VIEW_COMPLETED) &&
3140                 (appt->state->value->item.sint32_value ==
3141                  CSA_X_DT_STATUS_ACTIVE))))
3142             skip_appt = B_TRUE;
3143
3144           if ((appt_type == CSA_TYPE_EVENT) &&
3145               (appt->type->value->item.sint32_value != CSA_TYPE_EVENT))
3146             skip_appt = B_TRUE;
3147
3148           if (skip_appt)
3149             continue;
3150
3151           format_maxchars(appt, buf1, BUFFERSIZE - 5, dt);
3152           if (showDate)
3153           {
3154             _csa_iso8601_to_tick(appt->time->value->item.date_time_value,
3155                                  &start_tick);
3156             format_date3(start_tick, ot, st, buf2);
3157             sprintf(buf3, "%s  %s", buf2, buf1);
3158           } else
3159             cm_strcpy(buf3, buf1);
3160
3161           total_items++;
3162           cm_print_todo_text (gInfo, buf3,
3163                               appt->state->value->item.sint32_value,
3164                               appt_type, total_items);
3165           if ((++items_per_page % linesFullPage) == 0)
3166           {
3167             cm_unset_todo_text_clipping(gInfo);
3168             x_finish_printer(gInfoP);
3169             x_init_printer(gInfoP, PORTRAIT);
3170             x_init_list(gInfoP);
3171             x_print_header(gInfoP, buf, ++curPage, numPages);
3172             cm_todo_outline(gInfo, curPage == numPages);
3173             cm_set_todo_text_clipping(gInfo);
3174             items_per_page = 0;
3175           }
3176         } /* end for stmt */
3177
3178         free_appt_struct(&appt);
3179         cm_unset_todo_text_clipping(gInfo);
3180
3181         if (items_per_page > linesPartialPage) {
3182           x_finish_printer(gInfoP);
3183           x_init_printer(gInfoP, PORTRAIT);
3184           x_init_list(gInfoP);
3185           x_print_header(gInfoP, buf, ++curPage, numPages);
3186           cm_todo_outline(gInfo, curPage == numPages);
3187         }
3188
3189         cm_print_todo_months(gInfo, end_time);
3190 }
3191
3192 void
3193 x_print_month(void *gInfoP, int mon, int yr, int x1,
3194               int y1, int x2, int y2, int spacing)
3195 {
3196   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3197   CMFontInfo *fInfo;
3198   Tick j = monthdayyear(mon, 1, yr);        /* starting date Jan 1, y */
3199   int i, colWd, dateWd, monLen;
3200   char str[BUFFERSIZE];
3201
3202   if (mon > 12)
3203     mon = (mon % 13) + 1;
3204   else if (mon < 1)
3205     mon = mon + 12;
3206
3207   x_set_clip_box(gInfo, x1, y1, x2, y2);
3208
3209   cm_set_font(gInfo, cm_get_tiny_title_enum(gInfo));
3210   y1 += spacing;
3211
3212   cm_strcpy(str, months[mon]);
3213
3214   {
3215     char *to = NULL;
3216     unsigned long to_len = 0;
3217     unsigned long _len;
3218
3219     _len = strlen(str);
3220     _converter_( str, _len, &to, &to_len );
3221     if ( ( to != NULL ) && ( to_len != 0 ) ) {
3222       cm_strcpy(str, to);
3223     }
3224   }
3225
3226   cm_strcpy(str, euc_to_octal(str));
3227   x_fill_light_box(gInfo, x1 + HMARGIN(gInfo), y1,
3228                    x2 - HMARGIN(gInfo),
3229                    y1 + cm_font_height(gInfo, gInfo->curFont),
3230                    0);
3231   x_print_string(gInfo, str,
3232                  (x1 + x2) / 2, y1,
3233                  CENTER_AT_X | TOP_AT_Y);
3234   y1 += spacing + cm_font_height(gInfo, gInfo->curFont);
3235
3236   fInfo = cm_find_font(gInfo, cm_get_tiny_date_enum(gInfo));
3237   monLen = monthlength(j);
3238   colWd = 0;
3239   for (i = 0; i < monLen; i++)
3240   {
3241     sprintf(str, "%d", i + 1);
3242     if ((dateWd = cm_string_width(gInfo, fInfo, str)) > colWd)
3243       colWd = dateWd;
3244   }
3245
3246   cm_std_month_weekdays(gInfo, colWd, x1, y1, x2);
3247   y1 += spacing + cm_font_height(gInfo, gInfo->curFont);
3248
3249   cm_std_month_dates(gInfo, fdom(j), monLen, colWd,
3250                      x1, y1, x2, spacing);
3251
3252   x_unset_clip_box(gInfo);
3253 }
3254
3255 void
3256 x_init_std_year(void *gInfoP)
3257 {
3258   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3259   CMFontInfo *fInfo;
3260
3261   gInfo->reportType = PR_YEAR_VIEW;
3262
3263   /* Load year fonts */
3264   if (gInfo->nFonts == 0)
3265   {
3266     int i;
3267
3268     for (i = 0; i < YV_NUM_FONTS; i++)
3269       cm_load_font(gInfo, i, yvFonts[i]);
3270
3271     /* Set curFont to first loaded font. */
3272     gInfo->curFont = gInfo->fontInfo;
3273   }
3274
3275   cm_adjust_margins(gInfo);
3276 }
3277
3278 void
3279 x_std_year_name(void *gInfoP, int yr)
3280 {
3281   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3282   char yearBuf[BUFFERSIZE];
3283
3284   /* --- print year centered at top --- */
3285   sprintf(yearBuf, "%d", yr);
3286   x_print_header(gInfoP, yearBuf, 1, 1);
3287 }
3288
3289 void
3290 x_print_year(void *gInfoP, int yr)
3291 {
3292   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3293   CMFontInfo *fInfo;
3294   int i;
3295   int leftX, topY;
3296   int x1, y1;
3297   int x2, y2;
3298   int row, col;
3299   int pageWd, pageHt;
3300   int monthHt;
3301   int extraSpace;
3302
3303   fInfo = cm_find_font(gInfo, YV_HEADER_FONT);
3304   monthHt = cm_tiny_month_height(gInfo, VMARGIN(gInfo));
3305
3306   leftX = gInfo->leftMarginX;
3307   topY = gInfo->topMarginY + cm_font_height(gInfo, fInfo) + VMARGIN(gInfo);
3308
3309   pageWd = gInfo->rightMarginX - leftX;
3310   pageHt = gInfo->bottomMarginY - topY;
3311   extraSpace = pageHt - (4 * monthHt);
3312
3313   for (i = 0; i < 12; i++)
3314   {
3315     row = i / 3;
3316     col = i % 3;
3317
3318     x1 = leftX + ((col * pageWd) / 3);
3319     x2 = leftX + (((col + 1) * pageWd) / 3);
3320
3321     if (extraSpace > 0)
3322     {
3323       y1 = topY + (((row + 1) * extraSpace) / 5) + (row * monthHt);
3324       y2 = topY + (((row + 2) * extraSpace) / 5) + ((row + 1) * monthHt);
3325     }
3326     else
3327     {
3328       y1 = topY + ((row * pageHt) / 4);
3329       y2 = topY + (((row + 1) * pageHt) / 4);
3330     }
3331
3332     x_print_month(gInfoP, i + 1, yr, x1, y1, x2, y2, VMARGIN(gInfo));
3333   }
3334 }
3335
3336 void
3337 x_init_week(void *gInfoP)
3338 {
3339   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3340   CMFontInfo *fInfo;
3341
3342   gInfo->reportType = PR_WEEK_VIEW;
3343
3344   /* Load week fonts */
3345   if (gInfo->nFonts == 0)
3346   {
3347     int i;
3348
3349     for (i = 0; i < WV_NUM_FONTS; i++)
3350       cm_load_font(gInfo, i, wvFonts[i]);
3351
3352     /* Set curFont to first loaded font. */
3353     gInfo->curFont = gInfo->fontInfo;
3354   }
3355
3356   cm_adjust_margins(gInfo);
3357
3358   fInfo = cm_find_font(gInfo, WV_HEADER_FONT);
3359   gInfo->u.weekInfo.curX1 = gInfo->leftMarginX + (gInfo->thickWd / 2);
3360   gInfo->u.weekInfo.curY1 = gInfo->topMarginY + cm_font_height(gInfo, fInfo) +
3361     VMARGIN(gInfo) + (gInfo->thickWd / 2);
3362   gInfo->u.weekInfo.boxWd =
3363     gInfo->rightMarginX - gInfo->leftMarginX - gInfo->thickWd;
3364   gInfo->u.weekInfo.boxHt =
3365     (gInfo->bottomMarginY - ((gInfo->thickWd + 1) / 2) -
3366      gInfo->u.weekInfo.curY1) / 2;
3367   gInfo->u.weekInfo.curY2 =
3368     gInfo->u.weekInfo.curY1 + gInfo->u.weekInfo.boxHt;
3369
3370   fInfo = cm_find_font(gInfo, WV_DAY_FONT);
3371   gInfo->u.weekInfo.tab1 =
3372     ((3 * cm_font_height(gInfo, fInfo)) +
3373      gInfo->thickWd + gInfo->normalWd) / 2;
3374 }
3375
3376 void
3377 x_week_appt_boxes(void *gInfoP)
3378 {
3379   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3380   int x1, y1, x2, y2;
3381   int innerWd, innerOffset;
3382   int i;
3383
3384   /* Draw weekdays box. */
3385   x1 = gInfo->u.weekInfo.curX1;
3386   y1 = gInfo->u.weekInfo.curY1;
3387   x2 = x1 + gInfo->u.weekInfo.boxWd;
3388   y2 = y1 + gInfo->u.weekInfo.tab1;
3389
3390   x_fill_light_box(gInfo, x1, y1, x2, y2, gInfo->normalWd);
3391
3392   y2 = gInfo->u.weekInfo.curY2;
3393   x_draw_box(gInfo, x1, y1, x2, y2, gInfo->thickWd);
3394
3395   /* Draw weekdays vertical lines. */
3396   innerWd = gInfo->u.weekInfo.boxWd - gInfo->thickWd + gInfo->normalWd;
3397   innerOffset = ((gInfo->thickWd - 1) / 2) - ((gInfo->normalWd - 1) / 2);
3398   for (i = 1; i < WEEK_DAYS; i++)
3399   {
3400     x1 = gInfo->u.weekInfo.curX1 + innerOffset + ((i * innerWd) / WEEK_DAYS);
3401     x_draw_line(gInfo, x1, y1, x1, y2, gInfo->normalWd);
3402   }
3403
3404   /* Draw weekends box. */
3405   x1 = gInfo->u.weekInfo.curX1 +
3406     (((WEEK_DAYS - WEEKEND_DAYS) * gInfo->u.weekInfo.boxWd) / WEEK_DAYS);
3407   y1 = y2;
3408   y2 = y1 + gInfo->u.weekInfo.tab1;
3409   x_fill_light_box(gInfo, x1, y1, x2, y2, gInfo->normalWd);
3410
3411   y2 = gInfo->bottomMarginY - ((gInfo->thickWd + 1) / 2);
3412   x_draw_box(gInfo, x1, y1, x2, y2, gInfo->thickWd);
3413
3414   /* Draw weekends vertical lines. */
3415   for (i = WEEK_DAYS - WEEKEND_DAYS + 1; i < WEEK_DAYS; i++)
3416   {
3417     x1 = gInfo->u.weekInfo.curX1 + innerOffset + ((i * innerWd) / WEEK_DAYS);
3418     x_draw_line(gInfo, x1, y1, x1, y2, gInfo->normalWd);
3419   }
3420 }
3421
3422 void
3423 x_week_sched_boxes(void *gInfoP)
3424 {
3425   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3426   char *day_of_week[DAYS_IN_WEEK];
3427   char hourBuf[BUFFERSIZE];
3428   Props *p = (Props *)gInfo->c->properties;
3429   int begin = get_int_prop(p, CP_DAYBEGIN);
3430   int end = get_int_prop(p, CP_DAYEND);
3431   DisplayType dt = get_int_prop(p, CP_DEFAULTDISP);
3432   int thisHour;
3433   int num_hours;
3434   int boxIndent;
3435   int boxX1, boxY1, boxX2, boxY2, boxWd, boxHt;
3436   int x1, y1, x2, y2;
3437   int i;
3438   int ulOff = gInfo->thickWd / 2;
3439   int brOff = (gInfo->thickWd - 1) / 2;
3440
3441   /* --- print week sched boxes --- */
3442
3443   /* figure out number of partitions in sched box */
3444   num_hours = end - begin;
3445
3446   /* determine offset of sched box from left margin */
3447   cm_set_font(gInfo, WV_DAY_FONT);
3448   boxIndent = cm_week_sched_box_indent(gInfo);
3449   boxX1 = gInfo->u.weekInfo.curX1 + boxIndent;
3450   boxX2 = gInfo->u.weekInfo.curX1 +
3451     ((3 * gInfo->u.weekInfo.boxWd) / WEEK_DAYS) - boxIndent;
3452   boxY1 = gInfo->u.weekInfo.curY2 +
3453     (2 * cm_font_height(gInfo, gInfo->curFont)) +
3454       gInfo->thickWd;
3455   boxY2 = gInfo->bottomMarginY - 1 - brOff;
3456
3457   x_draw_box(gInfo, boxX1, boxY1, boxX2, boxY2, gInfo->thickWd);
3458
3459   boxX1 += brOff - ((gInfo->normalWd - 1) / 2);
3460   boxX2 -= ulOff - (gInfo->normalWd / 2);
3461   boxY1 += brOff - ((gInfo->thinWd - 1) / 2);
3462   boxY2 -= ulOff - (gInfo->thinWd / 2);
3463   boxWd = boxX2 - boxX1;
3464   boxHt = boxY2 - boxY1;
3465
3466   for (i = 0; i < DAYS_IN_WEEK; i++)
3467     local_dayname(gInfo->c, &day_of_week[i], (i + 1) % DAYS_IN_WEEK);
3468
3469   /* print abbreviated weekdays on top and draw vertical lines. */
3470   for (i = 0; i < DAYS_IN_WEEK; i++)
3471   {
3472     x1 = boxX1 + ((i * boxWd) / DAYS_IN_WEEK);
3473     x2 = boxX1 + (((i + 1) * boxWd) / DAYS_IN_WEEK);
3474
3475     x_print_string(gInfo, day_of_week[i],
3476                    (x1 + x2) / 2, boxY1 -
3477                    gInfo->thickWd - (2 * VMARGIN(gInfo)),
3478                    CENTER_AT_X | BOTTOM_AT_Y);
3479     free(day_of_week[i]);
3480     if (i > 0)
3481       x_draw_line(gInfo, x1, boxY1, x1, boxY2, gInfo->normalWd);
3482   }
3483
3484   /* Print hours and horizontal lines. */
3485   for (thisHour = begin, i = 0; i <= num_hours; i++, thisHour++)
3486   {
3487     if ( dt == HOUR12 )
3488     {
3489       if (thisHour > 12)
3490         thisHour %= 12;
3491     }
3492     else if ( dt == HOUR24 )
3493     {
3494       if (thisHour > 24)
3495         thisHour %= 24;
3496     }
3497     sprintf(hourBuf, "%d", thisHour);
3498     y1 = boxY1 + ((i * boxHt) / num_hours);
3499
3500     x_print_string(gInfo, hourBuf,
3501                    boxX1 - gInfo->thickWd - HMARGIN(gInfo), y1,
3502                    RIGHT_AT_X | CENTER_AT_Y);
3503
3504     if ((i > 0) && (i < num_hours))
3505       x_draw_line(gInfo, boxX1, y1, boxX2, y1, gInfo->thinWd);
3506   }
3507
3508   gInfo->u.weekInfo.schedBoxX1 = boxX1;
3509   gInfo->u.weekInfo.schedBoxY1 = boxY1;
3510   gInfo->u.weekInfo.schedBoxX2 = boxX2;
3511   gInfo->u.weekInfo.schedBoxY2 = boxY2;
3512 }
3513
3514 void
3515 x_week_daynames(void *gInfoP, char *dayName, int dayIndex, Boolean more)
3516 {
3517   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3518   Calendar *c = gInfo->c;
3519   int x1, y1, x2, y2;
3520   int innerOffset, innerWd;
3521   char dayBuf[BUFFERSIZE];
3522
3523   y1 = (dayIndex < WEEK_DAYS) ? gInfo->u.weekInfo.curY1 :
3524     gInfo->u.weekInfo.curY2;
3525   y2 = y1 + gInfo->u.weekInfo.tab1;
3526
3527   cm_set_font(gInfo, WV_DAY_FONT);
3528
3529   innerWd = gInfo->u.weekInfo.boxWd - gInfo->thickWd + gInfo->normalWd;
3530   innerOffset = ((gInfo->thickWd - 1) / 2) - ((gInfo->normalWd - 1) / 2);
3531
3532   if (dayIndex >= WEEK_DAYS)
3533     dayIndex -= WEEKEND_DAYS;
3534   x1 = gInfo->u.weekInfo.curX1 + innerOffset +
3535     ((dayIndex * innerWd) / WEEK_DAYS);
3536   x2 = gInfo->u.weekInfo.curX1 + innerOffset +
3537     (((dayIndex + 1) * innerWd) / WEEK_DAYS);
3538
3539   {
3540     char *to = NULL;
3541     unsigned long to_len = 0;
3542     unsigned long _len;
3543
3544     _len = strlen(dayName);
3545     _converter_( dayName, _len, &to, &to_len );
3546     if ( ( to != NULL ) && ( to_len != 0 ) ) {
3547       dayName = to;
3548     }
3549   }
3550
3551   sprintf(dayBuf, more ? "%s *" : "%s", euc_to_octal(dayName));
3552   x_print_string(gInfo, dayBuf, (x1 + x2) / 2, (y1 + y2) / 2,
3553                  CENTER_AT_X | CENTER_AT_Y);
3554
3555   gInfo->u.weekInfo.lineX = x1;
3556   gInfo->u.weekInfo.lineY = y2 + ((gInfo->normalWd + 1) / 2) + VMARGIN(gInfo);
3557   gInfo->u.weekInfo.lineMaxY = y1 + gInfo->u.weekInfo.boxHt;
3558 }
3559
3560 void
3561 x_week_sched_init(void *gInfoP)
3562 {
3563   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3564
3565   memset(gInfo->u.weekInfo.schedBucket, 0,
3566          sizeof(gInfo->u.weekInfo.schedBucket));
3567 }
3568
3569 void
3570 x_week_sched_draw(void *gInfoP, int dayIndex)
3571 {
3572   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3573   int i;
3574   Props *p = (Props *)gInfo->c->properties;
3575   int begin = get_int_prop(p, CP_DAYBEGIN);
3576   int end = get_int_prop(p, CP_DAYEND);
3577   int num_hours = end - begin;
3578   int nIntervals = num_hours * 4;
3579   int x1, y1, x2, y2;
3580   int boxWd = gInfo->u.weekInfo.schedBoxX2 - gInfo->u.weekInfo.schedBoxX1;
3581   int boxHt = gInfo->u.weekInfo.schedBoxY2 - gInfo->u.weekInfo.schedBoxY1;
3582   int currColor, lastColor;
3583   int tOffset, bOffset;
3584
3585   x1 = gInfo->u.weekInfo.schedBoxX1 +
3586     ((dayIndex * boxWd) / DAYS_IN_WEEK) + ((gInfo->normalWd + 1) / 2);
3587   x2 = gInfo->u.weekInfo.schedBoxX1 +
3588     (((dayIndex + 1) * boxWd) / DAYS_IN_WEEK) - (gInfo->normalWd / 2) - 1;
3589
3590   lastColor = 0;
3591   for (i = 0; i < nIntervals; i++)
3592   {
3593     y1 = gInfo->u.weekInfo.schedBoxY1 + ((i * boxHt) / nIntervals);
3594     y2 = gInfo->u.weekInfo.schedBoxY1 + (((i + 1) * boxHt) / nIntervals);
3595     switch (gInfo->u.weekInfo.schedBucket[i])
3596     {
3597     case 0:
3598       currColor = 0;
3599       break;
3600
3601     case 1:
3602       currColor = 1;
3603       tOffset = (i % 4) ? 0 : ((gInfo->thinWd + 1) / 2);
3604       bOffset = ((i + 1) % 4) ? 1 : (gInfo->thinWd / 2) + 1;
3605       x_fill_dark_box(gInfo, x1, y1 + tOffset, x2,
3606                       y2 - bOffset, 0);
3607       break;
3608
3609     default:
3610       currColor = 2;
3611       x_fill_black_box(gInfo, x1, y1, x2, y2);
3612       break;
3613     }
3614
3615     if (currColor != lastColor)
3616     {
3617       if ((currColor != 2) && (lastColor != 2))
3618         x_draw_line(gInfo, x1, y1, x2 + 1, y1, gInfo->thinWd);
3619       lastColor = currColor;
3620     }
3621   }
3622 }
3623
3624 void
3625 x_init_month(void *gInfoP, int nRows)
3626 {
3627   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3628   CMFontInfo *fInfo;
3629
3630   gInfo->reportType = PR_MONTH_VIEW;
3631
3632   /* Load month fonts */
3633   if (gInfo->nFonts == 0)
3634   {
3635     int i;
3636
3637     for (i = 0; i < MV_NUM_FONTS; i++)
3638       cm_load_font(gInfo, i, mvFonts[i]);
3639
3640     /* Set curFont to first loaded font. */
3641     gInfo->curFont = gInfo->fontInfo;
3642   }
3643
3644   cm_adjust_margins(gInfo);
3645
3646   /* --- init for month view print --- */
3647   fInfo = cm_find_font(gInfo, MV_HEADER_FONT);
3648   gInfo->u.monthInfo.curX1 = gInfo->leftMarginX + (gInfo->normalWd / 2);
3649   gInfo->u.monthInfo.curY1 =
3650     gInfo->topMarginY + cm_font_height(gInfo, fInfo) +
3651       VMARGIN(gInfo) + (gInfo->normalWd / 2);
3652   gInfo->u.monthInfo.boxWd =
3653     gInfo->rightMarginX - gInfo->leftMarginX - gInfo->normalWd;
3654   gInfo->u.monthInfo.boxHt =
3655     gInfo->bottomMarginY - ((gInfo->normalWd + 1) / 2) -
3656       gInfo->u.monthInfo.curY1;
3657   fInfo = cm_find_font(gInfo, MV_DAY_FONT);
3658   gInfo->u.monthInfo.tab1 = 2 * cm_font_height(gInfo, fInfo);
3659   gInfo->u.monthInfo.nRows = nRows;
3660 }
3661
3662 int
3663 x_get_month_lines_per_page(void *gInfoP)
3664 {
3665   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3666   CMFontInfo *fInfo = cm_find_font(gInfo, MV_APPT_FONT);
3667   CMFontInfo *dateFInfo = cm_find_font(gInfo, MV_DATE_FONT);
3668   int dateSz = HMARGIN(gInfo) + cm_font_height(gInfo, dateFInfo);
3669
3670   return (((gInfo->u.monthInfo.boxHt - gInfo->u.monthInfo.tab1) /
3671            gInfo->u.monthInfo.nRows) -
3672           gInfo->normalWd - dateSz - (2 * VMARGIN(gInfo))) /
3673     cm_font_height(gInfo, fInfo);
3674 }
3675
3676 void
3677 x_month_daynames(void *gInfoP, int nRows)
3678 {
3679   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3680   char *day_of_week[DAYS_IN_WEEK];
3681   int i;
3682   Calendar *c = gInfo->c;
3683   int x1, y1, x2, y2;
3684   int dayBoxHt;
3685
3686   for (i = 0; i < DAYS_IN_WEEK; i++)
3687     local_dayname3(gInfo->c, &(day_of_week[i]), i);
3688
3689   /* Draw outer box. */
3690   x1 = gInfo->u.monthInfo.curX1;
3691   y1 = gInfo->u.monthInfo.curY1;
3692   x2 = x1 + gInfo->u.monthInfo.boxWd;
3693   y2 = y1 + gInfo->u.monthInfo.boxHt;
3694   x_draw_box(gInfo, x1, y1, x2, y2, gInfo->normalWd);
3695
3696   /* Draw box around days. */
3697   y2 = y1 + gInfo->u.monthInfo.tab1;
3698   x_fill_dark_box(gInfo, x1, y1, x2, y2, gInfo->normalWd);
3699
3700   cm_set_font(gInfo, MV_DAY_FONT);
3701   for (i = 0; i < DAYS_IN_WEEK; i++)
3702   {
3703     x1 = gInfo->u.monthInfo.curX1 +
3704       ((i * gInfo->u.monthInfo.boxWd) / DAYS_IN_WEEK);
3705     x2 = gInfo->u.monthInfo.curX1 +
3706       (((i + 1) * gInfo->u.monthInfo.boxWd) / DAYS_IN_WEEK);
3707
3708     cm_reverse_video(gInfo, True);
3709     x_print_string(gInfo, day_of_week[i],
3710                    (x1 + x2) / 2, (y1 + y2) / 2,
3711                    CENTER_AT_X | CENTER_AT_Y);
3712     free(day_of_week[i]);
3713
3714     cm_reverse_video(gInfo, False);
3715     if (i != 0)
3716       x_draw_line(gInfo, x1, y1, x1, y1 + gInfo->u.monthInfo.boxHt,
3717                   gInfo->normalWd);
3718   }
3719
3720   x1 = gInfo->u.monthInfo.curX1;
3721   x2 = x1 + gInfo->u.monthInfo.boxWd;
3722   dayBoxHt = gInfo->u.monthInfo.boxHt - gInfo->u.monthInfo.tab1;
3723
3724   /* Draw horizontal lines. */
3725   for (i = 1; i < nRows; i++)
3726   {
3727     y1 = gInfo->u.monthInfo.curY1 + gInfo->u.monthInfo.tab1 +
3728       ((i * dayBoxHt) / nRows);
3729     x_draw_line(gInfo, x1, y1, x2, y1, gInfo->normalWd);
3730   }
3731 }
3732
3733 void
3734 x_print_little_months(void *gInfoP, Tick tick)
3735 {
3736   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3737   int m = month(tick);          /* current month just printed */
3738   int y = year(tick);           /* year of month just printed */
3739   int fday = fdom(tick);        /* first day of month, 0=Sun ... */
3740
3741   int nm, nmy, pm, pmy;
3742
3743   int ndays = monthlength(tick);
3744   int nrows = gInfo->u.monthInfo.nRows;
3745   int pmIndex;
3746   int i, nBoxes;
3747   int x1, y1, x2, y2;
3748   int boxX1, boxY1, boxWd, boxHt;
3749   int ulOffset, brOffset;
3750   int dayRow, dayCol;
3751   int spacing;
3752
3753   /* 
3754    * Print out miniature prev & next month on month grid.
3755    * Check if there is enough room at end;  if not then
3756    * print at beginning of grid.
3757    */
3758   nBoxes = nrows * DAYS_IN_WEEK;
3759   if ((fday + ndays + 2) <= nBoxes)
3760   {
3761     pmIndex = nBoxes - 2;
3762   }
3763   else
3764   {
3765     pmIndex = 0;
3766   }
3767
3768   if (m == 12)
3769   {
3770     nm = 1;
3771     nmy = y + 1;
3772     pm = m - 1;
3773     pmy = y;
3774   }
3775   else if (m == 1)
3776   {
3777     nm = m + 1;
3778     nmy = y;
3779     pm = 12;
3780     pmy = y - 1;
3781   }
3782   else
3783   {
3784     nm = m + 1;
3785     pm = m - 1;
3786     nmy = pmy = y;
3787   }
3788
3789   boxX1 = gInfo->u.monthInfo.curX1;
3790   boxY1 = gInfo->u.monthInfo.curY1 + gInfo->u.monthInfo.tab1;
3791   boxWd = gInfo->u.monthInfo.boxWd;
3792   boxHt = gInfo->u.monthInfo.boxHt - gInfo->u.monthInfo.tab1;
3793   ulOffset = (gInfo->normalWd + 1) / 2;
3794   brOffset = (gInfo->normalWd / 2) + 1;
3795
3796   /* Determine spacing for drawing little months.  Can be negative. */
3797   for (spacing = VMARGIN(gInfo);
3798        cm_tiny_month_height(gInfo, spacing) >
3799        (boxHt / nrows) - gInfo->normalWd;
3800        spacing--)
3801     ;
3802
3803   /* Gray out extra boxes. */
3804   y1 = boxY1 + ulOffset;
3805   y2 = boxY1 - brOffset + (boxHt / nrows);
3806   for (i = 0; i < fday; i++)
3807   {
3808     x1 = boxX1 + ((i * boxWd) / DAYS_IN_WEEK) + ulOffset;
3809     x2 = boxX1 + (((i + 1) * boxWd) / DAYS_IN_WEEK) - brOffset;
3810
3811     x_fill_light_box(gInfo, x1, y1, x2, y2, 0);
3812
3813     if (i == pmIndex)
3814       x_print_month(gInfoP, pm, pmy, x1, y1, x2, y2, spacing);
3815     else if (i == (pmIndex + 1))
3816       x_print_month(gInfoP, nm, nmy, x1, y1, x2, y2, spacing);
3817   }
3818
3819   dayRow = (nBoxes - 1) / DAYS_IN_WEEK;
3820   y1 = boxY1 + ((dayRow * boxHt) / nrows) + ulOffset;
3821   y2 = boxY1 + (((dayRow + 1) * boxHt) / nrows) - brOffset;
3822   for (i = fday + ndays; i < nBoxes; i++)
3823   {
3824     dayCol = i % DAYS_IN_WEEK;
3825     x1 = boxX1 + ((dayCol * boxWd) / DAYS_IN_WEEK) + ulOffset;
3826     x2 = boxX1 + (((dayCol + 1) * boxWd) / DAYS_IN_WEEK) - brOffset;
3827
3828     x_fill_light_box(gInfo, x1, y1, x2, y2, 0);
3829
3830     if (i == pmIndex)
3831       x_print_month(gInfoP, pm, pmy, x1, y1, x2, y2, spacing);
3832     else if (i == (pmIndex + 1))
3833       x_print_month(gInfoP, nm, nmy, x1, y1, x2, y2, spacing);
3834   }
3835 }
3836
3837 void
3838 x_month_timeslots(void *gInfoP, Tick tick, Boolean more)
3839 {
3840   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3841   int fday = fdom(tick);        /* first day of month, 0=Sun ... */
3842   int thisDay = dom(tick);
3843   int nrows = gInfo->u.monthInfo.nRows;
3844   int x1, y1;
3845   int boxX1, boxY1, boxWd, boxHt;
3846   int ulOffset, brOffset;
3847   int dayRow, dayCol;
3848   char dateBuf[BUFFERSIZE];
3849
3850   boxX1 = gInfo->u.monthInfo.curX1;
3851   boxY1 = gInfo->u.monthInfo.curY1 + gInfo->u.monthInfo.tab1;
3852   boxWd = gInfo->u.monthInfo.boxWd;
3853   boxHt = gInfo->u.monthInfo.boxHt - gInfo->u.monthInfo.tab1;
3854   ulOffset = (gInfo->normalWd + 1) / 2;
3855   brOffset = (gInfo->normalWd / 2) + 1;
3856
3857   /* Write date into appropriate box. */
3858   cm_set_font(gInfo, MV_DATE_FONT);
3859   dayRow = (thisDay + fday - 1) / DAYS_IN_WEEK;
3860   dayCol = (thisDay + fday - 1) % DAYS_IN_WEEK;
3861
3862   gInfo->u.monthInfo.lineY = boxY1 + ((dayRow * boxHt) / nrows);
3863   gInfo->u.monthInfo.lineX = boxX1 + ((dayCol * boxWd) / DAYS_IN_WEEK);
3864   gInfo->u.monthInfo.lastX = gInfo->u.monthInfo.lineX + ulOffset;
3865   gInfo->u.monthInfo.lineMaxY = boxY1 + (((dayRow + 1) * boxHt) / nrows);
3866   gInfo->u.monthInfo.lineMaxX = boxX1 + (((dayCol + 1) * boxWd) /
3867                                          DAYS_IN_WEEK);
3868   y1 = gInfo->u.monthInfo.lineY + ulOffset + HMARGIN(gInfo);
3869   x1 = gInfo->u.monthInfo.lineX + ulOffset + VMARGIN(gInfo);
3870
3871   sprintf(dateBuf, more ? "%d *" : "%d", thisDay);
3872   x_print_string(gInfo, dateBuf, x1, y1, LEFT_AT_X | TOP_AT_Y);
3873
3874   gInfo->u.monthInfo.lineY =
3875     y1 + cm_font_height(gInfo, gInfo->curFont) + VMARGIN(gInfo);
3876 }
3877
3878 Boolean
3879 x_print_month_appts(void *gInfoP, CSA_entry_handle *list,
3880                     int a_total, int num_page,
3881                     time_t hi_hour, int lines_per_box)
3882 {
3883   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3884   int indented;
3885   Lines *lines;
3886   char buf1[BUFFERSIZE];
3887   Calendar *c = gInfo->c;
3888   Props *pr = (Props *)c->properties;
3889   int meoval = get_int_prop(pr, CP_PRINTPRIVACY);
3890   int i, start, pos = 1, line_counter = 0;      
3891   CSA_return_code stat;
3892   Dtcm_appointment *appt;
3893   Tick start_tick;
3894
3895   start = ((num_page - 1) * lines_per_box) + 1;
3896
3897   appt = allocate_appt_struct(appt_read,
3898                               c->general->version,
3899                               CSA_ENTRY_ATTR_CLASSIFICATION_I,
3900                               CSA_ENTRY_ATTR_START_DATE_I,
3901                               CSA_ENTRY_ATTR_SUMMARY_I,
3902                               CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,
3903                               NULL);
3904   for (i = 0; i < a_total; i++)
3905   {
3906     stat = query_appt_struct(c->cal_handle, list[i], appt);
3907     if (stat != CSA_SUCCESS)
3908     {
3909       free_appt_struct(&appt);
3910       return False;
3911     }
3912
3913     _csa_iso8601_to_tick(appt->time->value->item.date_time_value, &start_tick);
3914     if (start_tick >= hi_hour)
3915     {
3916       free_appt_struct(&appt);
3917       return True;
3918     }
3919  
3920     if ((privacy_set(appt) == CSA_CLASS_PUBLIC) &&
3921         !(meoval & PRINT_PUBLIC))
3922       continue;
3923     if ((privacy_set(appt) == CSA_CLASS_CONFIDENTIAL) &&
3924         !(meoval & PRINT_SEMIPRIVATE))
3925       continue;
3926     if ((privacy_set(appt) == CSA_CLASS_PRIVATE) &&
3927         !(meoval & PRINT_PRIVATE))
3928       continue;
3929
3930     if (pos < start)
3931     {
3932       pos++;
3933     }
3934     else
3935     {
3936       get_time_str(appt, buf1);
3937
3938       indented = (*buf1 != NULL);
3939
3940       lines = text_to_lines(appt->what->value->item.string_value, 1);
3941       line_counter++;
3942       if ((line_counter > lines_per_box) && (lines != NULL))
3943       {
3944         free_appt_struct(&appt);
3945         return(False);
3946       }
3947
3948       /* only print if appt text found */ 
3949       if ((lines != NULL) && (lines->s != NULL))
3950       {
3951         if (indented)   /* time found so print it */
3952           cm_print_month_time(gInfo, buf1);
3953         cm_print_month_text(gInfo, lines->s, indented ? 2 : 0);
3954       }
3955
3956       destroy_lines(lines);
3957     }
3958   }
3959
3960   free_appt_struct(&appt);
3961   return(True);
3962 }