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