dtcm: Coverity 88383
[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;
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         if (stat != CSA_SUCCESS) {
3014                 return;
3015         }
3016
3017         x_print_todo(xp, list, a_total, appt_type,
3018                      (start_tick != end_tick), todo_view, end, buf);
3019
3020         csa_free(list);
3021
3022         x_finish_printer(xp);
3023         x_print_file(xp, c);
3024 }
3025
3026 void
3027 x_init_list(void *gInfoP)
3028 {
3029   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3030   CMFontInfo *fInfo;
3031   int hIndent;
3032   int vIndent;
3033
3034   /* We can ONLY get here printing via dialog - printData is valid. */
3035   gInfo->reportType = pd_get_report_type(gInfo->c);
3036
3037   /* Load list fonts */
3038   if (gInfo->nFonts == 0)
3039   {
3040     int i;
3041
3042     if (gInfo->reportType == PR_APPT_LIST)
3043     {
3044       for (i = 0; i < AV_NUM_FONTS; i++)
3045         cm_load_font(gInfo, i, avFonts[i]);
3046     }
3047     else
3048     {
3049       for (i = 0; i < TV_NUM_FONTS; i++)
3050         cm_load_font(gInfo, i, tvFonts[i]);
3051     }
3052
3053     /* Set curFont to first loaded font. */
3054     gInfo->curFont = gInfo->fontInfo;
3055   }
3056
3057   cm_adjust_margins(gInfo);
3058
3059   cm_set_font(gInfo, cm_get_header_enum(gInfo));
3060
3061   hIndent = TODO_HINDENT * gInfo->hscale * gInfo->normalWd;
3062   vIndent = TODO_VINDENT * gInfo->vscale * gInfo->normalWd;
3063   gInfo->u.toDoInfo.outerX1 = gInfo->leftMarginX + (gInfo->thickWd / 2);
3064   gInfo->u.toDoInfo.outerY1 = gInfo->topMarginY + (gInfo->thickWd / 2) +
3065     cm_font_height(gInfo, gInfo->curFont) + VMARGIN(gInfo);
3066   gInfo->u.toDoInfo.innerX1 = gInfo->u.toDoInfo.outerX1 + hIndent;
3067   gInfo->u.toDoInfo.innerY1 = gInfo->u.toDoInfo.outerY1 + vIndent;
3068   gInfo->u.toDoInfo.outerX2 =
3069     gInfo->rightMarginX - ((gInfo->thickWd + 1) / 2);
3070   gInfo->u.toDoInfo.outerY2 =
3071     gInfo->bottomMarginY - ((gInfo->thickWd + 1) / 2);
3072   gInfo->u.toDoInfo.boxX2 = gInfo->u.toDoInfo.outerX2 - hIndent;
3073   gInfo->u.toDoInfo.boxY2 = gInfo->u.toDoInfo.outerY2 - vIndent;
3074   gInfo->u.toDoInfo.boxX1 = gInfo->u.toDoInfo.innerX1;
3075   gInfo->u.toDoInfo.boxY1 = gInfo->u.toDoInfo.boxY2 -
3076     cm_tiny_month_height(gInfo, VMARGIN(gInfo)) - gInfo->thickWd;
3077   gInfo->u.toDoInfo.innerX2 = gInfo->u.toDoInfo.boxX2;
3078   gInfo->u.toDoInfo.innerY2 = gInfo->u.toDoInfo.boxY1 - vIndent;
3079
3080   gInfo->u.toDoInfo.lineX =
3081     gInfo->u.toDoInfo.innerX1 + ((gInfo->thickWd + 1) / 2) + HMARGIN(gInfo);
3082   gInfo->u.toDoInfo.lineY =
3083     gInfo->u.toDoInfo.innerY1 + ((gInfo->thickWd + 1) / 2) + VMARGIN(gInfo);
3084 }
3085
3086 void
3087 x_print_todo(void *gInfoP, CSA_entry_handle *list, int a_total, 
3088              CSA_sint32 appt_type, Boolean showDate, int vf,
3089              time_t end_time, char *buf)
3090 {
3091         CMGraphicsInfo  *gInfo = (CMGraphicsInfo *)gInfoP;
3092         int             i, items_per_page = 0, meoval;
3093         char            buf3[BUFFERSIZE], buf2[BUFFERSIZE], buf1[BUFFERSIZE];
3094         int             total_items = 0;
3095         boolean_t       skip_appt;
3096         CSA_return_code stat;
3097         Dtcm_appointment *appt;
3098         Calendar        *c = gInfo->c;
3099         Props           *p = (Props*)c->properties;
3100         DisplayType     dt = get_int_prop(p, CP_DEFAULTDISP);
3101         OrderingType    ot = get_int_prop(p, CP_DATEORDERING);
3102         SeparatorType   st = get_int_prop(p, CP_DATESEPARATOR);
3103         Tick            start_tick;
3104         int             linesFullPage, linesPartialPage;
3105         int             numAppts, numPages, curPage;
3106
3107         curPage = 1;
3108         cm_get_todo_lines_per_page(gInfo, appt_type, &linesFullPage,
3109                                    &linesPartialPage);
3110         numAppts = cm_count_appts(gInfo, list, a_total, appt_type, vf);
3111         for (numPages = 1, numAppts -= linesPartialPage;
3112              numAppts > 0;
3113              numPages++)
3114           numAppts -= linesFullPage;
3115         x_print_header(gInfoP, buf, curPage, numPages);
3116         cm_todo_outline(gInfo, curPage == numPages);
3117         cm_set_todo_text_clipping(gInfo);
3118
3119         meoval = get_int_prop(p, CP_PRINTPRIVACY);
3120         buf1[0] = buf2[0] = buf3[0] = '\0';
3121
3122         appt = allocate_appt_struct(appt_read,
3123                                     c->general->version,
3124                                     CSA_ENTRY_ATTR_CLASSIFICATION_I,
3125                                     CSA_ENTRY_ATTR_TYPE_I,
3126                                     CSA_ENTRY_ATTR_STATUS_I,
3127                                     CSA_ENTRY_ATTR_START_DATE_I,
3128                                     CSA_ENTRY_ATTR_SUMMARY_I,
3129                                     CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,
3130                                     CSA_ENTRY_ATTR_END_DATE_I,
3131                                     NULL);
3132         for (i = 0; i < a_total; i++)
3133         {
3134           stat = query_appt_struct(c->cal_handle, list[i], appt);
3135           if (stat != CSA_SUCCESS)
3136           {
3137             free_appt_struct(&appt);
3138             return;
3139           }
3140           skip_appt = B_FALSE;
3141
3142           if ((privacy_set(appt) == CSA_CLASS_PUBLIC) &&
3143               !(meoval & PRINT_PUBLIC))
3144             skip_appt = B_TRUE;
3145           else if ((privacy_set(appt) == CSA_CLASS_CONFIDENTIAL) &&
3146                    !(meoval & PRINT_SEMIPRIVATE))
3147             skip_appt = B_TRUE;
3148           else if ((privacy_set(appt) == CSA_CLASS_PRIVATE) &&
3149                    !(meoval & PRINT_PRIVATE))
3150             skip_appt = B_TRUE;
3151
3152           if ((appt_type == CSA_TYPE_TODO) &&
3153               ((appt->type->value->item.sint32_value != CSA_TYPE_TODO)
3154                ||
3155                ((vf == VIEW_PENDING) &&
3156                 (appt->state->value->item.sint32_value ==
3157                  CSA_STATUS_COMPLETED)) ||
3158                ((vf == VIEW_COMPLETED) &&
3159                 (appt->state->value->item.sint32_value ==
3160                  CSA_X_DT_STATUS_ACTIVE))))
3161             skip_appt = B_TRUE;
3162
3163           if ((appt_type == CSA_TYPE_EVENT) &&
3164               (appt->type->value->item.sint32_value != CSA_TYPE_EVENT))
3165             skip_appt = B_TRUE;
3166
3167           if (skip_appt)
3168             continue;
3169
3170           format_maxchars(appt, buf1, BUFFERSIZE - 5, dt);
3171           if (showDate)
3172           {
3173             _csa_iso8601_to_tick(appt->time->value->item.date_time_value,
3174                                  &start_tick);
3175             format_date3(start_tick, ot, st, buf2);
3176             sprintf(buf3, "%s  %s", buf2, buf1);
3177           } else
3178             cm_strcpy(buf3, buf1);
3179
3180           total_items++;
3181           cm_print_todo_text (gInfo, buf3,
3182                               appt->state->value->item.sint32_value,
3183                               appt_type, total_items);
3184           if ((++items_per_page % linesFullPage) == 0)
3185           {
3186             cm_unset_todo_text_clipping(gInfo);
3187             x_finish_printer(gInfoP);
3188             x_init_printer(gInfoP, PORTRAIT);
3189             x_init_list(gInfoP);
3190             x_print_header(gInfoP, buf, ++curPage, numPages);
3191             cm_todo_outline(gInfo, curPage == numPages);
3192             cm_set_todo_text_clipping(gInfo);
3193             items_per_page = 0;
3194           }
3195         } /* end for stmt */
3196
3197         free_appt_struct(&appt);
3198         cm_unset_todo_text_clipping(gInfo);
3199
3200         if (items_per_page > linesPartialPage) {
3201           x_finish_printer(gInfoP);
3202           x_init_printer(gInfoP, PORTRAIT);
3203           x_init_list(gInfoP);
3204           x_print_header(gInfoP, buf, ++curPage, numPages);
3205           cm_todo_outline(gInfo, curPage == numPages);
3206         }
3207
3208         cm_print_todo_months(gInfo, end_time);
3209 }
3210
3211 void
3212 x_print_month(void *gInfoP, int mon, int yr, int x1,
3213               int y1, int x2, int y2, int spacing)
3214 {
3215   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3216   CMFontInfo *fInfo;
3217   Tick j = monthdayyear(mon, 1, yr);        /* starting date Jan 1, y */
3218   int i, colWd, dateWd, monLen;
3219   char str[BUFFERSIZE];
3220
3221   if (mon > 12)
3222     mon = (mon % 13) + 1;
3223   else if (mon < 1)
3224     mon = mon + 12;
3225
3226   x_set_clip_box(gInfo, x1, y1, x2, y2);
3227
3228   cm_set_font(gInfo, cm_get_tiny_title_enum(gInfo));
3229   y1 += spacing;
3230
3231   cm_strcpy(str, months[mon]);
3232
3233   {
3234     char *to = NULL;
3235     unsigned long to_len = 0;
3236     unsigned long _len;
3237
3238     _len = strlen(str);
3239     _converter_( str, _len, &to, &to_len );
3240     if ( ( to != NULL ) && ( to_len != 0 ) ) {
3241       cm_strcpy(str, to);
3242     }
3243   }
3244
3245   cm_strcpy(str, euc_to_octal(str));
3246   x_fill_light_box(gInfo, x1 + HMARGIN(gInfo), y1,
3247                    x2 - HMARGIN(gInfo),
3248                    y1 + cm_font_height(gInfo, gInfo->curFont),
3249                    0);
3250   x_print_string(gInfo, str,
3251                  (x1 + x2) / 2, y1,
3252                  CENTER_AT_X | TOP_AT_Y);
3253   y1 += spacing + cm_font_height(gInfo, gInfo->curFont);
3254
3255   fInfo = cm_find_font(gInfo, cm_get_tiny_date_enum(gInfo));
3256   monLen = monthlength(j);
3257   colWd = 0;
3258   for (i = 0; i < monLen; i++)
3259   {
3260     sprintf(str, "%d", i + 1);
3261     if ((dateWd = cm_string_width(gInfo, fInfo, str)) > colWd)
3262       colWd = dateWd;
3263   }
3264
3265   cm_std_month_weekdays(gInfo, colWd, x1, y1, x2);
3266   y1 += spacing + cm_font_height(gInfo, gInfo->curFont);
3267
3268   cm_std_month_dates(gInfo, fdom(j), monLen, colWd,
3269                      x1, y1, x2, spacing);
3270
3271   x_unset_clip_box(gInfo);
3272 }
3273
3274 void
3275 x_init_std_year(void *gInfoP)
3276 {
3277   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3278   CMFontInfo *fInfo;
3279
3280   gInfo->reportType = PR_YEAR_VIEW;
3281
3282   /* Load year fonts */
3283   if (gInfo->nFonts == 0)
3284   {
3285     int i;
3286
3287     for (i = 0; i < YV_NUM_FONTS; i++)
3288       cm_load_font(gInfo, i, yvFonts[i]);
3289
3290     /* Set curFont to first loaded font. */
3291     gInfo->curFont = gInfo->fontInfo;
3292   }
3293
3294   cm_adjust_margins(gInfo);
3295 }
3296
3297 void
3298 x_std_year_name(void *gInfoP, int yr)
3299 {
3300   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3301   char yearBuf[BUFFERSIZE];
3302
3303   /* --- print year centered at top --- */
3304   sprintf(yearBuf, "%d", yr);
3305   x_print_header(gInfoP, yearBuf, 1, 1);
3306 }
3307
3308 void
3309 x_print_year(void *gInfoP, int yr)
3310 {
3311   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3312   CMFontInfo *fInfo;
3313   int i;
3314   int leftX, topY;
3315   int x1, y1;
3316   int x2, y2;
3317   int row, col;
3318   int pageWd, pageHt;
3319   int monthHt;
3320   int extraSpace;
3321
3322   fInfo = cm_find_font(gInfo, YV_HEADER_FONT);
3323   monthHt = cm_tiny_month_height(gInfo, VMARGIN(gInfo));
3324
3325   leftX = gInfo->leftMarginX;
3326   topY = gInfo->topMarginY + cm_font_height(gInfo, fInfo) + VMARGIN(gInfo);
3327
3328   pageWd = gInfo->rightMarginX - leftX;
3329   pageHt = gInfo->bottomMarginY - topY;
3330   extraSpace = pageHt - (4 * monthHt);
3331
3332   for (i = 0; i < 12; i++)
3333   {
3334     row = i / 3;
3335     col = i % 3;
3336
3337     x1 = leftX + ((col * pageWd) / 3);
3338     x2 = leftX + (((col + 1) * pageWd) / 3);
3339
3340     if (extraSpace > 0)
3341     {
3342       y1 = topY + (((row + 1) * extraSpace) / 5) + (row * monthHt);
3343       y2 = topY + (((row + 2) * extraSpace) / 5) + ((row + 1) * monthHt);
3344     }
3345     else
3346     {
3347       y1 = topY + ((row * pageHt) / 4);
3348       y2 = topY + (((row + 1) * pageHt) / 4);
3349     }
3350
3351     x_print_month(gInfoP, i + 1, yr, x1, y1, x2, y2, VMARGIN(gInfo));
3352   }
3353 }
3354
3355 void
3356 x_init_week(void *gInfoP)
3357 {
3358   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3359   CMFontInfo *fInfo;
3360
3361   gInfo->reportType = PR_WEEK_VIEW;
3362
3363   /* Load week fonts */
3364   if (gInfo->nFonts == 0)
3365   {
3366     int i;
3367
3368     for (i = 0; i < WV_NUM_FONTS; i++)
3369       cm_load_font(gInfo, i, wvFonts[i]);
3370
3371     /* Set curFont to first loaded font. */
3372     gInfo->curFont = gInfo->fontInfo;
3373   }
3374
3375   cm_adjust_margins(gInfo);
3376
3377   fInfo = cm_find_font(gInfo, WV_HEADER_FONT);
3378   gInfo->u.weekInfo.curX1 = gInfo->leftMarginX + (gInfo->thickWd / 2);
3379   gInfo->u.weekInfo.curY1 = gInfo->topMarginY + cm_font_height(gInfo, fInfo) +
3380     VMARGIN(gInfo) + (gInfo->thickWd / 2);
3381   gInfo->u.weekInfo.boxWd =
3382     gInfo->rightMarginX - gInfo->leftMarginX - gInfo->thickWd;
3383   gInfo->u.weekInfo.boxHt =
3384     (gInfo->bottomMarginY - ((gInfo->thickWd + 1) / 2) -
3385      gInfo->u.weekInfo.curY1) / 2;
3386   gInfo->u.weekInfo.curY2 =
3387     gInfo->u.weekInfo.curY1 + gInfo->u.weekInfo.boxHt;
3388
3389   fInfo = cm_find_font(gInfo, WV_DAY_FONT);
3390   gInfo->u.weekInfo.tab1 =
3391     ((3 * cm_font_height(gInfo, fInfo)) +
3392      gInfo->thickWd + gInfo->normalWd) / 2;
3393 }
3394
3395 void
3396 x_week_appt_boxes(void *gInfoP)
3397 {
3398   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3399   int x1, y1, x2, y2;
3400   int innerWd, innerOffset;
3401   int i;
3402
3403   /* Draw weekdays box. */
3404   x1 = gInfo->u.weekInfo.curX1;
3405   y1 = gInfo->u.weekInfo.curY1;
3406   x2 = x1 + gInfo->u.weekInfo.boxWd;
3407   y2 = y1 + gInfo->u.weekInfo.tab1;
3408
3409   x_fill_light_box(gInfo, x1, y1, x2, y2, gInfo->normalWd);
3410
3411   y2 = gInfo->u.weekInfo.curY2;
3412   x_draw_box(gInfo, x1, y1, x2, y2, gInfo->thickWd);
3413
3414   /* Draw weekdays vertical lines. */
3415   innerWd = gInfo->u.weekInfo.boxWd - gInfo->thickWd + gInfo->normalWd;
3416   innerOffset = ((gInfo->thickWd - 1) / 2) - ((gInfo->normalWd - 1) / 2);
3417   for (i = 1; i < WEEK_DAYS; i++)
3418   {
3419     x1 = gInfo->u.weekInfo.curX1 + innerOffset + ((i * innerWd) / WEEK_DAYS);
3420     x_draw_line(gInfo, x1, y1, x1, y2, gInfo->normalWd);
3421   }
3422
3423   /* Draw weekends box. */
3424   x1 = gInfo->u.weekInfo.curX1 +
3425     (((WEEK_DAYS - WEEKEND_DAYS) * gInfo->u.weekInfo.boxWd) / WEEK_DAYS);
3426   y1 = y2;
3427   y2 = y1 + gInfo->u.weekInfo.tab1;
3428   x_fill_light_box(gInfo, x1, y1, x2, y2, gInfo->normalWd);
3429
3430   y2 = gInfo->bottomMarginY - ((gInfo->thickWd + 1) / 2);
3431   x_draw_box(gInfo, x1, y1, x2, y2, gInfo->thickWd);
3432
3433   /* Draw weekends vertical lines. */
3434   for (i = WEEK_DAYS - WEEKEND_DAYS + 1; i < WEEK_DAYS; i++)
3435   {
3436     x1 = gInfo->u.weekInfo.curX1 + innerOffset + ((i * innerWd) / WEEK_DAYS);
3437     x_draw_line(gInfo, x1, y1, x1, y2, gInfo->normalWd);
3438   }
3439 }
3440
3441 void
3442 x_week_sched_boxes(void *gInfoP)
3443 {
3444   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3445   char *day_of_week[DAYS_IN_WEEK];
3446   char hourBuf[BUFFERSIZE];
3447   Props *p = (Props *)gInfo->c->properties;
3448   int begin = get_int_prop(p, CP_DAYBEGIN);
3449   int end = get_int_prop(p, CP_DAYEND);
3450   DisplayType dt = get_int_prop(p, CP_DEFAULTDISP);
3451   int thisHour;
3452   int num_hours;
3453   int boxIndent;
3454   int boxX1, boxY1, boxX2, boxY2, boxWd, boxHt;
3455   int x1, y1, x2, y2;
3456   int i;
3457   int ulOff = gInfo->thickWd / 2;
3458   int brOff = (gInfo->thickWd - 1) / 2;
3459
3460   /* --- print week sched boxes --- */
3461
3462   /* figure out number of partitions in sched box */
3463   num_hours = end - begin;
3464
3465   /* determine offset of sched box from left margin */
3466   cm_set_font(gInfo, WV_DAY_FONT);
3467   boxIndent = cm_week_sched_box_indent(gInfo);
3468   boxX1 = gInfo->u.weekInfo.curX1 + boxIndent;
3469   boxX2 = gInfo->u.weekInfo.curX1 +
3470     ((3 * gInfo->u.weekInfo.boxWd) / WEEK_DAYS) - boxIndent;
3471   boxY1 = gInfo->u.weekInfo.curY2 +
3472     (2 * cm_font_height(gInfo, gInfo->curFont)) +
3473       gInfo->thickWd;
3474   boxY2 = gInfo->bottomMarginY - 1 - brOff;
3475
3476   x_draw_box(gInfo, boxX1, boxY1, boxX2, boxY2, gInfo->thickWd);
3477
3478   boxX1 += brOff - ((gInfo->normalWd - 1) / 2);
3479   boxX2 -= ulOff - (gInfo->normalWd / 2);
3480   boxY1 += brOff - ((gInfo->thinWd - 1) / 2);
3481   boxY2 -= ulOff - (gInfo->thinWd / 2);
3482   boxWd = boxX2 - boxX1;
3483   boxHt = boxY2 - boxY1;
3484
3485   for (i = 0; i < DAYS_IN_WEEK; i++)
3486     local_dayname(gInfo->c, &day_of_week[i], (i + 1) % DAYS_IN_WEEK);
3487
3488   /* print abbreviated weekdays on top and draw vertical lines. */
3489   for (i = 0; i < DAYS_IN_WEEK; i++)
3490   {
3491     x1 = boxX1 + ((i * boxWd) / DAYS_IN_WEEK);
3492     x2 = boxX1 + (((i + 1) * boxWd) / DAYS_IN_WEEK);
3493
3494     x_print_string(gInfo, day_of_week[i],
3495                    (x1 + x2) / 2, boxY1 -
3496                    gInfo->thickWd - (2 * VMARGIN(gInfo)),
3497                    CENTER_AT_X | BOTTOM_AT_Y);
3498     free(day_of_week[i]);
3499     if (i > 0)
3500       x_draw_line(gInfo, x1, boxY1, x1, boxY2, gInfo->normalWd);
3501   }
3502
3503   /* Print hours and horizontal lines. */
3504   for (thisHour = begin, i = 0; i <= num_hours; i++, thisHour++)
3505   {
3506     if ( dt == HOUR12 )
3507     {
3508       if (thisHour > 12)
3509         thisHour %= 12;
3510     }
3511     else if ( dt == HOUR24 )
3512     {
3513       if (thisHour > 24)
3514         thisHour %= 24;
3515     }
3516     sprintf(hourBuf, "%d", thisHour);
3517     y1 = boxY1 + ((i * boxHt) / num_hours);
3518
3519     x_print_string(gInfo, hourBuf,
3520                    boxX1 - gInfo->thickWd - HMARGIN(gInfo), y1,
3521                    RIGHT_AT_X | CENTER_AT_Y);
3522
3523     if ((i > 0) && (i < num_hours))
3524       x_draw_line(gInfo, boxX1, y1, boxX2, y1, gInfo->thinWd);
3525   }
3526
3527   gInfo->u.weekInfo.schedBoxX1 = boxX1;
3528   gInfo->u.weekInfo.schedBoxY1 = boxY1;
3529   gInfo->u.weekInfo.schedBoxX2 = boxX2;
3530   gInfo->u.weekInfo.schedBoxY2 = boxY2;
3531 }
3532
3533 void
3534 x_week_daynames(void *gInfoP, char *dayName, int dayIndex, Boolean more)
3535 {
3536   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3537   Calendar *c = gInfo->c;
3538   int x1, y1, x2, y2;
3539   int innerOffset, innerWd;
3540   char dayBuf[BUFFERSIZE];
3541
3542   y1 = (dayIndex < WEEK_DAYS) ? gInfo->u.weekInfo.curY1 :
3543     gInfo->u.weekInfo.curY2;
3544   y2 = y1 + gInfo->u.weekInfo.tab1;
3545
3546   cm_set_font(gInfo, WV_DAY_FONT);
3547
3548   innerWd = gInfo->u.weekInfo.boxWd - gInfo->thickWd + gInfo->normalWd;
3549   innerOffset = ((gInfo->thickWd - 1) / 2) - ((gInfo->normalWd - 1) / 2);
3550
3551   if (dayIndex >= WEEK_DAYS)
3552     dayIndex -= WEEKEND_DAYS;
3553   x1 = gInfo->u.weekInfo.curX1 + innerOffset +
3554     ((dayIndex * innerWd) / WEEK_DAYS);
3555   x2 = gInfo->u.weekInfo.curX1 + innerOffset +
3556     (((dayIndex + 1) * innerWd) / WEEK_DAYS);
3557
3558   {
3559     char *to = NULL;
3560     unsigned long to_len = 0;
3561     unsigned long _len;
3562
3563     _len = strlen(dayName);
3564     _converter_( dayName, _len, &to, &to_len );
3565     if ( ( to != NULL ) && ( to_len != 0 ) ) {
3566       dayName = to;
3567     }
3568   }
3569
3570   sprintf(dayBuf, more ? "%s *" : "%s", euc_to_octal(dayName));
3571   x_print_string(gInfo, dayBuf, (x1 + x2) / 2, (y1 + y2) / 2,
3572                  CENTER_AT_X | CENTER_AT_Y);
3573
3574   gInfo->u.weekInfo.lineX = x1;
3575   gInfo->u.weekInfo.lineY = y2 + ((gInfo->normalWd + 1) / 2) + VMARGIN(gInfo);
3576   gInfo->u.weekInfo.lineMaxY = y1 + gInfo->u.weekInfo.boxHt;
3577 }
3578
3579 void
3580 x_week_sched_init(void *gInfoP)
3581 {
3582   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3583
3584   memset(gInfo->u.weekInfo.schedBucket, 0,
3585          sizeof(gInfo->u.weekInfo.schedBucket));
3586 }
3587
3588 void
3589 x_week_sched_draw(void *gInfoP, int dayIndex)
3590 {
3591   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3592   int i;
3593   Props *p = (Props *)gInfo->c->properties;
3594   int begin = get_int_prop(p, CP_DAYBEGIN);
3595   int end = get_int_prop(p, CP_DAYEND);
3596   int num_hours = end - begin;
3597   int nIntervals = num_hours * 4;
3598   int x1, y1, x2, y2;
3599   int boxWd = gInfo->u.weekInfo.schedBoxX2 - gInfo->u.weekInfo.schedBoxX1;
3600   int boxHt = gInfo->u.weekInfo.schedBoxY2 - gInfo->u.weekInfo.schedBoxY1;
3601   int currColor, lastColor;
3602   int tOffset, bOffset;
3603
3604   x1 = gInfo->u.weekInfo.schedBoxX1 +
3605     ((dayIndex * boxWd) / DAYS_IN_WEEK) + ((gInfo->normalWd + 1) / 2);
3606   x2 = gInfo->u.weekInfo.schedBoxX1 +
3607     (((dayIndex + 1) * boxWd) / DAYS_IN_WEEK) - (gInfo->normalWd / 2) - 1;
3608
3609   lastColor = 0;
3610   for (i = 0; i < nIntervals; i++)
3611   {
3612     y1 = gInfo->u.weekInfo.schedBoxY1 + ((i * boxHt) / nIntervals);
3613     y2 = gInfo->u.weekInfo.schedBoxY1 + (((i + 1) * boxHt) / nIntervals);
3614     switch (gInfo->u.weekInfo.schedBucket[i])
3615     {
3616     case 0:
3617       currColor = 0;
3618       break;
3619
3620     case 1:
3621       currColor = 1;
3622       tOffset = (i % 4) ? 0 : ((gInfo->thinWd + 1) / 2);
3623       bOffset = ((i + 1) % 4) ? 1 : (gInfo->thinWd / 2) + 1;
3624       x_fill_dark_box(gInfo, x1, y1 + tOffset, x2,
3625                       y2 - bOffset, 0);
3626       break;
3627
3628     default:
3629       currColor = 2;
3630       x_fill_black_box(gInfo, x1, y1, x2, y2);
3631       break;
3632     }
3633
3634     if (currColor != lastColor)
3635     {
3636       if ((currColor != 2) && (lastColor != 2))
3637         x_draw_line(gInfo, x1, y1, x2 + 1, y1, gInfo->thinWd);
3638       lastColor = currColor;
3639     }
3640   }
3641 }
3642
3643 void
3644 x_init_month(void *gInfoP, int nRows)
3645 {
3646   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3647   CMFontInfo *fInfo;
3648
3649   gInfo->reportType = PR_MONTH_VIEW;
3650
3651   /* Load month fonts */
3652   if (gInfo->nFonts == 0)
3653   {
3654     int i;
3655
3656     for (i = 0; i < MV_NUM_FONTS; i++)
3657       cm_load_font(gInfo, i, mvFonts[i]);
3658
3659     /* Set curFont to first loaded font. */
3660     gInfo->curFont = gInfo->fontInfo;
3661   }
3662
3663   cm_adjust_margins(gInfo);
3664
3665   /* --- init for month view print --- */
3666   fInfo = cm_find_font(gInfo, MV_HEADER_FONT);
3667   gInfo->u.monthInfo.curX1 = gInfo->leftMarginX + (gInfo->normalWd / 2);
3668   gInfo->u.monthInfo.curY1 =
3669     gInfo->topMarginY + cm_font_height(gInfo, fInfo) +
3670       VMARGIN(gInfo) + (gInfo->normalWd / 2);
3671   gInfo->u.monthInfo.boxWd =
3672     gInfo->rightMarginX - gInfo->leftMarginX - gInfo->normalWd;
3673   gInfo->u.monthInfo.boxHt =
3674     gInfo->bottomMarginY - ((gInfo->normalWd + 1) / 2) -
3675       gInfo->u.monthInfo.curY1;
3676   fInfo = cm_find_font(gInfo, MV_DAY_FONT);
3677   gInfo->u.monthInfo.tab1 = 2 * cm_font_height(gInfo, fInfo);
3678   gInfo->u.monthInfo.nRows = nRows;
3679 }
3680
3681 int
3682 x_get_month_lines_per_page(void *gInfoP)
3683 {
3684   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3685   CMFontInfo *fInfo = cm_find_font(gInfo, MV_APPT_FONT);
3686   CMFontInfo *dateFInfo = cm_find_font(gInfo, MV_DATE_FONT);
3687   int dateSz = HMARGIN(gInfo) + cm_font_height(gInfo, dateFInfo);
3688
3689   return (((gInfo->u.monthInfo.boxHt - gInfo->u.monthInfo.tab1) /
3690            gInfo->u.monthInfo.nRows) -
3691           gInfo->normalWd - dateSz - (2 * VMARGIN(gInfo))) /
3692     cm_font_height(gInfo, fInfo);
3693 }
3694
3695 void
3696 x_month_daynames(void *gInfoP, int nRows)
3697 {
3698   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3699   char *day_of_week[DAYS_IN_WEEK];
3700   int i;
3701   Calendar *c = gInfo->c;
3702   int x1, y1, x2, y2;
3703   int dayBoxHt;
3704
3705   for (i = 0; i < DAYS_IN_WEEK; i++)
3706     local_dayname3(gInfo->c, &(day_of_week[i]), i);
3707
3708   /* Draw outer box. */
3709   x1 = gInfo->u.monthInfo.curX1;
3710   y1 = gInfo->u.monthInfo.curY1;
3711   x2 = x1 + gInfo->u.monthInfo.boxWd;
3712   y2 = y1 + gInfo->u.monthInfo.boxHt;
3713   x_draw_box(gInfo, x1, y1, x2, y2, gInfo->normalWd);
3714
3715   /* Draw box around days. */
3716   y2 = y1 + gInfo->u.monthInfo.tab1;
3717   x_fill_dark_box(gInfo, x1, y1, x2, y2, gInfo->normalWd);
3718
3719   cm_set_font(gInfo, MV_DAY_FONT);
3720   for (i = 0; i < DAYS_IN_WEEK; i++)
3721   {
3722     x1 = gInfo->u.monthInfo.curX1 +
3723       ((i * gInfo->u.monthInfo.boxWd) / DAYS_IN_WEEK);
3724     x2 = gInfo->u.monthInfo.curX1 +
3725       (((i + 1) * gInfo->u.monthInfo.boxWd) / DAYS_IN_WEEK);
3726
3727     cm_reverse_video(gInfo, True);
3728     x_print_string(gInfo, day_of_week[i],
3729                    (x1 + x2) / 2, (y1 + y2) / 2,
3730                    CENTER_AT_X | CENTER_AT_Y);
3731     free(day_of_week[i]);
3732
3733     cm_reverse_video(gInfo, False);
3734     if (i != 0)
3735       x_draw_line(gInfo, x1, y1, x1, y1 + gInfo->u.monthInfo.boxHt,
3736                   gInfo->normalWd);
3737   }
3738
3739   x1 = gInfo->u.monthInfo.curX1;
3740   x2 = x1 + gInfo->u.monthInfo.boxWd;
3741   dayBoxHt = gInfo->u.monthInfo.boxHt - gInfo->u.monthInfo.tab1;
3742
3743   /* Draw horizontal lines. */
3744   for (i = 1; i < nRows; i++)
3745   {
3746     y1 = gInfo->u.monthInfo.curY1 + gInfo->u.monthInfo.tab1 +
3747       ((i * dayBoxHt) / nRows);
3748     x_draw_line(gInfo, x1, y1, x2, y1, gInfo->normalWd);
3749   }
3750 }
3751
3752 void
3753 x_print_little_months(void *gInfoP, Tick tick)
3754 {
3755   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3756   int m = month(tick);          /* current month just printed */
3757   int y = year(tick);           /* year of month just printed */
3758   int fday = fdom(tick);        /* first day of month, 0=Sun ... */
3759
3760   int nm, nmy, pm, pmy;
3761
3762   int ndays = monthlength(tick);
3763   int nrows = gInfo->u.monthInfo.nRows;
3764   int pmIndex;
3765   int i, nBoxes;
3766   int x1, y1, x2, y2;
3767   int boxX1, boxY1, boxWd, boxHt;
3768   int ulOffset, brOffset;
3769   int dayRow, dayCol;
3770   int spacing;
3771
3772   /* 
3773    * Print out miniature prev & next month on month grid.
3774    * Check if there is enough room at end;  if not then
3775    * print at beginning of grid.
3776    */
3777   nBoxes = nrows * DAYS_IN_WEEK;
3778   if ((fday + ndays + 2) <= nBoxes)
3779   {
3780     pmIndex = nBoxes - 2;
3781   }
3782   else
3783   {
3784     pmIndex = 0;
3785   }
3786
3787   if (m == 12)
3788   {
3789     nm = 1;
3790     nmy = y + 1;
3791     pm = m - 1;
3792     pmy = y;
3793   }
3794   else if (m == 1)
3795   {
3796     nm = m + 1;
3797     nmy = y;
3798     pm = 12;
3799     pmy = y - 1;
3800   }
3801   else
3802   {
3803     nm = m + 1;
3804     pm = m - 1;
3805     nmy = pmy = y;
3806   }
3807
3808   boxX1 = gInfo->u.monthInfo.curX1;
3809   boxY1 = gInfo->u.monthInfo.curY1 + gInfo->u.monthInfo.tab1;
3810   boxWd = gInfo->u.monthInfo.boxWd;
3811   boxHt = gInfo->u.monthInfo.boxHt - gInfo->u.monthInfo.tab1;
3812   ulOffset = (gInfo->normalWd + 1) / 2;
3813   brOffset = (gInfo->normalWd / 2) + 1;
3814
3815   /* Determine spacing for drawing little months.  Can be negative. */
3816   for (spacing = VMARGIN(gInfo);
3817        cm_tiny_month_height(gInfo, spacing) >
3818        (boxHt / nrows) - gInfo->normalWd;
3819        spacing--)
3820     ;
3821
3822   /* Gray out extra boxes. */
3823   y1 = boxY1 + ulOffset;
3824   y2 = boxY1 - brOffset + (boxHt / nrows);
3825   for (i = 0; i < fday; i++)
3826   {
3827     x1 = boxX1 + ((i * boxWd) / DAYS_IN_WEEK) + ulOffset;
3828     x2 = boxX1 + (((i + 1) * boxWd) / DAYS_IN_WEEK) - brOffset;
3829
3830     x_fill_light_box(gInfo, x1, y1, x2, y2, 0);
3831
3832     if (i == pmIndex)
3833       x_print_month(gInfoP, pm, pmy, x1, y1, x2, y2, spacing);
3834     else if (i == (pmIndex + 1))
3835       x_print_month(gInfoP, nm, nmy, x1, y1, x2, y2, spacing);
3836   }
3837
3838   dayRow = (nBoxes - 1) / DAYS_IN_WEEK;
3839   y1 = boxY1 + ((dayRow * boxHt) / nrows) + ulOffset;
3840   y2 = boxY1 + (((dayRow + 1) * boxHt) / nrows) - brOffset;
3841   for (i = fday + ndays; i < nBoxes; i++)
3842   {
3843     dayCol = i % DAYS_IN_WEEK;
3844     x1 = boxX1 + ((dayCol * boxWd) / DAYS_IN_WEEK) + ulOffset;
3845     x2 = boxX1 + (((dayCol + 1) * boxWd) / DAYS_IN_WEEK) - brOffset;
3846
3847     x_fill_light_box(gInfo, x1, y1, x2, y2, 0);
3848
3849     if (i == pmIndex)
3850       x_print_month(gInfoP, pm, pmy, x1, y1, x2, y2, spacing);
3851     else if (i == (pmIndex + 1))
3852       x_print_month(gInfoP, nm, nmy, x1, y1, x2, y2, spacing);
3853   }
3854 }
3855
3856 void
3857 x_month_timeslots(void *gInfoP, Tick tick, Boolean more)
3858 {
3859   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3860   int fday = fdom(tick);        /* first day of month, 0=Sun ... */
3861   int thisDay = dom(tick);
3862   int nrows = gInfo->u.monthInfo.nRows;
3863   int x1, y1;
3864   int boxX1, boxY1, boxWd, boxHt;
3865   int ulOffset, brOffset;
3866   int dayRow, dayCol;
3867   char dateBuf[BUFFERSIZE];
3868
3869   boxX1 = gInfo->u.monthInfo.curX1;
3870   boxY1 = gInfo->u.monthInfo.curY1 + gInfo->u.monthInfo.tab1;
3871   boxWd = gInfo->u.monthInfo.boxWd;
3872   boxHt = gInfo->u.monthInfo.boxHt - gInfo->u.monthInfo.tab1;
3873   ulOffset = (gInfo->normalWd + 1) / 2;
3874   brOffset = (gInfo->normalWd / 2) + 1;
3875
3876   /* Write date into appropriate box. */
3877   cm_set_font(gInfo, MV_DATE_FONT);
3878   dayRow = (thisDay + fday - 1) / DAYS_IN_WEEK;
3879   dayCol = (thisDay + fday - 1) % DAYS_IN_WEEK;
3880
3881   gInfo->u.monthInfo.lineY = boxY1 + ((dayRow * boxHt) / nrows);
3882   gInfo->u.monthInfo.lineX = boxX1 + ((dayCol * boxWd) / DAYS_IN_WEEK);
3883   gInfo->u.monthInfo.lastX = gInfo->u.monthInfo.lineX + ulOffset;
3884   gInfo->u.monthInfo.lineMaxY = boxY1 + (((dayRow + 1) * boxHt) / nrows);
3885   gInfo->u.monthInfo.lineMaxX = boxX1 + (((dayCol + 1) * boxWd) /
3886                                          DAYS_IN_WEEK);
3887   y1 = gInfo->u.monthInfo.lineY + ulOffset + HMARGIN(gInfo);
3888   x1 = gInfo->u.monthInfo.lineX + ulOffset + VMARGIN(gInfo);
3889
3890   sprintf(dateBuf, more ? "%d *" : "%d", thisDay);
3891   x_print_string(gInfo, dateBuf, x1, y1, LEFT_AT_X | TOP_AT_Y);
3892
3893   gInfo->u.monthInfo.lineY =
3894     y1 + cm_font_height(gInfo, gInfo->curFont) + VMARGIN(gInfo);
3895 }
3896
3897 Boolean
3898 x_print_month_appts(void *gInfoP, CSA_entry_handle *list,
3899                     int a_total, int num_page,
3900                     time_t hi_hour, int lines_per_box)
3901 {
3902   CMGraphicsInfo *gInfo = (CMGraphicsInfo *)gInfoP;
3903   int indented;
3904   Lines *lines;
3905   char buf1[BUFFERSIZE];
3906   Calendar *c = gInfo->c;
3907   Props *pr = (Props *)c->properties;
3908   int meoval = get_int_prop(pr, CP_PRINTPRIVACY);
3909   int i, start, pos = 1, line_counter = 0;      
3910   CSA_return_code stat;
3911   Dtcm_appointment *appt;
3912   Tick start_tick;
3913
3914   start = ((num_page - 1) * lines_per_box) + 1;
3915
3916   appt = allocate_appt_struct(appt_read,
3917                               c->general->version,
3918                               CSA_ENTRY_ATTR_CLASSIFICATION_I,
3919                               CSA_ENTRY_ATTR_START_DATE_I,
3920                               CSA_ENTRY_ATTR_SUMMARY_I,
3921                               CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,
3922                               NULL);
3923   for (i = 0; i < a_total; i++)
3924   {
3925     stat = query_appt_struct(c->cal_handle, list[i], appt);
3926     if (stat != CSA_SUCCESS)
3927     {
3928       free_appt_struct(&appt);
3929       return False;
3930     }
3931
3932     _csa_iso8601_to_tick(appt->time->value->item.date_time_value, &start_tick);
3933     if (start_tick >= hi_hour)
3934     {
3935       free_appt_struct(&appt);
3936       return True;
3937     }
3938  
3939     if ((privacy_set(appt) == CSA_CLASS_PUBLIC) &&
3940         !(meoval & PRINT_PUBLIC))
3941       continue;
3942     if ((privacy_set(appt) == CSA_CLASS_CONFIDENTIAL) &&
3943         !(meoval & PRINT_SEMIPRIVATE))
3944       continue;
3945     if ((privacy_set(appt) == CSA_CLASS_PRIVATE) &&
3946         !(meoval & PRINT_PRIVATE))
3947       continue;
3948
3949     if (pos < start)
3950     {
3951       pos++;
3952     }
3953     else
3954     {
3955       get_time_str(appt, buf1);
3956
3957       indented = (*buf1 != '\0');
3958
3959       lines = text_to_lines(appt->what->value->item.string_value, 1);
3960       line_counter++;
3961       if ((line_counter > lines_per_box) && (lines != NULL))
3962       {
3963         free_appt_struct(&appt);
3964         return(False);
3965       }
3966
3967       /* only print if appt text found */ 
3968       if ((lines != NULL) && (lines->s != NULL))
3969       {
3970         if (indented)   /* time found so print it */
3971           cm_print_month_time(gInfo, buf1);
3972         cm_print_month_text(gInfo, lines->s, indented ? 2 : 0);
3973       }
3974
3975       destroy_lines(lines);
3976     }
3977   }
3978
3979   free_appt_struct(&appt);
3980   return(True);
3981 }