ad85028664de7b8b406f21551e2205d10dca3000
[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 #if defined(PRINTING_SUPPORTED)
2232
2233 #ifdef GR_DEBUG
2234   if (!inDebugMode(c))
2235   {
2236 #endif
2237     if (pd_print_to_file(c))
2238     {
2239       char *fileName = pd_get_file_name(c);
2240
2241       /* Protocol says XpStartJob() MUST be called before XmPrintToFile() */
2242       XpStartJob(XtDisplay(printShell), XPGetData);
2243
2244       XFlush(XtDisplay(printShell));
2245
2246       if (!XmPrintToFile(XtDisplay(printShell), fileName,
2247                          filePrintDoneCB, (XtPointer)c))
2248       {
2249           XpCancelJob(XtDisplay(printShell), False);
2250
2251           XtFree(fileName);
2252           XtFree((char *)gInfo);
2253
2254           filePrintReportStatus(c, False);
2255
2256           return (void *)NULL;
2257       }
2258       XtFree(fileName);
2259     }
2260     else
2261     {
2262       XpStartJob(XtDisplay(printShell), XPSpool);
2263     }
2264 #ifdef GR_DEBUG
2265   }
2266 #endif
2267 #endif  /* PRINTING_SUPPORTED */
2268
2269
2270   nargs = 0;
2271 #ifdef SHELL_SIZE_BUG
2272   XtSetArg(args[nargs], XmNwidth, &shellWd); nargs++;
2273   XtSetArg(args[nargs], XmNheight, &shellHt); nargs++;
2274 #endif /* SHELL_SIZE_BUG */
2275   XtSetArg(args[nargs], XmNchildren, &shellChildren); nargs++;
2276   XtSetArg(args[nargs], XmNnumChildren, &nChildren); nargs++;
2277   XtGetValues(printShell, args, nargs);
2278
2279 #ifdef SHELL_SIZE_BUG
2280   if ((shellWd < 10) || (shellHt < 10))
2281   {
2282     shellWd = XmConvertUnits(printShell, XmHORIZONTAL, Xm1000TH_INCHES,
2283                              PAGE_WIDTH, XmPIXELS);
2284     shellHt = XmConvertUnits(printShell, XmVERTICAL, Xm1000TH_INCHES,
2285                              PAGE_HEIGHT, XmPIXELS);
2286
2287     nargs = 0;
2288     XtSetArg(args[nargs], XmNwidth, shellWd); nargs++;
2289     XtSetArg(args[nargs], XmNheight, shellHt); nargs++;
2290     XtSetValues(printShell, args, nargs);
2291   }
2292 #endif /* SHELL_SIZE_BUG */
2293
2294   if (nChildren == 0)
2295   {
2296     nargs = 0;
2297     XtSetArg(args[nargs], XmNunitType, XmPIXELS); nargs++;
2298 #ifdef GR_DEBUG
2299     if (!inDebugMode(c))
2300     {
2301 #endif
2302       XtSetArg(args[nargs], XmNbackground,
2303                WhitePixelOfScreen(XtScreen(printShell))); nargs++;
2304 #ifdef GR_DEBUG
2305     }
2306 #endif
2307     drawingArea = XmCreateDrawingArea(printShell, "PrintArea",
2308                                       args, nargs);
2309   }
2310   else
2311     drawingArea = shellChildren[0];
2312
2313 #ifdef GR_DEBUG
2314   if (inDebugMode(c))
2315     XtAddCallback(drawingArea, XmNinputCallback,
2316                   tmpFn, (XtPointer)NULL);
2317 #endif
2318
2319   gInfo->drawingArea = drawingArea;
2320   gInfo->gc = XtAllocateGC(drawingArea, 0, 0, NULL, gcMask, 0);
2321   gInfo->c = c;
2322   gInfo->reportType = PR_MONTH_VIEW; /* Set properly in x_init_*() */
2323
2324   gInfo->fontInfo = gInfo->curFont = (CMFontInfo *)NULL;
2325   gInfo->nFonts = 0;
2326
2327   gInfo->reverseVideo = False;
2328   gInfo->fg = BlackPixelOfScreen(XtScreen(drawingArea));
2329   gInfo->bg = WhitePixelOfScreen(XtScreen(drawingArea));
2330 #ifdef GR_DEBUG
2331   nargs = 0;
2332   XtSetArg(args[nargs], XmNforeground, &(gInfo->fg)); nargs++;
2333   XtSetArg(args[nargs], XmNbackground, &(gInfo->bg)); nargs++;
2334   XtGetValues(drawingArea, args, nargs);
2335 #endif
2336   gInfo->lightPixmap = None;
2337   gInfo->darkPixmap = None;
2338
2339   /* set up time stamp */
2340   /* STRING_EXTRACTION SUNW_DESKSET_CM_MSG
2341    * The following string is the date/time format used in printing out
2342    * calendar views.  This is the locale's date and time.  If this string
2343    * is to be translated, please refer to the man pages for strftime()
2344    * for various format strings.
2345    */
2346   t = now();
2347   tm = _XLocaltime(&t, localtime_buf);
2348   strftime(gInfo->timestamp, BUFFERSIZE, "%x %I:%M %p", tm);
2349
2350   {
2351     char *to = NULL;
2352     unsigned long to_len = 0;
2353     unsigned long _len;
2354
2355     _len = strlen( gInfo->timestamp );
2356     _converter_( gInfo->timestamp, _len, &to, &to_len );
2357     if ( ( to != NULL ) && ( to_len != 0 ) )
2358       strncpy( gInfo->timestamp, to,
2359               ( BUFFERSIZE > to_len ) ? to_len : BUFFERSIZE - 1 );
2360   }
2361
2362   return (void *)gInfo;
2363 }
2364
2365 void
2366 x_print_file(void *gInfoP, Calendar *c)
2367 {
2368   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
2369   Display *dsp = XtDisplay(gInfo->drawingArea);
2370
2371 #ifdef GR_DEBUG
2372   if (!inDebugMode(c))
2373 #endif
2374   {
2375     XpEndJob(dsp);
2376
2377     /* Make sure we know about a BadAlloc if it happens. */
2378     XSync(XtDisplay(gInfo->drawingArea), FALSE);
2379   }
2380
2381   if (pd_get_bad_alloc_error(c) &&
2382       (!pd_print_to_file(c)))
2383   {
2384     showBadAllocError(c);
2385     pd_set_bad_alloc_error(c, False);
2386   }
2387
2388   if (gInfo->lightPixmap != None)
2389     XFreePixmap(dsp, gInfo->lightPixmap);
2390   if (gInfo->darkPixmap != None)
2391     XFreePixmap(dsp, gInfo->darkPixmap);
2392
2393   XtReleaseGC(gInfo->drawingArea, gInfo->gc);
2394
2395   cm_release_fonts(gInfo);
2396
2397   XtFree((char *)gInfo);
2398 }
2399
2400 void
2401 x_init_printer(void *gInfoP, short orientation)
2402 {
2403   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
2404   Widget w = gInfo->drawingArea;
2405   Arg args[10];
2406   int nargs;
2407   unsigned int pageWd, pageHt;
2408   int baseWd, baseHt;
2409   int rMargin, bMargin;
2410   int inchWd;
2411   Dimension daWd, daHt;
2412
2413 #ifdef GR_DEBUG
2414   if (inDebugMode(gInfo->c))
2415   {
2416     XtAddCallback(w, XmNexposeCallback,
2417                   tmpFn, (XtPointer)NULL);
2418   }
2419   else
2420 #endif
2421     XpStartPage(XtDisplay(w), XtWindow(XtParent(w)));
2422
2423   /* XpStartPage() sets the shell width/height correctly. */
2424   nargs = 0;
2425   XtSetArg(args[nargs], XmNwidth, &daWd); nargs++;
2426   XtSetArg(args[nargs], XmNheight, &daHt); nargs++;
2427   XtGetValues(XtParent(w), args, nargs);
2428
2429   if (XtIsRealized(w))
2430   {
2431     XClearArea(XtDisplay(w), XtWindow(w), 0, 0, 0, 0,
2432 #ifdef GR_DEBUG
2433                inDebugMode(gInfo->c)
2434 #else
2435                True
2436 #endif
2437                );
2438   }
2439   else
2440   {
2441     nargs = 0;
2442     XtSetArg(args[nargs], XmNwidth, daWd); nargs++;
2443     XtSetArg(args[nargs], XmNheight, daHt); nargs++;
2444     XtSetValues(w, args, nargs);
2445     XtManageChild(w);
2446   }
2447
2448 #ifdef GR_DEBUG
2449   if (inDebugMode(gInfo->c))
2450   {
2451     tmpSpin(w);
2452
2453     XtRemoveCallback(w, XmNexposeCallback,
2454                      tmpFn, (XtPointer)NULL);
2455
2456     /* Now that window is displayed, get its actual size, */
2457     /* since the Window Manager may have modified it. */
2458     nargs = 0;
2459     XtSetArg(args[nargs], XmNwidth, &daWd); nargs++;
2460     XtSetArg(args[nargs], XmNheight, &daHt); nargs++;
2461     XtGetValues(XtParent(w), args, nargs);
2462   }
2463 #endif
2464
2465   /* Get margins from properties. */
2466   inchWd = XmConvertUnits(w, XmHORIZONTAL, Xm1000TH_INCHES,
2467                           XINCH, XmPIXELS);
2468   gInfo->leftMarginX = cm_cvt_margin(gInfo, CP_PRINTLMARGIN, inchWd);
2469   gInfo->topMarginY = cm_cvt_margin(gInfo, CP_PRINTTMARGIN, inchWd);
2470   rMargin = cm_cvt_margin(gInfo, CP_PRINTRMARGIN, inchWd);
2471   bMargin = cm_cvt_margin(gInfo, CP_PRINTBMARGIN, inchWd);
2472
2473   gInfo->rightMarginX = daWd - rMargin;
2474   gInfo->bottomMarginY = daHt - bMargin;
2475
2476   pageWd = XmConvertUnits(w, XmHORIZONTAL, XmPIXELS,
2477                           daWd, Xm1000TH_INCHES);
2478   pageHt = XmConvertUnits(w, XmVERTICAL, XmPIXELS,
2479                           daHt, Xm1000TH_INCHES);
2480   if (orientation == PORTRAIT)
2481   {
2482     baseWd = PAGE_WIDTH;
2483     baseHt = PAGE_HEIGHT;
2484   }
2485   else
2486   {
2487     baseWd = PAGE_HEIGHT;
2488     baseHt = PAGE_WIDTH;
2489   }
2490
2491   gInfo->hscale = (double)pageWd / (double)baseWd;
2492   gInfo->vscale = (double)pageHt / (double)baseHt;
2493
2494   /* Scaled line widths: .25pt, 1pt, 2pt. */
2495   gInfo->thinWd = XmConvertUnits(w, XmHORIZONTAL, Xm100TH_POINTS,
2496                                  25, XmPIXELS);
2497   if (gInfo->thinWd < 1)
2498     gInfo->thinWd = 1;
2499   gInfo->normalWd = XmConvertUnits(w, XmHORIZONTAL, Xm100TH_POINTS,
2500                                    100, XmPIXELS);
2501   if (gInfo->normalWd < 1)
2502     gInfo->normalWd = 1;
2503   gInfo->thickWd = XmConvertUnits(w, XmHORIZONTAL, Xm100TH_POINTS,
2504                                   200, XmPIXELS);
2505   if (gInfo->thickWd < 1)
2506     gInfo->thickWd = 1;
2507 }
2508
2509 void
2510 x_init_day(void *gInfoP, int timeslots)
2511 {
2512   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
2513   CMFontInfo *fInfo;
2514
2515   gInfo->reportType = PR_DAY_VIEW;
2516
2517   /* Load day fonts */
2518   if (gInfo->nFonts == 0)
2519   {
2520     int i;
2521
2522     for (i = 0; i < DV_NUM_FONTS; i++)
2523       cm_load_font(gInfo, i, dvFonts[i]);
2524
2525     /* Set curFont to first loaded font. */
2526     gInfo->curFont = gInfo->fontInfo;
2527   }
2528
2529   cm_adjust_margins(gInfo);
2530
2531   fInfo = cm_find_font(gInfo, DV_TIME_FONT);
2532   gInfo->u.dayInfo.tab1 = (cm_font_height(gInfo, fInfo) * 2) + gInfo->normalWd;
2533
2534   gInfo->u.dayInfo.curX1 = gInfo->leftMarginX + (gInfo->normalWd / 2);
2535   gInfo->u.dayInfo.curX2 = (gInfo->leftMarginX + gInfo->rightMarginX) / 2;
2536   fInfo = cm_find_font(gInfo, DV_HEADER_FONT);
2537   gInfo->u.dayInfo.curY1 =
2538     gInfo->topMarginY + (gInfo->normalWd / 2) + cm_font_height(gInfo, fInfo) +
2539       VMARGIN(gInfo) + gInfo->u.dayInfo.tab1;
2540   gInfo->u.dayInfo.curY2 = gInfo->u.dayInfo.curY1;
2541
2542   gInfo->u.dayInfo.boxHt =
2543     (gInfo->bottomMarginY - ((gInfo->normalWd + 1) / 2) -
2544      gInfo->u.dayInfo.curY1) / timeslots;
2545   gInfo->u.dayInfo.boxWd =
2546     gInfo->u.dayInfo.curX2 - gInfo->u.dayInfo.curX1;
2547
2548   gInfo->u.dayInfo.line1 = 0;
2549 }
2550
2551 int
2552 x_get_day_lines_per_page(void *gInfoP)
2553 {
2554   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
2555   CMFontInfo *fInfo = cm_find_font(gInfo, DV_APPT_FONT);
2556
2557   return (gInfo->u.dayInfo.boxHt - gInfo->normalWd - (2 * VMARGIN(gInfo))) /
2558     cm_font_height(gInfo, fInfo);
2559 }
2560
2561 int
2562 x_get_week_lines_per_page(void *gInfoP)
2563 {
2564   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
2565   CMFontInfo *fInfo = cm_find_font(gInfo, DV_APPT_FONT);
2566
2567   return (gInfo->u.weekInfo.boxHt - gInfo->u.weekInfo.tab1 -
2568           ((gInfo->normalWd + 1) / 2) -
2569           (gInfo->thickWd / 2) - (2 * VMARGIN(gInfo))) /
2570             cm_font_height(gInfo, fInfo);
2571 }
2572
2573 void
2574 x_print_header(void *gInfoP, char *buf, int pageNum, int numPages)
2575 {
2576   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
2577   Calendar *c = gInfo->c;
2578   char *str;
2579   char str2[BUFFERSIZE];
2580   char pageStr[BUFFERSIZE];
2581   char *timeStamp;
2582   char *userId;
2583   char *reportTypeStr;
2584
2585   /* --- print header info at top --- */
2586   if (buf != (char *)NULL)
2587   {
2588     cm_set_font(gInfo, cm_get_title_enum(gInfo));
2589     {
2590       char *to = NULL;
2591       unsigned long to_len = 0;
2592       unsigned long _len;
2593
2594       _len = strlen( buf );
2595       _converter_( buf, _len, &to, &to_len );
2596       if ( ( to != NULL ) && ( to_len != 0 ) ) {
2597         str = euc_to_octal(to);
2598       } else {
2599         str = euc_to_octal(buf);
2600       }
2601     }
2602     x_print_string(gInfo, str,
2603                    (gInfo->rightMarginX + gInfo->leftMarginX) / 2,
2604                    gInfo->topMarginY,
2605                    CENTER_AT_X | BOTTOM_AT_Y);
2606   }
2607
2608   /* Get header/footer strings ready. */
2609   timeStamp = gInfo->timestamp;
2610   userId = c->view->current_calendar;
2611   reportTypeStr = get_report_type_string(gInfo);
2612
2613   if (numPages == 0)
2614     numPages++;
2615
2616   /* print creation notice at bottom */ 
2617   cm_strcpy(str2, catgets(c->DT_catd, 1, 468, "Page"));
2618   {
2619     char *to = NULL;
2620     unsigned long to_len = 0;
2621     unsigned long _len;
2622
2623     _len = strlen( str2 );
2624     _converter_( str2, _len, &to, &to_len );
2625     if ( ( to != NULL ) && ( to_len != 0 ) ) {
2626       strncpy( str2, to,
2627               ( BUFFERSIZE > to_len ) ? to_len : BUFFERSIZE );
2628     }
2629   }
2630   cm_strcpy(str2, euc_to_octal(str2));
2631
2632   str = catgets(c->DT_catd, 1, 476, "of");
2633   {
2634     char *to = NULL;
2635     unsigned long to_len = 0;
2636     unsigned long _len;
2637
2638     _len = strlen( str );
2639     _converter_( str, _len, &to, &to_len );
2640     if ( ( to != NULL ) && ( to_len != 0 ) ) {
2641       str = to;
2642     }
2643   }
2644
2645   sprintf(pageStr, "%s %d %s %d", str2, pageNum, str, numPages);
2646
2647   /* Header/footer strings are all set - print 'em! */
2648   cm_print_header_string(gInfo, CP_PRINTLHEADER,
2649                          timeStamp, userId, pageStr, reportTypeStr);
2650   cm_print_header_string(gInfo, CP_PRINTRHEADER,
2651                          timeStamp, userId, pageStr, reportTypeStr);
2652   cm_print_header_string(gInfo, CP_PRINTLFOOTER,
2653                          timeStamp, userId, pageStr, reportTypeStr);
2654   cm_print_header_string(gInfo, CP_PRINTRFOOTER,
2655                          timeStamp, userId, pageStr, reportTypeStr);
2656 }
2657
2658 void
2659 x_day_header (void *gInfoP)
2660 {
2661   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
2662   CMFontInfo *fInfo;
2663   char *str;
2664   Calendar *c = gInfo->c;
2665   int dayBoxVOffset;
2666   int midX;
2667
2668   fInfo = cm_find_font(gInfo, DV_HEADER_FONT);
2669   dayBoxVOffset = (gInfo->normalWd / 2) +
2670     cm_font_height(gInfo, fInfo) + VMARGIN(gInfo);
2671
2672   /* --- print Morning/Afternoon boxes --- */
2673   cm_set_font(gInfo, DV_TIME_FONT);
2674
2675   x_fill_light_box(gInfo, gInfo->u.dayInfo.curX1,
2676                    gInfo->topMarginY + dayBoxVOffset,
2677                    gInfo->rightMarginX - ((gInfo->normalWd + 1) / 2),
2678                    gInfo->topMarginY + dayBoxVOffset + gInfo->u.dayInfo.tab1,
2679                    gInfo->normalWd);
2680
2681   x_fill_dark_box(gInfo, gInfo->u.dayInfo.curX1,
2682                   gInfo->topMarginY + dayBoxVOffset,
2683                   gInfo->u.dayInfo.curX1 + gInfo->u.dayInfo.tab1,
2684                   gInfo->topMarginY + dayBoxVOffset + gInfo->u.dayInfo.tab1,
2685                   gInfo->normalWd);
2686
2687   midX = gInfo->u.dayInfo.curX2;
2688   x_fill_dark_box(gInfo, midX,
2689                   gInfo->topMarginY + dayBoxVOffset,
2690                   midX + gInfo->u.dayInfo.tab1,
2691                   gInfo->topMarginY + dayBoxVOffset + gInfo->u.dayInfo.tab1,
2692                   gInfo->normalWd);
2693
2694   str = catgets(c->DT_catd, 1, 470, "Morning");
2695
2696   {
2697     char *to = NULL;
2698     unsigned long to_len = 0;
2699     unsigned long _len;
2700
2701     _len = strlen( str );
2702     _converter_( str, _len, &to, &to_len );
2703     if ( ( to != NULL ) && ( to_len != 0 ) ) {
2704       str = to;
2705     }
2706   }
2707
2708   x_print_string(gInfo, str,
2709                  (gInfo->u.dayInfo.curX1 + gInfo->u.dayInfo.tab1 + midX) / 2,
2710                  gInfo->topMarginY + dayBoxVOffset +
2711                  (gInfo->u.dayInfo.tab1 / 2),
2712                  CENTER_AT_X | CENTER_AT_Y);
2713
2714   str = catgets(c->DT_catd, 1, 471, "Afternoon");
2715
2716   {
2717     char *to = NULL;
2718     unsigned long to_len = 0;
2719     unsigned long _len;
2720
2721     _len = strlen( str );
2722     _converter_( str, _len, &to, &to_len );
2723     if ( ( to != NULL ) && ( to_len != 0 ) ) {
2724       str = to;
2725     }
2726   }
2727
2728   str = euc_to_octal(str);
2729   x_print_string(gInfo, str,
2730                  (midX + gInfo->u.dayInfo.tab1 + gInfo->rightMarginX
2731                   - ((gInfo->normalWd + 1) / 2)) / 2,
2732                  gInfo->topMarginY + dayBoxVOffset +
2733                  (gInfo->u.dayInfo.tab1 / 2),
2734                  CENTER_AT_X | CENTER_AT_Y);
2735 }
2736
2737 void
2738 x_day_timeslots(void *gInfoP, int i, Boolean more)
2739 {
2740   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
2741
2742   char hourbuf[6];
2743   char modbuf[6];
2744   Calendar *c = gInfo->c;
2745
2746   sprintf (hourbuf, "%d", (morning(i) || (i == 12)) ? i : (i - 12) );
2747   sprintf (modbuf, "%s", morning(i) ? catgets(c->DT_catd, 1, 4, "am") :
2748            catgets(c->DT_catd, 1, 3, "pm"));
2749
2750   /* --- print hourly boxes for appt entries --- */
2751   if (i == 12)
2752   {
2753     gInfo->u.dayInfo.curX1 = gInfo->u.dayInfo.curX2;
2754     gInfo->u.dayInfo.curY1 = gInfo->u.dayInfo.curY2;
2755
2756     /* boxWd may be off by a pixel - set here to ensure correctness. */
2757     gInfo->u.dayInfo.boxWd =
2758       gInfo->rightMarginX - ((gInfo->normalWd + 1) / 2) -
2759         gInfo->u.dayInfo.curX1;
2760   }
2761
2762   x_draw_box(gInfo, gInfo->u.dayInfo.curX1, gInfo->u.dayInfo.curY1,
2763              gInfo->u.dayInfo.curX1 + gInfo->u.dayInfo.boxWd,
2764              gInfo->u.dayInfo.curY1 + gInfo->u.dayInfo.boxHt,
2765              gInfo->normalWd);
2766   x_fill_light_box(gInfo, gInfo->u.dayInfo.curX1,
2767                    gInfo->u.dayInfo.curY1,
2768                    gInfo->u.dayInfo.curX1 + gInfo->u.dayInfo.tab1,
2769                    gInfo->u.dayInfo.curY1 + gInfo->u.dayInfo.boxHt,
2770                    gInfo->normalWd);
2771
2772   cm_set_font(gInfo, DV_TIME_FONT);
2773
2774   x_print_string(gInfo, hourbuf,
2775                  gInfo->u.dayInfo.curX1 + (gInfo->u.dayInfo.tab1 / 2),
2776                  gInfo->u.dayInfo.curY1 + (gInfo->u.dayInfo.boxHt / 2) -
2777                  (VMARGIN(gInfo) / 2),
2778                  CENTER_AT_X | BOTTOM_AT_Y);
2779
2780   x_print_string(gInfo, modbuf,
2781                  gInfo->u.dayInfo.curX1 + (gInfo->u.dayInfo.tab1 / 2),
2782                  gInfo->u.dayInfo.curY1 + (gInfo->u.dayInfo.boxHt / 2) +
2783                  (VMARGIN(gInfo) / 2),
2784                  CENTER_AT_X | TOP_AT_Y);
2785
2786   if (more)
2787     x_print_string(gInfo, "*",
2788                    gInfo->u.dayInfo.curX1 + (gInfo->u.dayInfo.tab1 / 2),
2789                    gInfo->u.dayInfo.curY1 + (gInfo->u.dayInfo.boxHt / 2) +
2790                    cm_font_height(gInfo, gInfo->curFont) + VMARGIN(gInfo),
2791                    CENTER_AT_X | TOP_AT_Y);
2792
2793   gInfo->u.dayInfo.line1 = gInfo->u.dayInfo.curY1 +
2794     ((gInfo->normalWd + 1) / 2) + VMARGIN(gInfo);
2795   gInfo->u.dayInfo.curY1 += gInfo->u.dayInfo.boxHt;
2796 }
2797
2798 Boolean
2799 x_print_multi_appts(void *gInfoP,
2800         CSA_entry_handle *list,
2801         int a_total,
2802         int num_page,
2803         Glance view)
2804 {
2805   /*
2806    * This routine is used to print appointments for day and week
2807    * views.  The parm "view" is used to differentiate
2808    * who is printing, and personalize the print for that view.
2809    */
2810
2811   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
2812   int           indented, indentAmt, multlines=TRUE;
2813   Lines         *lines, *lp;    
2814   char          buf1[128], buf2[257];
2815   Calendar      *c = gInfo->c;  
2816   Props         *pr = (Props*)c->properties;
2817   int           meoval = get_int_prop(pr, CP_PRINTPRIVACY);
2818   int           dt = get_int_prop(pr, CP_DEFAULTDISP);
2819   int           i, j, start, maxlines, pos = 1, line_counter = 0;
2820   Boolean       new_appt = FALSE;
2821   CSA_return_code       stat;
2822   Dtcm_appointment      *appt;
2823
2824   if (view == weekGlance)
2825     maxlines = x_get_week_lines_per_page(gInfoP);
2826   else if (view == dayGlance)
2827     maxlines = x_get_day_lines_per_page(gInfoP);
2828   else maxlines = 1;
2829
2830   start = ((num_page - 1) * maxlines) + 1;
2831
2832   appt = allocate_appt_struct(appt_read,
2833                               c->general->version,
2834                               CSA_ENTRY_ATTR_CLASSIFICATION_I,
2835                               CSA_ENTRY_ATTR_START_DATE_I,
2836                               CSA_ENTRY_ATTR_SUMMARY_I,
2837                               CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,
2838                               CSA_ENTRY_ATTR_END_DATE_I,
2839                               NULL);
2840   for (j = 0; j < a_total; j++) {
2841     stat = query_appt_struct(c->cal_handle, list[j], appt);
2842     if (stat != CSA_SUCCESS) {
2843       free_appt_struct(&appt);
2844       return False;
2845     }
2846
2847     if ((privacy_set(appt) == CSA_CLASS_PUBLIC) && !(meoval & PRINT_PUBLIC))
2848       continue;
2849     if ((privacy_set(appt) == CSA_CLASS_CONFIDENTIAL) &&
2850         !(meoval & PRINT_SEMIPRIVATE))
2851       continue;
2852     if ((privacy_set(appt) == CSA_CLASS_PRIVATE) &&
2853         !(meoval & PRINT_PRIVATE))
2854       continue;
2855
2856     lp = lines = text_to_lines(appt->what->value->item.string_value,
2857                                multlines ? 10 : 1);
2858     new_appt = TRUE;
2859
2860     /* skip past lines already printed */
2861     if (pos < start) {
2862       if (showtime_set(appt)) {
2863         if (new_appt)
2864           for (i = 1; i <= num_page; i++)
2865             if (pos == (maxlines * i))
2866               start--;
2867         pos++;
2868       }
2869       while ((lines != NULL) && (pos < start)) {
2870         pos++;
2871         new_appt = FALSE;
2872         lines = lines->next;
2873       }
2874       if (pos < start) {
2875         continue;
2876       }
2877     }
2878
2879     /* skip last line if it's a time */
2880     if (showtime_set(appt)) {
2881       if (line_counter == (maxlines - 1)) {
2882         free_appt_struct(&appt);
2883         return(FALSE);
2884       }
2885     }
2886
2887     /* HH:MM xm - HH:MM xm format */
2888     format_line2(appt, buf1, buf2, dt);
2889
2890     indented = (*buf1 != NULL);
2891     indentAmt = (view == dayGlance) ? 0 : 1;
2892     if (indented)
2893       indentAmt += 2;
2894
2895     /* only print if appt text found */
2896     if (lines != NULL && lines->s != NULL) {
2897       if ((indented) && (new_appt)) {
2898         line_counter++;
2899         if ((line_counter > maxlines) && (lines != NULL)) {
2900           free_appt_struct(&appt);
2901           return(FALSE);
2902         }
2903
2904         cm_print_time (gInfo, buf1, view);
2905       }
2906
2907       cm_print_appt_text (gInfo, lines->s, indentAmt, view);
2908       line_counter++;
2909       if ((line_counter > maxlines) && (lines != NULL)) {
2910         free_appt_struct(&appt);
2911         return(FALSE);
2912       }
2913
2914       lines = lines->next;
2915       while (lines != NULL) {
2916         line_counter++;
2917         if ((line_counter > maxlines) && (lines != NULL)) {
2918           free_appt_struct(&appt);
2919           return(FALSE);
2920         }
2921
2922         cm_print_appt_text (gInfo, lines->s, indentAmt, view);
2923         lines = lines->next;
2924       }
2925     }
2926     destroy_lines(lp);
2927     if (view == weekGlance)
2928       cm_week_sched_update(gInfo, appt, pr);
2929     new_appt = FALSE;
2930   }
2931   free_appt_struct(&appt);
2932   return(TRUE);
2933 }
2934
2935 void
2936 x_finish_printer(void *gInfoP)
2937 {
2938   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
2939   Widget w = gInfo->drawingArea;
2940
2941 #ifdef GR_DEBUG
2942   if (inDebugMode(gInfo->c))
2943     tmpSpin(w);
2944   else
2945 #endif
2946     XpEndPage(XtDisplay(w));
2947 }
2948
2949 void
2950 x_print_list_range(Calendar *c, CSA_sint32 appt_type, int item_data,
2951                    Tick start_tick, Tick end_tick)
2952 {
2953         char            buf[MAXNAMELEN], buf2[MAXNAMELEN];
2954         void            *xp;
2955         Props           *p = (Props *)c->properties;
2956         Glance          glance;
2957         todo_view_op    todo_view = VIEW_ALL;
2958         OrderingType    ot = get_int_prop(p, CP_DATEORDERING);
2959         time_t          start, end;
2960         CSA_return_code stat;
2961         CSA_entry_handle *list;
2962         CSA_attribute *range_attrs;
2963         CSA_enum *ops;
2964         int i;
2965         CSA_uint32 a_total;
2966
2967         if ((xp = x_open_file(c)) == (void *)NULL)
2968           return;
2969
2970         if (appt_type ==  CSA_TYPE_TODO) {
2971                 todo_view = (todo_view_op)item_data;
2972                 glance = c->view->glance;
2973         } else
2974                 glance = (Glance)item_data;
2975
2976         x_init_printer(xp, PORTRAIT);
2977         x_init_list(xp);
2978
2979         memset(buf, '\0', MAXNAMELEN);
2980         memset(buf2, '\0', MAXNAMELEN);
2981
2982         start = lowerbound(start_tick);
2983         end = nextday(end_tick) - 1;
2984
2985         format_date(start + 1, ot, buf2, 1, 0, 0);
2986
2987         if (appt_type == CSA_TYPE_TODO)
2988                 sprintf(buf, catgets(c->DT_catd, 1, 899,
2989                                      "To Do List Beginning: %s"), buf2);
2990         else
2991                 sprintf(buf, catgets(c->DT_catd, 1, 900,
2992                                      "Appt List Beginning: %s"), buf2);
2993
2994         setup_range(&range_attrs, &ops, &i, start, end, appt_type,
2995                     NULL, B_FALSE, c->general->version);
2996         stat = csa_list_entries(c->cal_handle, i, range_attrs,
2997                                 ops, &a_total, &list, NULL);
2998         if (stat != CSA_SUCCESS) {
2999                 return;
3000         }
3001
3002         x_print_todo(xp, list, a_total, appt_type,
3003                      (start_tick != end_tick), todo_view, end, buf);
3004
3005         csa_free(list);
3006
3007         x_finish_printer(xp);
3008         x_print_file(xp, c);
3009 }
3010
3011 void
3012 x_init_list(void *gInfoP)
3013 {
3014   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3015   CMFontInfo *fInfo;
3016   int hIndent;
3017   int vIndent;
3018
3019   /* We can ONLY get here printing via dialog - printData is valid. */
3020   gInfo->reportType = pd_get_report_type(gInfo->c);
3021
3022   /* Load list fonts */
3023   if (gInfo->nFonts == 0)
3024   {
3025     int i;
3026
3027     if (gInfo->reportType == PR_APPT_LIST)
3028     {
3029       for (i = 0; i < AV_NUM_FONTS; i++)
3030         cm_load_font(gInfo, i, avFonts[i]);
3031     }
3032     else
3033     {
3034       for (i = 0; i < TV_NUM_FONTS; i++)
3035         cm_load_font(gInfo, i, tvFonts[i]);
3036     }
3037
3038     /* Set curFont to first loaded font. */
3039     gInfo->curFont = gInfo->fontInfo;
3040   }
3041
3042   cm_adjust_margins(gInfo);
3043
3044   cm_set_font(gInfo, cm_get_header_enum(gInfo));
3045
3046   hIndent = TODO_HINDENT * gInfo->hscale * gInfo->normalWd;
3047   vIndent = TODO_VINDENT * gInfo->vscale * gInfo->normalWd;
3048   gInfo->u.toDoInfo.outerX1 = gInfo->leftMarginX + (gInfo->thickWd / 2);
3049   gInfo->u.toDoInfo.outerY1 = gInfo->topMarginY + (gInfo->thickWd / 2) +
3050     cm_font_height(gInfo, gInfo->curFont) + VMARGIN(gInfo);
3051   gInfo->u.toDoInfo.innerX1 = gInfo->u.toDoInfo.outerX1 + hIndent;
3052   gInfo->u.toDoInfo.innerY1 = gInfo->u.toDoInfo.outerY1 + vIndent;
3053   gInfo->u.toDoInfo.outerX2 =
3054     gInfo->rightMarginX - ((gInfo->thickWd + 1) / 2);
3055   gInfo->u.toDoInfo.outerY2 =
3056     gInfo->bottomMarginY - ((gInfo->thickWd + 1) / 2);
3057   gInfo->u.toDoInfo.boxX2 = gInfo->u.toDoInfo.outerX2 - hIndent;
3058   gInfo->u.toDoInfo.boxY2 = gInfo->u.toDoInfo.outerY2 - vIndent;
3059   gInfo->u.toDoInfo.boxX1 = gInfo->u.toDoInfo.innerX1;
3060   gInfo->u.toDoInfo.boxY1 = gInfo->u.toDoInfo.boxY2 -
3061     cm_tiny_month_height(gInfo, VMARGIN(gInfo)) - gInfo->thickWd;
3062   gInfo->u.toDoInfo.innerX2 = gInfo->u.toDoInfo.boxX2;
3063   gInfo->u.toDoInfo.innerY2 = gInfo->u.toDoInfo.boxY1 - vIndent;
3064
3065   gInfo->u.toDoInfo.lineX =
3066     gInfo->u.toDoInfo.innerX1 + ((gInfo->thickWd + 1) / 2) + HMARGIN(gInfo);
3067   gInfo->u.toDoInfo.lineY =
3068     gInfo->u.toDoInfo.innerY1 + ((gInfo->thickWd + 1) / 2) + VMARGIN(gInfo);
3069 }
3070
3071 void
3072 x_print_todo(void *gInfoP, CSA_entry_handle *list, int a_total, 
3073              CSA_sint32 appt_type, Boolean showDate, int vf,
3074              time_t end_time, char *buf)
3075 {
3076         CMGraphicsInfo  *gInfo = (CMGraphicsInfo *)gInfoP;
3077         int             i, items_per_page = 0, meoval;
3078         char            buf3[BUFFERSIZE], buf2[BUFFERSIZE], buf1[BUFFERSIZE];
3079         int             total_items = 0;
3080         boolean_t       skip_appt;
3081         CSA_return_code stat;
3082         Dtcm_appointment *appt;
3083         Calendar        *c = gInfo->c;
3084         Props           *p = (Props*)c->properties;
3085         DisplayType     dt = get_int_prop(p, CP_DEFAULTDISP);
3086         OrderingType    ot = get_int_prop(p, CP_DATEORDERING);
3087         SeparatorType   st = get_int_prop(p, CP_DATESEPARATOR);
3088         Tick            start_tick;
3089         int             linesFullPage, linesPartialPage;
3090         int             numAppts, numPages, curPage;
3091
3092         curPage = 1;
3093         cm_get_todo_lines_per_page(gInfo, appt_type, &linesFullPage,
3094                                    &linesPartialPage);
3095         numAppts = cm_count_appts(gInfo, list, a_total, appt_type, vf);
3096         for (numPages = 1, numAppts -= linesPartialPage;
3097              numAppts > 0;
3098              numPages++)
3099           numAppts -= linesFullPage;
3100         x_print_header(gInfoP, buf, curPage, numPages);
3101         cm_todo_outline(gInfo, curPage == numPages);
3102         cm_set_todo_text_clipping(gInfo);
3103
3104         meoval = get_int_prop(p, CP_PRINTPRIVACY);
3105         buf1[0] = buf2[0] = buf3[0] = '\0';
3106
3107         appt = allocate_appt_struct(appt_read,
3108                                     c->general->version,
3109                                     CSA_ENTRY_ATTR_CLASSIFICATION_I,
3110                                     CSA_ENTRY_ATTR_TYPE_I,
3111                                     CSA_ENTRY_ATTR_STATUS_I,
3112                                     CSA_ENTRY_ATTR_START_DATE_I,
3113                                     CSA_ENTRY_ATTR_SUMMARY_I,
3114                                     CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,
3115                                     CSA_ENTRY_ATTR_END_DATE_I,
3116                                     NULL);
3117         for (i = 0; i < a_total; i++)
3118         {
3119           stat = query_appt_struct(c->cal_handle, list[i], appt);
3120           if (stat != CSA_SUCCESS)
3121           {
3122             free_appt_struct(&appt);
3123             return;
3124           }
3125           skip_appt = B_FALSE;
3126
3127           if ((privacy_set(appt) == CSA_CLASS_PUBLIC) &&
3128               !(meoval & PRINT_PUBLIC))
3129             skip_appt = B_TRUE;
3130           else if ((privacy_set(appt) == CSA_CLASS_CONFIDENTIAL) &&
3131                    !(meoval & PRINT_SEMIPRIVATE))
3132             skip_appt = B_TRUE;
3133           else if ((privacy_set(appt) == CSA_CLASS_PRIVATE) &&
3134                    !(meoval & PRINT_PRIVATE))
3135             skip_appt = B_TRUE;
3136
3137           if ((appt_type == CSA_TYPE_TODO) &&
3138               ((appt->type->value->item.sint32_value != CSA_TYPE_TODO)
3139                ||
3140                ((vf == VIEW_PENDING) &&
3141                 (appt->state->value->item.sint32_value ==
3142                  CSA_STATUS_COMPLETED)) ||
3143                ((vf == VIEW_COMPLETED) &&
3144                 (appt->state->value->item.sint32_value ==
3145                  CSA_X_DT_STATUS_ACTIVE))))
3146             skip_appt = B_TRUE;
3147
3148           if ((appt_type == CSA_TYPE_EVENT) &&
3149               (appt->type->value->item.sint32_value != CSA_TYPE_EVENT))
3150             skip_appt = B_TRUE;
3151
3152           if (skip_appt)
3153             continue;
3154
3155           format_maxchars(appt, buf1, BUFFERSIZE - 5, dt);
3156           if (showDate)
3157           {
3158             _csa_iso8601_to_tick(appt->time->value->item.date_time_value,
3159                                  &start_tick);
3160             format_date3(start_tick, ot, st, buf2);
3161             sprintf(buf3, "%s  %s", buf2, buf1);
3162           } else
3163             cm_strcpy(buf3, buf1);
3164
3165           total_items++;
3166           cm_print_todo_text (gInfo, buf3,
3167                               appt->state->value->item.sint32_value,
3168                               appt_type, total_items);
3169           if ((++items_per_page % linesFullPage) == 0)
3170           {
3171             cm_unset_todo_text_clipping(gInfo);
3172             x_finish_printer(gInfoP);
3173             x_init_printer(gInfoP, PORTRAIT);
3174             x_init_list(gInfoP);
3175             x_print_header(gInfoP, buf, ++curPage, numPages);
3176             cm_todo_outline(gInfo, curPage == numPages);
3177             cm_set_todo_text_clipping(gInfo);
3178             items_per_page = 0;
3179           }
3180         } /* end for stmt */
3181
3182         free_appt_struct(&appt);
3183         cm_unset_todo_text_clipping(gInfo);
3184
3185         if (items_per_page > linesPartialPage) {
3186           x_finish_printer(gInfoP);
3187           x_init_printer(gInfoP, PORTRAIT);
3188           x_init_list(gInfoP);
3189           x_print_header(gInfoP, buf, ++curPage, numPages);
3190           cm_todo_outline(gInfo, curPage == numPages);
3191         }
3192
3193         cm_print_todo_months(gInfo, end_time);
3194 }
3195
3196 void
3197 x_print_month(void *gInfoP, int mon, int yr, int x1,
3198               int y1, int x2, int y2, int spacing)
3199 {
3200   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3201   CMFontInfo *fInfo;
3202   Tick j = monthdayyear(mon, 1, yr);        /* starting date Jan 1, y */
3203   int i, colWd, dateWd, monLen;
3204   char str[BUFFERSIZE];
3205
3206   if (mon > 12)
3207     mon = (mon % 13) + 1;
3208   else if (mon < 1)
3209     mon = mon + 12;
3210
3211   x_set_clip_box(gInfo, x1, y1, x2, y2);
3212
3213   cm_set_font(gInfo, cm_get_tiny_title_enum(gInfo));
3214   y1 += spacing;
3215
3216   cm_strcpy(str, months[mon]);
3217
3218   {
3219     char *to = NULL;
3220     unsigned long to_len = 0;
3221     unsigned long _len;
3222
3223     _len = strlen(str);
3224     _converter_( str, _len, &to, &to_len );
3225     if ( ( to != NULL ) && ( to_len != 0 ) ) {
3226       cm_strcpy(str, to);
3227     }
3228   }
3229
3230   cm_strcpy(str, euc_to_octal(str));
3231   x_fill_light_box(gInfo, x1 + HMARGIN(gInfo), y1,
3232                    x2 - HMARGIN(gInfo),
3233                    y1 + cm_font_height(gInfo, gInfo->curFont),
3234                    0);
3235   x_print_string(gInfo, str,
3236                  (x1 + x2) / 2, y1,
3237                  CENTER_AT_X | TOP_AT_Y);
3238   y1 += spacing + cm_font_height(gInfo, gInfo->curFont);
3239
3240   fInfo = cm_find_font(gInfo, cm_get_tiny_date_enum(gInfo));
3241   monLen = monthlength(j);
3242   colWd = 0;
3243   for (i = 0; i < monLen; i++)
3244   {
3245     sprintf(str, "%d", i + 1);
3246     if ((dateWd = cm_string_width(gInfo, fInfo, str)) > colWd)
3247       colWd = dateWd;
3248   }
3249
3250   cm_std_month_weekdays(gInfo, colWd, x1, y1, x2);
3251   y1 += spacing + cm_font_height(gInfo, gInfo->curFont);
3252
3253   cm_std_month_dates(gInfo, fdom(j), monLen, colWd,
3254                      x1, y1, x2, spacing);
3255
3256   x_unset_clip_box(gInfo);
3257 }
3258
3259 void
3260 x_init_std_year(void *gInfoP)
3261 {
3262   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3263   CMFontInfo *fInfo;
3264
3265   gInfo->reportType = PR_YEAR_VIEW;
3266
3267   /* Load year fonts */
3268   if (gInfo->nFonts == 0)
3269   {
3270     int i;
3271
3272     for (i = 0; i < YV_NUM_FONTS; i++)
3273       cm_load_font(gInfo, i, yvFonts[i]);
3274
3275     /* Set curFont to first loaded font. */
3276     gInfo->curFont = gInfo->fontInfo;
3277   }
3278
3279   cm_adjust_margins(gInfo);
3280 }
3281
3282 void
3283 x_std_year_name(void *gInfoP, int yr)
3284 {
3285   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3286   char yearBuf[BUFFERSIZE];
3287
3288   /* --- print year centered at top --- */
3289   sprintf(yearBuf, "%d", yr);
3290   x_print_header(gInfoP, yearBuf, 1, 1);
3291 }
3292
3293 void
3294 x_print_year(void *gInfoP, int yr)
3295 {
3296   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3297   CMFontInfo *fInfo;
3298   int i;
3299   int leftX, topY;
3300   int x1, y1;
3301   int x2, y2;
3302   int row, col;
3303   int pageWd, pageHt;
3304   int monthHt;
3305   int extraSpace;
3306
3307   fInfo = cm_find_font(gInfo, YV_HEADER_FONT);
3308   monthHt = cm_tiny_month_height(gInfo, VMARGIN(gInfo));
3309
3310   leftX = gInfo->leftMarginX;
3311   topY = gInfo->topMarginY + cm_font_height(gInfo, fInfo) + VMARGIN(gInfo);
3312
3313   pageWd = gInfo->rightMarginX - leftX;
3314   pageHt = gInfo->bottomMarginY - topY;
3315   extraSpace = pageHt - (4 * monthHt);
3316
3317   for (i = 0; i < 12; i++)
3318   {
3319     row = i / 3;
3320     col = i % 3;
3321
3322     x1 = leftX + ((col * pageWd) / 3);
3323     x2 = leftX + (((col + 1) * pageWd) / 3);
3324
3325     if (extraSpace > 0)
3326     {
3327       y1 = topY + (((row + 1) * extraSpace) / 5) + (row * monthHt);
3328       y2 = topY + (((row + 2) * extraSpace) / 5) + ((row + 1) * monthHt);
3329     }
3330     else
3331     {
3332       y1 = topY + ((row * pageHt) / 4);
3333       y2 = topY + (((row + 1) * pageHt) / 4);
3334     }
3335
3336     x_print_month(gInfoP, i + 1, yr, x1, y1, x2, y2, VMARGIN(gInfo));
3337   }
3338 }
3339
3340 void
3341 x_init_week(void *gInfoP)
3342 {
3343   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3344   CMFontInfo *fInfo;
3345
3346   gInfo->reportType = PR_WEEK_VIEW;
3347
3348   /* Load week fonts */
3349   if (gInfo->nFonts == 0)
3350   {
3351     int i;
3352
3353     for (i = 0; i < WV_NUM_FONTS; i++)
3354       cm_load_font(gInfo, i, wvFonts[i]);
3355
3356     /* Set curFont to first loaded font. */
3357     gInfo->curFont = gInfo->fontInfo;
3358   }
3359
3360   cm_adjust_margins(gInfo);
3361
3362   fInfo = cm_find_font(gInfo, WV_HEADER_FONT);
3363   gInfo->u.weekInfo.curX1 = gInfo->leftMarginX + (gInfo->thickWd / 2);
3364   gInfo->u.weekInfo.curY1 = gInfo->topMarginY + cm_font_height(gInfo, fInfo) +
3365     VMARGIN(gInfo) + (gInfo->thickWd / 2);
3366   gInfo->u.weekInfo.boxWd =
3367     gInfo->rightMarginX - gInfo->leftMarginX - gInfo->thickWd;
3368   gInfo->u.weekInfo.boxHt =
3369     (gInfo->bottomMarginY - ((gInfo->thickWd + 1) / 2) -
3370      gInfo->u.weekInfo.curY1) / 2;
3371   gInfo->u.weekInfo.curY2 =
3372     gInfo->u.weekInfo.curY1 + gInfo->u.weekInfo.boxHt;
3373
3374   fInfo = cm_find_font(gInfo, WV_DAY_FONT);
3375   gInfo->u.weekInfo.tab1 =
3376     ((3 * cm_font_height(gInfo, fInfo)) +
3377      gInfo->thickWd + gInfo->normalWd) / 2;
3378 }
3379
3380 void
3381 x_week_appt_boxes(void *gInfoP)
3382 {
3383   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3384   int x1, y1, x2, y2;
3385   int innerWd, innerOffset;
3386   int i;
3387
3388   /* Draw weekdays box. */
3389   x1 = gInfo->u.weekInfo.curX1;
3390   y1 = gInfo->u.weekInfo.curY1;
3391   x2 = x1 + gInfo->u.weekInfo.boxWd;
3392   y2 = y1 + gInfo->u.weekInfo.tab1;
3393
3394   x_fill_light_box(gInfo, x1, y1, x2, y2, gInfo->normalWd);
3395
3396   y2 = gInfo->u.weekInfo.curY2;
3397   x_draw_box(gInfo, x1, y1, x2, y2, gInfo->thickWd);
3398
3399   /* Draw weekdays vertical lines. */
3400   innerWd = gInfo->u.weekInfo.boxWd - gInfo->thickWd + gInfo->normalWd;
3401   innerOffset = ((gInfo->thickWd - 1) / 2) - ((gInfo->normalWd - 1) / 2);
3402   for (i = 1; i < WEEK_DAYS; i++)
3403   {
3404     x1 = gInfo->u.weekInfo.curX1 + innerOffset + ((i * innerWd) / WEEK_DAYS);
3405     x_draw_line(gInfo, x1, y1, x1, y2, gInfo->normalWd);
3406   }
3407
3408   /* Draw weekends box. */
3409   x1 = gInfo->u.weekInfo.curX1 +
3410     (((WEEK_DAYS - WEEKEND_DAYS) * gInfo->u.weekInfo.boxWd) / WEEK_DAYS);
3411   y1 = y2;
3412   y2 = y1 + gInfo->u.weekInfo.tab1;
3413   x_fill_light_box(gInfo, x1, y1, x2, y2, gInfo->normalWd);
3414
3415   y2 = gInfo->bottomMarginY - ((gInfo->thickWd + 1) / 2);
3416   x_draw_box(gInfo, x1, y1, x2, y2, gInfo->thickWd);
3417
3418   /* Draw weekends vertical lines. */
3419   for (i = WEEK_DAYS - WEEKEND_DAYS + 1; i < WEEK_DAYS; i++)
3420   {
3421     x1 = gInfo->u.weekInfo.curX1 + innerOffset + ((i * innerWd) / WEEK_DAYS);
3422     x_draw_line(gInfo, x1, y1, x1, y2, gInfo->normalWd);
3423   }
3424 }
3425
3426 void
3427 x_week_sched_boxes(void *gInfoP)
3428 {
3429   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3430   char *day_of_week[DAYS_IN_WEEK];
3431   char hourBuf[BUFFERSIZE];
3432   Props *p = (Props *)gInfo->c->properties;
3433   int begin = get_int_prop(p, CP_DAYBEGIN);
3434   int end = get_int_prop(p, CP_DAYEND);
3435   DisplayType dt = get_int_prop(p, CP_DEFAULTDISP);
3436   int thisHour;
3437   int num_hours;
3438   int boxIndent;
3439   int boxX1, boxY1, boxX2, boxY2, boxWd, boxHt;
3440   int x1, y1, x2, y2;
3441   int i;
3442   int ulOff = gInfo->thickWd / 2;
3443   int brOff = (gInfo->thickWd - 1) / 2;
3444
3445   /* --- print week sched boxes --- */
3446
3447   /* figure out number of partitions in sched box */
3448   num_hours = end - begin;
3449
3450   /* determine offset of sched box from left margin */
3451   cm_set_font(gInfo, WV_DAY_FONT);
3452   boxIndent = cm_week_sched_box_indent(gInfo);
3453   boxX1 = gInfo->u.weekInfo.curX1 + boxIndent;
3454   boxX2 = gInfo->u.weekInfo.curX1 +
3455     ((3 * gInfo->u.weekInfo.boxWd) / WEEK_DAYS) - boxIndent;
3456   boxY1 = gInfo->u.weekInfo.curY2 +
3457     (2 * cm_font_height(gInfo, gInfo->curFont)) +
3458       gInfo->thickWd;
3459   boxY2 = gInfo->bottomMarginY - 1 - brOff;
3460
3461   x_draw_box(gInfo, boxX1, boxY1, boxX2, boxY2, gInfo->thickWd);
3462
3463   boxX1 += brOff - ((gInfo->normalWd - 1) / 2);
3464   boxX2 -= ulOff - (gInfo->normalWd / 2);
3465   boxY1 += brOff - ((gInfo->thinWd - 1) / 2);
3466   boxY2 -= ulOff - (gInfo->thinWd / 2);
3467   boxWd = boxX2 - boxX1;
3468   boxHt = boxY2 - boxY1;
3469
3470   for (i = 0; i < DAYS_IN_WEEK; i++)
3471     local_dayname(gInfo->c, &day_of_week[i], (i + 1) % DAYS_IN_WEEK);
3472
3473   /* print abbreviated weekdays on top and draw vertical lines. */
3474   for (i = 0; i < DAYS_IN_WEEK; i++)
3475   {
3476     x1 = boxX1 + ((i * boxWd) / DAYS_IN_WEEK);
3477     x2 = boxX1 + (((i + 1) * boxWd) / DAYS_IN_WEEK);
3478
3479     x_print_string(gInfo, day_of_week[i],
3480                    (x1 + x2) / 2, boxY1 -
3481                    gInfo->thickWd - (2 * VMARGIN(gInfo)),
3482                    CENTER_AT_X | BOTTOM_AT_Y);
3483     free(day_of_week[i]);
3484     if (i > 0)
3485       x_draw_line(gInfo, x1, boxY1, x1, boxY2, gInfo->normalWd);
3486   }
3487
3488   /* Print hours and horizontal lines. */
3489   for (thisHour = begin, i = 0; i <= num_hours; i++, thisHour++)
3490   {
3491     if ( dt == HOUR12 )
3492     {
3493       if (thisHour > 12)
3494         thisHour %= 12;
3495     }
3496     else if ( dt == HOUR24 )
3497     {
3498       if (thisHour > 24)
3499         thisHour %= 24;
3500     }
3501     sprintf(hourBuf, "%d", thisHour);
3502     y1 = boxY1 + ((i * boxHt) / num_hours);
3503
3504     x_print_string(gInfo, hourBuf,
3505                    boxX1 - gInfo->thickWd - HMARGIN(gInfo), y1,
3506                    RIGHT_AT_X | CENTER_AT_Y);
3507
3508     if ((i > 0) && (i < num_hours))
3509       x_draw_line(gInfo, boxX1, y1, boxX2, y1, gInfo->thinWd);
3510   }
3511
3512   gInfo->u.weekInfo.schedBoxX1 = boxX1;
3513   gInfo->u.weekInfo.schedBoxY1 = boxY1;
3514   gInfo->u.weekInfo.schedBoxX2 = boxX2;
3515   gInfo->u.weekInfo.schedBoxY2 = boxY2;
3516 }
3517
3518 void
3519 x_week_daynames(void *gInfoP, char *dayName, int dayIndex, Boolean more)
3520 {
3521   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3522   Calendar *c = gInfo->c;
3523   int x1, y1, x2, y2;
3524   int innerOffset, innerWd;
3525   char dayBuf[BUFFERSIZE];
3526
3527   y1 = (dayIndex < WEEK_DAYS) ? gInfo->u.weekInfo.curY1 :
3528     gInfo->u.weekInfo.curY2;
3529   y2 = y1 + gInfo->u.weekInfo.tab1;
3530
3531   cm_set_font(gInfo, WV_DAY_FONT);
3532
3533   innerWd = gInfo->u.weekInfo.boxWd - gInfo->thickWd + gInfo->normalWd;
3534   innerOffset = ((gInfo->thickWd - 1) / 2) - ((gInfo->normalWd - 1) / 2);
3535
3536   if (dayIndex >= WEEK_DAYS)
3537     dayIndex -= WEEKEND_DAYS;
3538   x1 = gInfo->u.weekInfo.curX1 + innerOffset +
3539     ((dayIndex * innerWd) / WEEK_DAYS);
3540   x2 = gInfo->u.weekInfo.curX1 + innerOffset +
3541     (((dayIndex + 1) * innerWd) / WEEK_DAYS);
3542
3543   {
3544     char *to = NULL;
3545     unsigned long to_len = 0;
3546     unsigned long _len;
3547
3548     _len = strlen(dayName);
3549     _converter_( dayName, _len, &to, &to_len );
3550     if ( ( to != NULL ) && ( to_len != 0 ) ) {
3551       dayName = to;
3552     }
3553   }
3554
3555   sprintf(dayBuf, more ? "%s *" : "%s", euc_to_octal(dayName));
3556   x_print_string(gInfo, dayBuf, (x1 + x2) / 2, (y1 + y2) / 2,
3557                  CENTER_AT_X | CENTER_AT_Y);
3558
3559   gInfo->u.weekInfo.lineX = x1;
3560   gInfo->u.weekInfo.lineY = y2 + ((gInfo->normalWd + 1) / 2) + VMARGIN(gInfo);
3561   gInfo->u.weekInfo.lineMaxY = y1 + gInfo->u.weekInfo.boxHt;
3562 }
3563
3564 void
3565 x_week_sched_init(void *gInfoP)
3566 {
3567   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3568
3569   memset(gInfo->u.weekInfo.schedBucket, 0,
3570          sizeof(gInfo->u.weekInfo.schedBucket));
3571 }
3572
3573 void
3574 x_week_sched_draw(void *gInfoP, int dayIndex)
3575 {
3576   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3577   int i;
3578   Props *p = (Props *)gInfo->c->properties;
3579   int begin = get_int_prop(p, CP_DAYBEGIN);
3580   int end = get_int_prop(p, CP_DAYEND);
3581   int num_hours = end - begin;
3582   int nIntervals = num_hours * 4;
3583   int x1, y1, x2, y2;
3584   int boxWd = gInfo->u.weekInfo.schedBoxX2 - gInfo->u.weekInfo.schedBoxX1;
3585   int boxHt = gInfo->u.weekInfo.schedBoxY2 - gInfo->u.weekInfo.schedBoxY1;
3586   int currColor, lastColor;
3587   int tOffset, bOffset;
3588
3589   x1 = gInfo->u.weekInfo.schedBoxX1 +
3590     ((dayIndex * boxWd) / DAYS_IN_WEEK) + ((gInfo->normalWd + 1) / 2);
3591   x2 = gInfo->u.weekInfo.schedBoxX1 +
3592     (((dayIndex + 1) * boxWd) / DAYS_IN_WEEK) - (gInfo->normalWd / 2) - 1;
3593
3594   lastColor = 0;
3595   for (i = 0; i < nIntervals; i++)
3596   {
3597     y1 = gInfo->u.weekInfo.schedBoxY1 + ((i * boxHt) / nIntervals);
3598     y2 = gInfo->u.weekInfo.schedBoxY1 + (((i + 1) * boxHt) / nIntervals);
3599     switch (gInfo->u.weekInfo.schedBucket[i])
3600     {
3601     case 0:
3602       currColor = 0;
3603       break;
3604
3605     case 1:
3606       currColor = 1;
3607       tOffset = (i % 4) ? 0 : ((gInfo->thinWd + 1) / 2);
3608       bOffset = ((i + 1) % 4) ? 1 : (gInfo->thinWd / 2) + 1;
3609       x_fill_dark_box(gInfo, x1, y1 + tOffset, x2,
3610                       y2 - bOffset, 0);
3611       break;
3612
3613     default:
3614       currColor = 2;
3615       x_fill_black_box(gInfo, x1, y1, x2, y2);
3616       break;
3617     }
3618
3619     if (currColor != lastColor)
3620     {
3621       if ((currColor != 2) && (lastColor != 2))
3622         x_draw_line(gInfo, x1, y1, x2 + 1, y1, gInfo->thinWd);
3623       lastColor = currColor;
3624     }
3625   }
3626 }
3627
3628 void
3629 x_init_month(void *gInfoP, int nRows)
3630 {
3631   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3632   CMFontInfo *fInfo;
3633
3634   gInfo->reportType = PR_MONTH_VIEW;
3635
3636   /* Load month fonts */
3637   if (gInfo->nFonts == 0)
3638   {
3639     int i;
3640
3641     for (i = 0; i < MV_NUM_FONTS; i++)
3642       cm_load_font(gInfo, i, mvFonts[i]);
3643
3644     /* Set curFont to first loaded font. */
3645     gInfo->curFont = gInfo->fontInfo;
3646   }
3647
3648   cm_adjust_margins(gInfo);
3649
3650   /* --- init for month view print --- */
3651   fInfo = cm_find_font(gInfo, MV_HEADER_FONT);
3652   gInfo->u.monthInfo.curX1 = gInfo->leftMarginX + (gInfo->normalWd / 2);
3653   gInfo->u.monthInfo.curY1 =
3654     gInfo->topMarginY + cm_font_height(gInfo, fInfo) +
3655       VMARGIN(gInfo) + (gInfo->normalWd / 2);
3656   gInfo->u.monthInfo.boxWd =
3657     gInfo->rightMarginX - gInfo->leftMarginX - gInfo->normalWd;
3658   gInfo->u.monthInfo.boxHt =
3659     gInfo->bottomMarginY - ((gInfo->normalWd + 1) / 2) -
3660       gInfo->u.monthInfo.curY1;
3661   fInfo = cm_find_font(gInfo, MV_DAY_FONT);
3662   gInfo->u.monthInfo.tab1 = 2 * cm_font_height(gInfo, fInfo);
3663   gInfo->u.monthInfo.nRows = nRows;
3664 }
3665
3666 int
3667 x_get_month_lines_per_page(void *gInfoP)
3668 {
3669   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3670   CMFontInfo *fInfo = cm_find_font(gInfo, MV_APPT_FONT);
3671   CMFontInfo *dateFInfo = cm_find_font(gInfo, MV_DATE_FONT);
3672   int dateSz = HMARGIN(gInfo) + cm_font_height(gInfo, dateFInfo);
3673
3674   return (((gInfo->u.monthInfo.boxHt - gInfo->u.monthInfo.tab1) /
3675            gInfo->u.monthInfo.nRows) -
3676           gInfo->normalWd - dateSz - (2 * VMARGIN(gInfo))) /
3677     cm_font_height(gInfo, fInfo);
3678 }
3679
3680 void
3681 x_month_daynames(void *gInfoP, int nRows)
3682 {
3683   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3684   char *day_of_week[DAYS_IN_WEEK];
3685   int i;
3686   Calendar *c = gInfo->c;
3687   int x1, y1, x2, y2;
3688   int dayBoxHt;
3689
3690   for (i = 0; i < DAYS_IN_WEEK; i++)
3691     local_dayname3(gInfo->c, &(day_of_week[i]), i);
3692
3693   /* Draw outer box. */
3694   x1 = gInfo->u.monthInfo.curX1;
3695   y1 = gInfo->u.monthInfo.curY1;
3696   x2 = x1 + gInfo->u.monthInfo.boxWd;
3697   y2 = y1 + gInfo->u.monthInfo.boxHt;
3698   x_draw_box(gInfo, x1, y1, x2, y2, gInfo->normalWd);
3699
3700   /* Draw box around days. */
3701   y2 = y1 + gInfo->u.monthInfo.tab1;
3702   x_fill_dark_box(gInfo, x1, y1, x2, y2, gInfo->normalWd);
3703
3704   cm_set_font(gInfo, MV_DAY_FONT);
3705   for (i = 0; i < DAYS_IN_WEEK; i++)
3706   {
3707     x1 = gInfo->u.monthInfo.curX1 +
3708       ((i * gInfo->u.monthInfo.boxWd) / DAYS_IN_WEEK);
3709     x2 = gInfo->u.monthInfo.curX1 +
3710       (((i + 1) * gInfo->u.monthInfo.boxWd) / DAYS_IN_WEEK);
3711
3712     cm_reverse_video(gInfo, True);
3713     x_print_string(gInfo, day_of_week[i],
3714                    (x1 + x2) / 2, (y1 + y2) / 2,
3715                    CENTER_AT_X | CENTER_AT_Y);
3716     free(day_of_week[i]);
3717
3718     cm_reverse_video(gInfo, False);
3719     if (i != 0)
3720       x_draw_line(gInfo, x1, y1, x1, y1 + gInfo->u.monthInfo.boxHt,
3721                   gInfo->normalWd);
3722   }
3723
3724   x1 = gInfo->u.monthInfo.curX1;
3725   x2 = x1 + gInfo->u.monthInfo.boxWd;
3726   dayBoxHt = gInfo->u.monthInfo.boxHt - gInfo->u.monthInfo.tab1;
3727
3728   /* Draw horizontal lines. */
3729   for (i = 1; i < nRows; i++)
3730   {
3731     y1 = gInfo->u.monthInfo.curY1 + gInfo->u.monthInfo.tab1 +
3732       ((i * dayBoxHt) / nRows);
3733     x_draw_line(gInfo, x1, y1, x2, y1, gInfo->normalWd);
3734   }
3735 }
3736
3737 void
3738 x_print_little_months(void *gInfoP, Tick tick)
3739 {
3740   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3741   int m = month(tick);          /* current month just printed */
3742   int y = year(tick);           /* year of month just printed */
3743   int fday = fdom(tick);        /* first day of month, 0=Sun ... */
3744
3745   int nm, nmy, pm, pmy;
3746
3747   int ndays = monthlength(tick);
3748   int nrows = gInfo->u.monthInfo.nRows;
3749   int pmIndex;
3750   int i, nBoxes;
3751   int x1, y1, x2, y2;
3752   int boxX1, boxY1, boxWd, boxHt;
3753   int ulOffset, brOffset;
3754   int dayRow, dayCol;
3755   int spacing;
3756
3757   /* 
3758    * Print out miniature prev & next month on month grid.
3759    * Check if there is enough room at end;  if not then
3760    * print at beginning of grid.
3761    */
3762   nBoxes = nrows * DAYS_IN_WEEK;
3763   if ((fday + ndays + 2) <= nBoxes)
3764   {
3765     pmIndex = nBoxes - 2;
3766   }
3767   else
3768   {
3769     pmIndex = 0;
3770   }
3771
3772   if (m == 12)
3773   {
3774     nm = 1;
3775     nmy = y + 1;
3776     pm = m - 1;
3777     pmy = y;
3778   }
3779   else if (m == 1)
3780   {
3781     nm = m + 1;
3782     nmy = y;
3783     pm = 12;
3784     pmy = y - 1;
3785   }
3786   else
3787   {
3788     nm = m + 1;
3789     pm = m - 1;
3790     nmy = pmy = y;
3791   }
3792
3793   boxX1 = gInfo->u.monthInfo.curX1;
3794   boxY1 = gInfo->u.monthInfo.curY1 + gInfo->u.monthInfo.tab1;
3795   boxWd = gInfo->u.monthInfo.boxWd;
3796   boxHt = gInfo->u.monthInfo.boxHt - gInfo->u.monthInfo.tab1;
3797   ulOffset = (gInfo->normalWd + 1) / 2;
3798   brOffset = (gInfo->normalWd / 2) + 1;
3799
3800   /* Determine spacing for drawing little months.  Can be negative. */
3801   for (spacing = VMARGIN(gInfo);
3802        cm_tiny_month_height(gInfo, spacing) >
3803        (boxHt / nrows) - gInfo->normalWd;
3804        spacing--)
3805     ;
3806
3807   /* Gray out extra boxes. */
3808   y1 = boxY1 + ulOffset;
3809   y2 = boxY1 - brOffset + (boxHt / nrows);
3810   for (i = 0; i < fday; i++)
3811   {
3812     x1 = boxX1 + ((i * boxWd) / DAYS_IN_WEEK) + ulOffset;
3813     x2 = boxX1 + (((i + 1) * boxWd) / DAYS_IN_WEEK) - brOffset;
3814
3815     x_fill_light_box(gInfo, x1, y1, x2, y2, 0);
3816
3817     if (i == pmIndex)
3818       x_print_month(gInfoP, pm, pmy, x1, y1, x2, y2, spacing);
3819     else if (i == (pmIndex + 1))
3820       x_print_month(gInfoP, nm, nmy, x1, y1, x2, y2, spacing);
3821   }
3822
3823   dayRow = (nBoxes - 1) / DAYS_IN_WEEK;
3824   y1 = boxY1 + ((dayRow * boxHt) / nrows) + ulOffset;
3825   y2 = boxY1 + (((dayRow + 1) * boxHt) / nrows) - brOffset;
3826   for (i = fday + ndays; i < nBoxes; i++)
3827   {
3828     dayCol = i % DAYS_IN_WEEK;
3829     x1 = boxX1 + ((dayCol * boxWd) / DAYS_IN_WEEK) + ulOffset;
3830     x2 = boxX1 + (((dayCol + 1) * boxWd) / DAYS_IN_WEEK) - brOffset;
3831
3832     x_fill_light_box(gInfo, x1, y1, x2, y2, 0);
3833
3834     if (i == pmIndex)
3835       x_print_month(gInfoP, pm, pmy, x1, y1, x2, y2, spacing);
3836     else if (i == (pmIndex + 1))
3837       x_print_month(gInfoP, nm, nmy, x1, y1, x2, y2, spacing);
3838   }
3839 }
3840
3841 void
3842 x_month_timeslots(void *gInfoP, Tick tick, Boolean more)
3843 {
3844   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3845   int fday = fdom(tick);        /* first day of month, 0=Sun ... */
3846   int thisDay = dom(tick);
3847   int nrows = gInfo->u.monthInfo.nRows;
3848   int x1, y1;
3849   int boxX1, boxY1, boxWd, boxHt;
3850   int ulOffset, brOffset;
3851   int dayRow, dayCol;
3852   char dateBuf[BUFFERSIZE];
3853
3854   boxX1 = gInfo->u.monthInfo.curX1;
3855   boxY1 = gInfo->u.monthInfo.curY1 + gInfo->u.monthInfo.tab1;
3856   boxWd = gInfo->u.monthInfo.boxWd;
3857   boxHt = gInfo->u.monthInfo.boxHt - gInfo->u.monthInfo.tab1;
3858   ulOffset = (gInfo->normalWd + 1) / 2;
3859   brOffset = (gInfo->normalWd / 2) + 1;
3860
3861   /* Write date into appropriate box. */
3862   cm_set_font(gInfo, MV_DATE_FONT);
3863   dayRow = (thisDay + fday - 1) / DAYS_IN_WEEK;
3864   dayCol = (thisDay + fday - 1) % DAYS_IN_WEEK;
3865
3866   gInfo->u.monthInfo.lineY = boxY1 + ((dayRow * boxHt) / nrows);
3867   gInfo->u.monthInfo.lineX = boxX1 + ((dayCol * boxWd) / DAYS_IN_WEEK);
3868   gInfo->u.monthInfo.lastX = gInfo->u.monthInfo.lineX + ulOffset;
3869   gInfo->u.monthInfo.lineMaxY = boxY1 + (((dayRow + 1) * boxHt) / nrows);
3870   gInfo->u.monthInfo.lineMaxX = boxX1 + (((dayCol + 1) * boxWd) /
3871                                          DAYS_IN_WEEK);
3872   y1 = gInfo->u.monthInfo.lineY + ulOffset + HMARGIN(gInfo);
3873   x1 = gInfo->u.monthInfo.lineX + ulOffset + VMARGIN(gInfo);
3874
3875   sprintf(dateBuf, more ? "%d *" : "%d", thisDay);
3876   x_print_string(gInfo, dateBuf, x1, y1, LEFT_AT_X | TOP_AT_Y);
3877
3878   gInfo->u.monthInfo.lineY =
3879     y1 + cm_font_height(gInfo, gInfo->curFont) + VMARGIN(gInfo);
3880 }
3881
3882 Boolean
3883 x_print_month_appts(void *gInfoP, CSA_entry_handle *list,
3884                     int a_total, int num_page,
3885                     time_t hi_hour, int lines_per_box)
3886 {
3887   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3888   int indented;
3889   Lines *lines;
3890   char buf1[BUFFERSIZE];
3891   Calendar *c = gInfo->c;
3892   Props *pr = (Props *)c->properties;
3893   int meoval = get_int_prop(pr, CP_PRINTPRIVACY);
3894   int i, start, pos = 1, line_counter = 0;      
3895   CSA_return_code stat;
3896   Dtcm_appointment *appt;
3897   Tick start_tick;
3898
3899   start = ((num_page - 1) * lines_per_box) + 1;
3900
3901   appt = allocate_appt_struct(appt_read,
3902                               c->general->version,
3903                               CSA_ENTRY_ATTR_CLASSIFICATION_I,
3904                               CSA_ENTRY_ATTR_START_DATE_I,
3905                               CSA_ENTRY_ATTR_SUMMARY_I,
3906                               CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,
3907                               NULL);
3908   for (i = 0; i < a_total; i++)
3909   {
3910     stat = query_appt_struct(c->cal_handle, list[i], appt);
3911     if (stat != CSA_SUCCESS)
3912     {
3913       free_appt_struct(&appt);
3914       return False;
3915     }
3916
3917     _csa_iso8601_to_tick(appt->time->value->item.date_time_value, &start_tick);
3918     if (start_tick >= hi_hour)
3919     {
3920       free_appt_struct(&appt);
3921       return True;
3922     }
3923  
3924     if ((privacy_set(appt) == CSA_CLASS_PUBLIC) &&
3925         !(meoval & PRINT_PUBLIC))
3926       continue;
3927     if ((privacy_set(appt) == CSA_CLASS_CONFIDENTIAL) &&
3928         !(meoval & PRINT_SEMIPRIVATE))
3929       continue;
3930     if ((privacy_set(appt) == CSA_CLASS_PRIVATE) &&
3931         !(meoval & PRINT_PRIVATE))
3932       continue;
3933
3934     if (pos < start)
3935     {
3936       pos++;
3937     }
3938     else
3939     {
3940       get_time_str(appt, buf1);
3941
3942       indented = (*buf1 != NULL);
3943
3944       lines = text_to_lines(appt->what->value->item.string_value, 1);
3945       line_counter++;
3946       if ((line_counter > lines_per_box) && (lines != NULL))
3947       {
3948         free_appt_struct(&appt);
3949         return(False);
3950       }
3951
3952       /* only print if appt text found */ 
3953       if ((lines != NULL) && (lines->s != NULL))
3954       {
3955         if (indented)   /* time found so print it */
3956           cm_print_month_time(gInfo, buf1);
3957         cm_print_month_text(gInfo, lines->s, indented ? 2 : 0);
3958       }
3959
3960       destroy_lines(lines);
3961     }
3962   }
3963
3964   free_appt_struct(&appt);
3965   return(True);
3966 }