dtcm: Resolve CID 87562
[oweals/cde.git] / cde / programs / dtcm / dtcm / dayglance.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*******************************************************************************
24 **
25 **  dayglance.c
26 **
27 **  $XConsortium: dayglance.c /main/10 1996/11/21 19:42:19 drk $
28 **
29 **  RESTRICTED CONFIDENTIAL INFORMATION:
30 **
31 **  The information in this document is subject to special
32 **  restrictions in a confidential disclosure agreement between
33 **  HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
34 **  document outside HP, IBM, Sun, USL, SCO, or Univel without
35 **  Sun's specific written approval.  This document and all copies
36 **  and derivative works thereof must be returned or destroyed at
37 **  Sun's request.
38 **
39 **  Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
40 **
41 *******************************************************************************/
42
43 /*                                                                      *
44  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
45  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
46  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
47  * (c) Copyright 1993, 1994 Novell, Inc.                                *
48  */
49
50 #ifndef lint
51 static char sccsid[] = "@(#)dayglance.c 1.76 95/04/24 Copyr 1991 Sun Microsystems, Inc.";
52 #endif
53
54 #include <EUSCompat.h>
55 #include <stdio.h>
56 #include <Xm/Xm.h>
57 #include <Xm/Form.h>
58 #include <Xm/Text.h>
59 #include <Xm/ToggleBG.h>
60 #include <Dt/HourGlass.h>
61 #include "util.h"
62 #include "stdlib.h"
63 #include "calendar.h"
64 #include "timeops.h"
65 #include "datefield.h"
66 #include "props.h"
67 #include "help.h"
68 #include "x_graphics.h"
69 #include "format.h"
70 #include "weekglance.h"
71 #include "monthglance.h"
72 #include "yearglance.h"
73 #include "MonthPanel.h"
74 #include "getdate.h"
75 #include "select.h"
76 #include "dayglance.h"
77 #include "editor.h"
78 #include "todo.h"
79 #include "print.h"
80 #include "group_editor.h"
81
82 #define XOS_USE_XT_LOCKING
83 #define X_INCLUDE_TIME_H
84 #if defined(linux)
85 #undef SVR4
86 #endif
87 #include <X11/Xos_r.h>
88
89 extern int debug;
90
91
92 /* private function prototypes */
93 static Boolean _print_day(Calendar*, int, void *,
94                           Tick, Props*, Boolean);
95 static void day_btn_cb(Widget, XtPointer, XtPointer);
96 static void create_month_panels(Calendar *);
97 static void display_monthpanels(Calendar *);
98 static void update_quarter(Calendar *);
99 static Boolean in_moboxes(Calendar *, int, int);
100
101 #define INSIDE_MARGIN 6
102
103 extern void
104 paint_day_header(Calendar *c, Tick date, void *rect)
105 {
106         Props *p = (Props*)c->properties;
107         OrderingType ot = get_int_prop(p, CP_DATEORDERING);
108         int pfy, x;
109         char buf[100];
110         Boolean inrange = False;
111         Colormap cmap;
112         Pixel foreground_pixel;
113         XFontSetExtents fontextents;
114         struct tm *tm;
115         _Xltimeparams localtime_buf;
116
117         tm = _XLocaltime(&date, localtime_buf);
118
119         CalFontExtents(c->fonts->labelfont, &fontextents);
120         pfy = fontextents.max_logical_extent.height;
121         XtVaGetValues(c->canvas, XmNcolormap, &cmap, NULL);
122         XtVaGetValues(c->canvas, XmNforeground, &foreground_pixel, NULL);
123         buf [0] = '\0';
124         /* NL_COMMENT
125            Attention Translator:
126
127            This string is used in the calendar day view.  In the C locale
128            it has the form:
129
130                 Monday, January 16, 1995
131
132            strftime conversion string: "%A, %B %e, %Y" is used.  
133
134            Use the appropriate strftime conversion for your locale.
135         */
136         strftime(buf, 100, catgets(c->DT_catd, 1, 992, "%A, %B %e, %Y"), tm);
137         inrange = today_inrange(c, date);
138         x = gr_center(c->view->winw-(int)MOBOX_AREA_WIDTH, buf,
139                         c->fonts->labelfont) + (int)MOBOX_AREA_WIDTH;
140         if (c->xcontext->screen_depth >= 8 && inrange) 
141                 gr_text_rgb(c->xcontext, x, c->view->topoffset - (pfy/2),
142                         c->fonts->labelfont, buf, foreground_pixel, 
143                         cmap, rect);
144         else
145                 gr_text(c->xcontext, x, c->view->topoffset - (pfy/2),
146                         c->fonts->labelfont, buf, rect);
147 }
148         
149 extern int
150 morning(int hr)
151 {
152         return(hr<12);
153 }
154
155 static void
156 paint_dayview_appts(Calendar *c, Paint_cache *cache, int a_total, void *rect)
157 {
158         int w = c->view->boxw;
159         int h = c->view->boxh;
160         int begin_time, end_time;
161         int x, x2, y, y2, num_hrs, i, last_hr, hr, x_off;
162         Cal_Font *pf = c->fonts->boldfont;
163         Cal_Font *pf2 = c->fonts->viewfont;
164         XFontSetExtents fontextents;
165         XFontSetExtents fontextents2;
166         Props *p = (Props*)c->properties;
167         Boolean am = True;
168         char buf[5], *appt_str;
169         int pfy, curr_line, maxlines;
170         Lines *lines = NULL, *headlines = NULL;
171         DisplayType disp_t;
172         Colormap cmap;
173         Pixel fg;
174         Tick start_tick, end_tick;
175         int     nop, hrbox_margin;
176
177         CalFontExtents(pf, &fontextents);
178         CalFontExtents(pf2, &fontextents2);
179
180
181         XtVaGetValues(c->canvas, XmNcolormap, &cmap, XmNforeground, &fg, NULL);
182
183         /* draw horizontal lines */
184         begin_time = get_int_prop(p, CP_DAYBEGIN);
185         end_time = get_int_prop(p, CP_DAYEND);
186         disp_t = get_int_prop(p, CP_DEFAULTDISP);
187         num_hrs = end_time - begin_time + 1;
188
189         if (disp_t == HOUR12)
190                 CalTextExtents(pf, "12pm", 4, &nop, &nop, &hrbox_margin, &nop);
191         else
192                 CalTextExtents(pf, "24 ", 3, &nop, &nop, &hrbox_margin, &nop);
193
194         x = MOBOX_AREA_WIDTH+2;
195         x2 = x + w;
196         y = c->view->topoffset;
197         for (i = 0; i <= num_hrs; i++) {
198                 gr_draw_line(c->xcontext, x, y, x2, y, gr_solid, rect);
199                 y += h;
200         }
201         /* draw vertical line */
202         y = c->view->topoffset;
203         y2 = y + num_hrs * h;
204         x += hrbox_margin;
205         gr_draw_line(c->xcontext, x, y, x, y2, gr_solid, rect);
206
207         x = MOBOX_AREA_WIDTH+3;
208         y += h/2+4;
209
210         /* draw in hours */
211         for (i = begin_time - 1; i < end_time; i++) {
212                 hr = i;
213                 if (i < begin_time)
214                         buf[0] = '\0';
215                 else if (disp_t == HOUR12) {
216                         am = adjust_hour(&hr);
217                         (void) sprintf(buf, "%d%s", hr, am ? "a" : "p");
218                 }
219                 else
220                         (void) sprintf(buf, "%02d", hr);
221                 x_off = gr_center(hrbox_margin, buf, pf); 
222
223 /* REVISIT: unclear why we're still distinguishing between gr_text[_rgb]
224                 if (c->xcontext->screen_depth >= 8) 
225                         gr_text_rgb(c->xcontext, x+x_off, y, pf,
226                                 buf, fg, cmap, rect);
227                 else
228 */
229                         gr_text(c->xcontext, x+x_off, y, pf, buf, rect);
230
231                 y += h;
232         }
233
234         /* draw in appointments */
235
236         x = MOBOX_AREA_WIDTH + hrbox_margin + 6;
237         pfy = fontextents2.max_logical_extent.height;
238
239         maxlines = (h - 6) / pfy;
240         curr_line = last_hr = 0;
241
242         /* loop thru, getting out the "no time" appointments */
243
244         for (i = 0; i < a_total; i++) {
245                 if (i != a_total)
246                         last_hr = hr;
247                 hr = begin_time;
248                 if (cache[i].show_time == 0) {
249                         if (last_hr != hr) curr_line = 0;
250                         y = c->view->topoffset + 2 + pfy;
251                         if (curr_line < maxlines) {
252                                 y += (curr_line * pfy) + h * (hr - begin_time);
253                                 headlines = lines = text_to_lines(cache[i].summary, 4);
254
255                                 start_tick = cache[i].start_time;
256                                 end_tick = cache[i].end_time;
257                                 if (lines != NULL && lines->s != NULL) { 
258                                         appt_str = ckalloc(cm_strlen(lines->s)+18);
259                                         format_line(start_tick, lines->s, 
260                                                 appt_str, end_tick, 
261                                                 cache[i].show_time, disp_t);
262                                         lines = lines->next;
263                                 }
264                                 else {
265                                         appt_str = ckalloc(15);
266                                         format_line(start_tick, (char*)NULL, 
267                                                 appt_str, end_tick, 
268                                                 cache[i].show_time, disp_t);
269                                 }
270                                 appt_str[cm_strlen(appt_str)] = '\0';
271
272 /* REVISIT: unclear why we're still distinguishing between gr_text[_rgb]
273                                 if (c->xcontext->screen_depth >= 8) 
274                                         gr_text_rgb(c->xcontext, x, y,
275                                            pf2, appt_str, fg, cmap, rect);
276                                 else
277 */
278                                         gr_text(c->xcontext, x, y,
279                                            pf2, appt_str, rect);
280
281                                 free(appt_str); appt_str = NULL;
282                                 curr_line++;
283                                 if (curr_line < maxlines && lines != NULL) {
284                                         appt_str = ckalloc(324);
285                                         cm_strcpy(appt_str, "    ");
286                                         while (lines != NULL) { 
287                                                 if (lines->s != NULL) 
288                                                         cm_strcat(appt_str, lines->s);
289                                                 lines = lines->next;
290                                                 if (lines != NULL && lines->s != NULL)
291                                                         cm_strcat(appt_str, " - ");
292                                         }
293                                         y += pfy;
294
295 /* REVISIT: unclear why we're still distinguishing between gr_text[_rgb]
296
297                                         if (c->xcontext->screen_depth >= 8) 
298                                                 gr_text_rgb(c->xcontext, x, y,
299                                                    pf2, appt_str, fg,
300                                                    cmap, rect);
301                                         else
302 */
303                                                 gr_text(c->xcontext, x, y,
304                                                    pf2, appt_str, rect);
305
306                                         curr_line++;
307                                         free(appt_str); appt_str = NULL;
308                                 }
309                                 destroy_lines(headlines); lines=NULL;
310                         }
311                 }
312         }
313
314         for (i = 0; i < a_total; i++) {
315                 if (i != a_total)
316                         last_hr = hr;
317
318                 start_tick = cache[i].start_time;
319                 end_tick = cache[i].end_time;
320                 hr = hour(start_tick);
321                 if (hr >= begin_time && hr < end_time && (cache[i].show_time && !magic_time(start_tick))) {
322                         if (last_hr != hr) curr_line = 0;
323                         y = c->view->topoffset + 2 + pfy;
324                         if (curr_line < maxlines) {
325                                 y += (curr_line * pfy) + h * (hr - begin_time + 1);
326                                 headlines = lines = text_to_lines(cache[i].summary, 4);
327                                 if (lines != NULL && lines->s != NULL) { 
328                                         appt_str = ckalloc(cm_strlen(lines->s)+18);
329                                         format_line(start_tick, lines->s, 
330                                                 appt_str, end_tick, 
331                                                 cache[i].show_time, disp_t);
332                                         lines = lines->next;
333                                 }
334                                 else {
335                                         appt_str = ckalloc(15);
336                                         format_line(start_tick, (char*)NULL, 
337                                                 appt_str, end_tick, 
338                                                 cache[i].show_time, disp_t);
339                                 }
340                                 appt_str[cm_strlen(appt_str)] = '\0';
341
342 /* REVISIT: unclear why we're still distinguishing between gr_text[_rgb]
343                                 if (c->xcontext->screen_depth >= 8) 
344                                         gr_text_rgb(c->xcontext, x, y,
345                                            pf2, appt_str, fg, cmap, rect);
346                                 else
347 */
348                                         gr_text(c->xcontext, x, y,
349                                            pf2, appt_str, rect);
350
351                                 free(appt_str); appt_str = NULL;
352                                 curr_line++;
353                                 if (curr_line < maxlines && lines != NULL) {
354                                         appt_str = ckalloc(324);
355                                         cm_strcpy(appt_str, "    ");
356                                         while (lines != NULL) { 
357                                                 if (lines->s != NULL) 
358                                                         cm_strcat(appt_str, lines->s);
359                                                 lines = lines->next;
360                                                 if (lines != NULL && lines->s != NULL)
361                                                         cm_strcat(appt_str, " - ");
362                                         }
363                                         y += pfy;
364
365 /* REVISIT: unclear why we're still distinguishing between gr_text[_rgb]
366
367                                         if (c->xcontext->screen_depth >= 8) 
368                                                 gr_text_rgb(c->xcontext, x, y,
369                                                    pf2, appt_str, fg,
370                                                    cmap, rect);
371                                         else 
372 */
373                                                 gr_text(c->xcontext, x, y,
374                                                    pf2, appt_str, rect);
375
376                                         curr_line++;
377                                         free(appt_str); appt_str = NULL;
378                                 }
379                                 destroy_lines(headlines); lines=NULL;
380                         }
381                 }
382         }
383 }
384
385 extern void
386 init_mo(Calendar *c)
387 {
388         Day *day_info = (Day *)c->view->day_info;
389         day_info->month1 = previousmonth(c->view->date);
390         day_info->month2 = c->view->date;
391         day_info->month3 = nextmonth(c->view->date);
392 }
393
394 extern void 
395 init_dayview(Calendar *c)
396 {
397         int  tot_rows, wks_1, wks_2, wks_3;
398         Dimension w, h;
399         Day *day_info = (Day *) c->view->day_info;
400
401         /*
402          * Create month panels if they're not already there
403          */
404         if (day_info->month_panels == (Widget *) NULL) {
405                 day_info->month_panels = (Widget *)ckalloc(3 * sizeof(Widget));
406
407                 create_month_panels(c);
408         }
409
410
411         XtVaGetValues(c->canvas, XmNwidth, &w, XmNheight, &h, NULL);
412         (void)cache_dims(c, w, h);
413
414         day_info->day_selected = -1;
415         day_info->mobox_width = (int)MOBOX_AREA_WIDTH - 
416                         2*c->view->outside_margin;
417         /* col width of day number in month boxes */
418         day_info->col_w = 
419                 (day_info->mobox_width-INSIDE_MARGIN*2)/7;
420         /* width of all of the month boxes */
421         day_info->mobox_width = 7 * day_info->col_w + 
422                         2 * INSIDE_MARGIN;
423
424         wks_1 = numwks(day_info->month1);
425         wks_2 = numwks(day_info->month2);
426         wks_3 = numwks(day_info->month3); 
427         /* total rows in three months */ 
428         tot_rows = wks_1 + wks_2 + wks_3 + 3; 
429
430         /* row height of day number in month boxes */
431         day_info->row_h = (c->view->winh - 3*c->view->topoffset-c->view->outside_margin) 
432                         / tot_rows;
433
434         /* height of 1st month */
435         day_info->mobox_height1 = day_info->row_h * 
436                         (wks_1+1)+1;
437         /* height of 2nd month */
438         day_info->mobox_height2 = day_info->row_h * 
439                         (wks_2+1)+1;
440         /* height of 2rd month */
441         day_info->mobox_height3 = day_info->row_h * 
442                         (wks_3+1)+1;
443
444         day_info->month1_y = c->view->topoffset;
445         day_info->month2_y = 2*c->view->topoffset + 
446                         day_info->mobox_height1; 
447         day_info->month3_y = 3*c->view->topoffset + 
448                         day_info->mobox_height1 +
449                         day_info->mobox_height2;
450         ((Selection*)(c->view->current_selection))->row = 0;
451 }
452
453 extern void
454 monthbox_xytodate(Calendar *c, int x, int y)
455 {
456         char str[5];
457         Day *day_info = (Day *)c->view->day_info;
458         XFontSetExtents fontextents;
459         int pfy;
460         int col_w = day_info->col_w;
461         int row_h = day_info->row_h;
462         int row, col, x_off;
463         int day_selected, tmpx;
464
465         CalFontExtents(c->fonts->labelfont, &fontextents);
466         pfy = fontextents.max_ink_extent.height;
467
468         col = (x-c->view->outside_margin-INSIDE_MARGIN) / col_w;
469         if (col < 0) return;
470         tmpx = c->view->outside_margin + INSIDE_MARGIN + col * col_w;
471
472         if (y < (day_info->month1_y + 
473                         day_info->mobox_height1)) {
474                 row = (y-day_info->month1_y-row_h) / row_h;
475                 day_selected = (7 * (row+1)) - fdom(day_info->month1)
476                                  - (6 - col);
477                 if (day_selected <= 0 || day_selected >
478                          monthlength(day_info->month1)) 
479                                 return;
480                 day_info->day_selected = day_selected;
481                 day_info->day_selected_y = 
482                         day_info->month1_y + (row+1)*row_h; 
483                 c->view->olddate = c->view->date;
484                 c->view->date = next_ndays(first_dom(day_info->month1),
485                          day_info->day_selected);
486         }
487         else if (y < (day_info->month2_y +
488                         day_info->mobox_height2)) {
489                 row = (y-day_info->month2_y-row_h) / row_h;
490                 day_selected = (7 * (row+1)) - fdom(day_info->month2)
491                                  - (6 - col);
492                 if (day_selected <= 0 || day_selected >
493                          monthlength(day_info->month2)) 
494                                 return;
495                 day_info->day_selected = day_selected;
496                 day_info->day_selected_y = 
497                         day_info->month2_y + (row+1)*row_h; 
498                 c->view->olddate = c->view->date;
499                 c->view->date = next_ndays(first_dom(day_info->month2),
500                          day_info->day_selected);
501         }
502         else if (y < (day_info->month3_y +
503                         day_info->mobox_height3)) {
504                 row = (y-day_info->month3_y-row_h) / row_h;
505                 day_selected = (7 * (row+1)) - fdom(day_info->month3) 
506                                 - (6 - col);
507                 if (day_selected <= 0 || day_selected > 
508                                 monthlength(day_info->month3)) 
509                                 return;
510                 day_info->day_selected = day_selected;
511                 day_info->day_selected_y = 
512                         day_info->month3_y + (row+1)*row_h; 
513                 c->view->olddate = c->view->date;
514                 c->view->date = next_ndays(first_dom(day_info->month3),
515                          day_info->day_selected);
516         }
517         day_info->day_selected_x = tmpx;
518         sprintf(str, "%d", day_info->day_selected);
519         x_off = gr_center(col_w, str, c->fonts->labelfont);
520         day_info->day_selected_x2 =
521                 day_info->day_selected_x+x_off;
522         day_info->day_selected_y2 =
523                 day_info->day_selected_y + pfy;
524
525 }
526
527 extern void
528 monthbox_datetoxy(Calendar *c)
529 {
530         char str[5];
531         int week, x_off, dayw, daym, mo;
532         Day *day_info = (Day *) c->view->day_info;
533         XFontSetExtents fontextents;
534         int pfy;
535         int col_w = day_info->col_w;
536         int row_h = day_info->row_h;
537         struct tm tm;
538         _Xltimeparams localtime_buf;
539
540         CalFontExtents(c->fonts->labelfont, &fontextents);
541         pfy = fontextents.max_logical_extent.height;
542
543         tm = *_XLocaltime(&c->view->date, localtime_buf);
544         mo = tm.tm_mon+1;
545         dayw = tm.tm_wday;
546         daym = tm.tm_mday;
547         week = (12+tm.tm_mday-tm.tm_wday)/7;
548         day_info->day_selected_x = c->view->outside_margin + 
549                         INSIDE_MARGIN + col_w*dayw;
550
551         if (mo == month(day_info->month1)) 
552                 day_info->day_selected_y = 
553                         day_info->month1_y + 
554                         row_h*week;
555         else if (mo == month(day_info->month2))  
556                 day_info->day_selected_y = 
557                         day_info->month2_y + 
558                         row_h*week;
559         else if (mo == month(day_info->month3)) 
560                 day_info->day_selected_y = 
561                         day_info->month3_y + 
562                         row_h*week;
563         sprintf(str, "%d", daym);
564         x_off = gr_center(col_w, str, c->fonts->labelfont);
565         day_info->day_selected_x2 = 
566                         day_info->day_selected_x+x_off;
567         day_info->day_selected_y2 = 
568                         day_info->day_selected_y + pfy;
569         day_info->day_selected = daym;
570 }
571
572 static Boolean
573 in_moboxes(Calendar *c, int x, int y)
574 {
575         int margin = c->view->outside_margin;
576         int topoff = c->view->topoffset;
577         Boolean in_mobox = False;
578         Day *day_info = (Day *)c->view->day_info;
579         int row_h = day_info->row_h;
580
581         if (x < (MOBOX_AREA_WIDTH-margin-2*INSIDE_MARGIN) && 
582                 x > margin && y > topoff && 
583                 ( (y < (day_info->month3_y+
584                         day_info->mobox_height3) &&
585                         y > (day_info->month3_y+row_h)) || 
586                   (y < (day_info->month2_y+
587                         day_info->mobox_height2) &&
588                         y > (day_info->month2_y+row_h)) ||
589                   (y < (day_info->month1_y+
590                         day_info->mobox_height1) &&
591                         y > day_info->month1_y+row_h) ) )
592                 in_mobox = True;
593
594         return in_mobox;
595 }
596
597 extern void
598 paint_dayview(Calendar *c, Boolean repaint, XRectangle *rect, Boolean update_months)
599 {
600         Props           *p = (Props*)c->properties;
601         int             num_hrs;
602         int             beg = get_int_prop(p, CP_DAYBEGIN);
603         int             end = get_int_prop(p, CP_DAYEND);
604         time_t          start, stop;
605         CSA_attribute           *range_attrs;
606         CSA_entry_handle        *list;
607         CSA_enum        *ops;
608         int             i, j;
609         CSA_uint32      a_total;
610         int             panel0_year, panel0_month;
611         int             panel1_year, panel1_month;
612         int             panel2_year, panel2_month;
613         int             year_num, month_num;
614         Boolean         day_not_on_panel = False;
615         Day             *d = (Day *)c->view->day_info;
616         int             top_panel = 0;
617         int             bottom_panel = 2;
618
619         num_hrs = end - beg + 1;
620         if (c->paint_cache == NULL) {
621                 start = (time_t) lower_bound(0, c->view->date);
622                 stop = (time_t) next_nhours(start, end+1) - 1;
623                 setup_range(&range_attrs, &ops, &j, start, stop, CSA_TYPE_EVENT, 0,
624                         B_FALSE, c->general->version);
625                 csa_list_entries(c->cal_handle, j, range_attrs, ops, &a_total, &list, NULL);
626         
627                 free_range(&range_attrs, &ops, j);
628                 allocate_paint_cache(list, a_total, &c->paint_cache);
629                 c->paint_cache_size = a_total;
630                 csa_free(list);
631         }
632
633         year_num = year(c->view->date);
634         month_num = month(c->view->date);
635         XtVaGetValues(d->month_panels[1],
636                 XmNyear, &panel1_year,
637                 XmNmonth, &panel1_month,
638                 NULL);
639
640         if ((panel1_year == year(get_bot())) && (panel1_month == 1))
641                 top_panel = 1;
642         else if ((panel1_year == year(get_eot())) && (panel1_month == 12))
643                 bottom_panel = 1;
644
645         XtVaGetValues(d->month_panels[top_panel],
646                 XmNyear, &panel0_year,
647                 XmNmonth, &panel0_month,
648                 NULL);
649
650         if ((year_num < panel0_year) || 
651             ((year_num == panel0_year) && (month_num < panel0_month)))
652                 day_not_on_panel = True;
653         
654         XtVaGetValues(d->month_panels[bottom_panel],
655                 XmNyear, &panel2_year,
656                 XmNmonth, &panel2_month,
657                 NULL);
658
659         if ((year_num > panel2_year) || 
660             ((year_num == panel2_year) && (month_num > panel2_month)))
661                 day_not_on_panel = True;
662
663         /* set up month panels */
664         if (update_months || day_not_on_panel)
665                 update_quarter(c);
666
667         /* no need to do this on a damage event */
668
669         if (!rect)
670                 display_monthpanels(c);
671
672         /* repaint appointment area */
673         if (repaint) {
674                 int     line_length;
675
676                 gr_clear_area(c->xcontext, 0, 0, 
677                         c->view->winw, c->view->winh);
678                 line_length = c->view->topoffset + 
679                               ((end - beg + 1) * c->view->boxh);
680                 /* draw line separating mo. boxes and appts. */
681                 gr_draw_line(c->xcontext, (int)MOBOX_AREA_WIDTH+1,
682                          0, (int)MOBOX_AREA_WIDTH+1,
683                          line_length, gr_solid, rect);
684                 gr_draw_line(c->xcontext, (int)MOBOX_AREA_WIDTH+2, 
685                          0, (int)MOBOX_AREA_WIDTH+2,
686                          line_length, gr_solid, rect);
687                 gr_draw_line(c->xcontext, (int)MOBOX_AREA_WIDTH+2, 
688                          c->view->topoffset-1, c->view->winw,
689                          c->view->topoffset-1,  gr_solid, rect);
690                 gr_draw_line(c->xcontext, (int)MOBOX_AREA_WIDTH+2, 
691                          c->view->topoffset, c->view->winw,
692                          c->view->topoffset, gr_solid, rect);
693                 paint_dayview_appts(c, c->paint_cache, c->paint_cache_size, rect);
694         }
695         /* just repaint schedule area */
696         else {
697                 gr_clear_area(c->xcontext, 
698                                 (int)MOBOX_AREA_WIDTH+4, 0, 
699                                 c->view->winw - (int)MOBOX_AREA_WIDTH+4,
700                                 c->view->winh);
701                 gr_draw_line(c->xcontext, (int)MOBOX_AREA_WIDTH+2, 
702                          c->view->topoffset, c->view->winw,
703                          c->view->topoffset,  gr_solid, rect);
704                 gr_draw_line(c->xcontext, (int)MOBOX_AREA_WIDTH+2, 
705                          c->view->topoffset+1, c->view->winw,
706                          c->view->topoffset+1, gr_solid, rect);
707                 paint_dayview_appts(c, c->paint_cache, c->paint_cache_size, rect);
708         }
709
710         paint_day_header(c, c->view->date, rect);
711 }
712
713 extern void
714 paint_day(Calendar *c)
715 {
716         Day *day_info = (Day *) c->view->day_info;
717
718         c->view->glance = dayGlance;
719         XmToggleButtonGadgetSetState(c->day_scope, True, False);
720         gr_clear_area(c->xcontext, 0, 0, c->view->winw, c->view->winh);
721         if (day_info->month_panels == (Widget *) NULL)
722                 (void)init_dayview(c);
723         paint_dayview(c, True, NULL, True); 
724         calendar_select(c, hourSelect, (caddr_t)NULL);
725 }
726         
727 /*
728  * handler for button to switch to day view.
729  */
730 extern void
731 day_button (Widget widget, XtPointer data, XtPointer cbs)
732 {
733         Calendar *c = calendar;
734
735         if (c->view->glance == dayGlance)
736                 return;
737
738         XtUnmapWidget(c->canvas);
739         invalidate_cache(c);
740
741         switch (c->view->glance) {
742                 case weekGlance:
743                         c->view->glance = dayGlance;
744                         cleanup_after_weekview(c);
745                         break;
746                 case yearGlance:
747                         c->view->glance = dayGlance;
748                         cleanup_after_yearview(c);
749                         break;
750                 case monthGlance:
751                         c->view->glance = dayGlance;
752                         cleanup_after_monthview(c);
753                         break;
754                 default:
755                         break;  
756         }
757
758         init_mo(c);
759         (void)init_dayview(c);
760
761         XtMapWidget(c->canvas);
762 }
763
764 extern void
765 print_day_range(Calendar *c, Tick start_tick, Tick end_tick)
766 {
767         int             n;
768         register Tick   first_date = start_tick;
769         Boolean         done = False, first = True;
770         int             num_page = 1;
771         Props           *pr = (Props*)c->properties;
772         void *xp = (void *)NULL;
773
774         n = (end_tick - start_tick)/daysec + 1;
775
776         if (n <= 0) n = 1;
777
778         if ((xp = x_open_file(c)) == (void *)NULL)
779           return;
780
781         for (; n > 0; n--) {
782           while (!done) {
783             done = _print_day(c, num_page, xp,
784                               first_date, pr, first);
785             num_page++;
786             first = False;
787           }
788           done = False;
789           num_page = 1;
790         }
791
792         x_print_file(xp, c);
793 }
794
795 static int
796 count_day_pages(Calendar *c, int lines_per_page, Tick tick)
797 {
798         int     n, i, j, timeslots, num_appts, pages, max = 0; 
799         Props *p = (Props *)c->properties;
800         int       daybegin = get_int_prop(p, CP_DAYBEGIN);
801         int       dayend   = get_int_prop(p, CP_DAYEND);
802         char    *location;
803         time_t  start, end;
804         CSA_return_code stat;
805         CSA_entry_handle *list;
806         CSA_attribute *range_attrs;
807         CSA_enum *ops;
808         CSA_uint32 a_total;
809
810         for (i=daybegin; i < dayend; i++) {
811                 start = (time_t) lower_bound(i, tick);
812                 end = (time_t) next_nhours(start+1, 1) - 1;
813                 setup_range(&range_attrs, &ops, &j, start, end,
814                             CSA_TYPE_EVENT, 0, B_FALSE, c->general->version);
815                 csa_list_entries(c->cal_handle, j, range_attrs, ops, &a_total, &list, NULL);
816                 free_range(&range_attrs, &ops, j);
817
818                 num_appts = count_multi_appts(list, a_total, c);
819
820                 if (num_appts > max)
821                         max = num_appts;
822
823                 csa_free(list);
824         }
825  
826         pages = max / lines_per_page;
827         if ((max % lines_per_page) > 0)
828                 pages++;
829  
830         return(pages);
831 }
832
833 static Boolean
834 _print_day(Calendar *c,
835     int num_page,
836     void *xp,
837     Tick first_date,
838     Props *p,
839     Boolean first)
840 {
841     char buf[100];
842     int n, i, j, timeslots, num_appts, pages;
843     int max = 0;
844     int daybegin = get_int_prop(p, CP_DAYBEGIN);
845     int dayend   = get_int_prop(p, CP_DAYEND);
846     OrderingType ord_t = get_int_prop(p, CP_DATEORDERING);
847     Boolean more, done = False, all_done = True;
848     char *location;
849     CSA_return_code stat;
850     CSA_entry_handle *list;
851     CSA_attribute *range_attrs;
852     CSA_enum *ops;
853     CSA_uint32 a_total;
854     time_t start, stop;
855     int lines_per_page;
856     static Tick tick = 0;
857     static int total_pages = 0;
858
859     /*
860      * Need to find the max number of timeslots which will be shown
861      * in one column, for later calculation of box height.
862      */  
863     if ((!morning(daybegin)) || dayend <= 12) 
864         timeslots = dayend - daybegin;
865     else
866         timeslots = ((12-daybegin) > (dayend-12)) ?
867                      (12-daybegin) : (dayend-12);
868
869     x_init_printer(xp, PORTRAIT);
870     x_init_day(xp, timeslots);
871     lines_per_page = x_get_day_lines_per_page(xp);
872
873     if (first)
874       tick = first_date;
875
876     if (num_page > 1)
877       tick = prevday(tick);
878     else
879       total_pages = (lines_per_page > 0) ?
880         count_day_pages(c, lines_per_page, tick) : 1;
881
882     format_date(tick, ord_t, buf, 1, 0, 0);
883
884     x_print_header(xp, buf, num_page, total_pages);
885     x_day_header(xp);
886
887     for (i=daybegin; i < dayend; i++) {
888       start = (time_t) lower_bound(i, tick);
889       stop = (time_t) next_nhours(start+1, 1) - 1;
890       setup_range(&range_attrs, &ops, &j, start, stop,
891                   CSA_TYPE_EVENT, 0, B_FALSE, c->general->version);
892
893       csa_list_entries(c->cal_handle, j, range_attrs,
894                        ops, &a_total, &list, NULL);
895       free_range(&range_attrs, &ops, j);
896  
897       num_appts = count_multi_appts(list, a_total, c);
898
899       if ((lines_per_page > 0) && (num_appts > (lines_per_page * num_page)))
900         more = True;
901       else
902         more = False;
903
904       x_day_timeslots (xp, i, more);
905
906       if (lines_per_page > 0)
907         done = x_print_multi_appts (xp, list, a_total,
908                                     num_page, dayGlance);
909       else done = True;
910
911       if (!done)
912         all_done = False;
913       csa_free(list);
914     }
915  
916     x_finish_printer(xp);
917     tick = nextday(tick); 
918
919     return(all_done);
920 }
921
922 static int
923 day_xytoclock(Calendar *c, int x, int y, Tick t)
924 {
925         int daybegin, hr, val;
926         char buf[10];
927         struct tm tm;
928         Props *p;
929         _Xltimeparams localtime_buf;
930
931         p       = (Props *)c->properties;
932         daybegin = get_int_prop(p, CP_DAYBEGIN);
933         tm      = *_XLocaltime(&t, localtime_buf);
934
935         hr = (x == 1) ? (12 + y) : (y + daybegin - 1);
936
937         /* 
938          * If y == 0 then the user is clicking on the no-time area.  There
939          * is no hour associated with no-time events.
940          */
941         if (y == 0) hr = 0;
942
943         (void)sprintf(buf, "%d/%d/%d", tm.tm_mon+1, tm.tm_mday, tm.tm_year+1900);
944         val     =cm_getdate(buf, NULL);
945         val     = val+(hr*(int)hrsec);
946         adjust_dst(t, val);
947         return(val);
948 }
949
950 extern void
951 day_event(XEvent *event)
952 {
953         static int lastcol, lastrow;
954         static XEvent lastevent;
955         pr_pos xy;
956         int x, y, i, j;
957         int boxw, boxh, margin, id;
958         Calendar *c = calendar;
959         Tick date = c->view->date;
960         Boolean in_mbox = False; /* in month boxes ? */
961         Editor *e = (Editor*)c->editor;
962         ToDo *t = (ToDo*)c->todo;
963         GEditor *ge = (GEditor*)c->geditor;
964         Day *day_info = (Day *)c->view->day_info;
965  
966         boxw    = c->view->boxw;
967         boxh    = c->view->boxh;
968         margin  = c->view->outside_margin;
969         x       = event->xbutton.x;
970         y       = event->xbutton.y;
971  
972         /* boundary conditions */
973         if ((!(in_mbox = in_moboxes(c, x, y)) && x < MOBOX_AREA_WIDTH+2)
974 ||
975                 (x > MOBOX_AREA_WIDTH+2 && y < c->view->topoffset)) {
976                 lastcol=0; lastrow=0;
977                 return;
978         }
979         if (in_mbox) {
980                 xy.x = (x - margin)/ day_info->col_w;
981                 xy.y = (x - c->view->topoffset)/ day_info->row_h;
982         }
983         else {
984                 xy.x    = boxw;
985                 xy.y    = (y - c->view->topoffset)/boxh;
986         }
987         switch(event->type) {
988         case MotionNotify:
989                 if (!in_mbox) {
990                         if (xy.x !=lastcol || xy.y !=lastrow) {
991                                 calendar_deselect(c);
992                                 j = day_xytoclock(c, xy.x, xy.y, date);
993                                 if (j >= 0) {
994                                         c->view->olddate = c->view->date;                                        c->view->date = j;
995                                         calendar_select(c, hourSelect, (caddr_t)&xy);
996                                 }
997                                 lastcol=xy.x;
998                                 lastrow=xy.y;
999                         }
1000                 }
1001                 break;
1002         case ButtonPress:
1003                 if (ds_is_double_click(&lastevent, event)) {
1004                         _DtTurnOnHourGlass(c->frame);
1005                         j = day_xytoclock(c, xy.x, xy.y, date);
1006                         if (lastcol == xy.x && lastrow == xy.y)
1007                                 show_editor(c, j, next_nhours(j, 1), xy.y == 0 ? True : False);
1008                         if (in_mbox) {
1009                                 monthbox_deselect(c);
1010                                 monthbox_xytodate(c, x, y);
1011                                 monthbox_select(c);
1012                         } else
1013                                 show_editor(c, j, next_nhours(j, 1), xy.y == 0 ? True : False);
1014                         _DtTurnOffHourGlass(c->frame);
1015                 } else {
1016                         if (in_mbox) {
1017                                 monthbox_deselect(c);
1018                                 monthbox_xytodate(c, x, y);
1019                                 paint_dayview(c, False, NULL, True);
1020                                 calendar_select(c, hourSelect, (caddr_t)NULL);
1021                                 monthbox_select(c);
1022                                 j = day_xytoclock(c, xy.x, xy.y, date);
1023                                 if (editor_showing(e)) {
1024                                         set_editor_defaults(e, j,
1025                                                             next_nhours(j, 1), False);
1026                                         add_all_appt(e);
1027                                 }
1028                                 if (todo_showing(t)) {
1029                                         set_todo_defaults(t);
1030                                         add_all_todo(t);
1031                                 }
1032                                 if (geditor_showing(ge)) {
1033                                         set_geditor_defaults(ge, j,
1034                                                              next_nhours(j, 1));
1035                                         add_all_gappt(ge);
1036                                 }
1037                         } else {
1038                                 calendar_deselect(c);
1039                                 j = day_xytoclock(c, xy.x, xy.y, date);
1040                                 if (j >= 0) {
1041                                         c->view->olddate = c->view->date;
1042                                         c->view->date = j;
1043                                         calendar_select(c, hourSelect,
1044                                                         (caddr_t)&xy);
1045                                         if (editor_showing(e)) {
1046                                                 set_editor_defaults(e, j,
1047                                                         next_nhours(j, 1), xy.y == 0 ? True : False);
1048                                                 add_all_appt(e);
1049                                         }
1050                                         if (todo_showing(t)) {
1051                                                 set_todo_defaults(t);
1052                                                 add_all_todo(t);
1053                                         }
1054                                         if (geditor_showing(ge)) {
1055                                                 set_geditor_defaults(ge, j,
1056                                                         next_nhours(j, 1));
1057                                                 add_all_gappt(ge);
1058                                         }
1059                                 }
1060                         }
1061                 }
1062                 lastcol=xy.x;
1063                 lastrow=xy.y;
1064                 break;
1065         default:
1066                 break;
1067         };            /* switch */
1068         lastevent = *event;
1069 }
1070
1071 static void
1072 display_monthpanels(Calendar *c)
1073 {
1074         Day     *d = (Day *)c->view->day_info;
1075         char    buf[BUFSIZ];
1076         int     lastyear = year(get_eot());
1077         int     firstyear = year(get_bot());
1078         int     panel_year;
1079         int     panel_month;
1080
1081         XtManageChild(d->panel_form);
1082
1083         XtVaGetValues(d->month_panels[1],
1084                 XmNyear, &panel_year,
1085                 XmNmonth, &panel_month,
1086                 NULL);
1087
1088         if ((panel_year == firstyear) && (panel_month == 1)) {
1089                 XtUnmapWidget(d->month_panels[0]);
1090                 XtMapWidget(d->month_panels[2]);
1091                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 623, "Calendar does not display dates prior to January 1, 1970"));
1092                 set_message(c->message_text, buf);
1093         }
1094         else if ((panel_year == lastyear) && (panel_month == 12)) {
1095                 XtMapWidget(d->month_panels[0]);
1096                 XtUnmapWidget(d->month_panels[2]);
1097                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 624, "Calendar does not display dates after December 31, 2037"));
1098                 set_message(c->message_text, buf);
1099         }
1100         else {
1101                 XtMapWidget(d->month_panels[0]);
1102                 XtMapWidget(d->month_panels[2]);
1103                 set_message(c->message_text, "");
1104         }
1105
1106         /* switch canvas to attach using its XmNleftPosition value */
1107 /* THIS IS THE RIGHT THIS TO DO, BUT ONLY AFTER REMOVING THE
1108    CODE THAT DRAWS THE OLD MO_BOXES.  FOR NOW, WE JUST MANAGE THE
1109    MONTHPANELS ON TOP OF THAT PART OF THE CANVAS - dac
1110         XtVaSetValues(c->canvas,
1111                 XmNleftAttachment, XmATTACH_POSITION,
1112                 XmNleftPosition, 40,
1113                 NULL);
1114 */
1115
1116 }
1117
1118 extern void
1119 cleanup_after_dayview(Calendar *c)
1120 {
1121         Day *d = (Day *)c->view->day_info;
1122
1123         invalidate_cache(c);
1124
1125         XtUnmanageChild(d->panel_form);
1126
1127         XmToggleButtonGadgetSetState(c->day_scope, False, False);
1128
1129         /* make canvas attach to form, and ignore its XmNleftPosition */
1130 /* DITTO ABOVE: THIS ISN'T NEEDED TILL WE ACTUALLY DO RESIZE THE
1131    CANVAS TO ADJOIN THE MONTHPANELS WHILE DAY VIEW IS UP
1132         XtVaSetValues(c->canvas, XmNleftAttachment, XmATTACH_FORM, NULL);
1133 */
1134
1135         gr_clear_area(calendar->xcontext, 0, 0, calendar->view->winw,
1136                        calendar->view->winh);
1137
1138         set_message(c->message_text, "");
1139 }
1140
1141 static void
1142 create_month_panels(Calendar *c)
1143 {
1144         Day *d = (Day *)c->view->day_info;
1145         Arg al[20];
1146         int ac;
1147
1148         ac=0;
1149         XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
1150         XtSetArg(al[ac], XmNtopWidget, c->canvas); ac++;
1151         XtSetArg(al[ac], XmNrightAttachment, XmATTACH_POSITION); ac++;
1152         XtSetArg(al[ac], XmNrightPosition, 40); ac++;
1153         XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
1154         XtSetArg(al[ac], XmNleftOffset, 2); ac++;
1155         XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_POSITION); ac++;
1156         XtSetArg(al[ac], XmNbottomPosition, 95); ac++;
1157         XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
1158         d->panel_form = XmCreateForm(c->form, "quarter", al, ac);
1159
1160
1161         ac=0;
1162         XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
1163         XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
1164         XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_POSITION); ac++;
1165         XtSetArg(al[ac], XmNbottomPosition, 33); ac++;
1166         XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
1167         XtSetArg(al[ac], XmNmonth, month(previousmonth(c->view->date))); ac++;
1168         XtSetArg(al[ac], XmNyear, year(previousmonth(c->view->date))); ac++;
1169         d->month_panels[0] = XmCreateMonthPanel(d->panel_form, "lastMonth", al, ac);
1170         XtAddCallback(d->month_panels[0], XmNactivateCallback,
1171                         day_btn_cb, (XtPointer) c);
1172         XtAddCallback(d->month_panels[0], XmNhelpCallback, 
1173                         (XtCallbackProc)help_view_cb, NULL);
1174
1175         ac=0;
1176         XtSetArg(al[ac], XmNtopAttachment, XmATTACH_POSITION); ac++;
1177         XtSetArg(al[ac], XmNtopPosition, 33); ac++;
1178         XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
1179         XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_POSITION); ac++;
1180         XtSetArg(al[ac], XmNbottomPosition, 66); ac++;
1181         XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
1182         XtSetArg(al[ac], XmNmonth, month(c->view->date)); ac++;
1183         XtSetArg(al[ac], XmNyear, year(c->view->date)); ac++;
1184         d->month_panels[1] = XmCreateMonthPanel(d->panel_form, "thisMonth", al, ac);
1185         XtAddCallback(d->month_panels[1], XmNactivateCallback,
1186                         day_btn_cb, (XtPointer) c);
1187         XtAddCallback(d->month_panels[1], XmNhelpCallback, 
1188                         (XtCallbackProc)help_view_cb, NULL);
1189
1190         ac=0;
1191         XtSetArg(al[ac], XmNtopAttachment, XmATTACH_POSITION); ac++;
1192         XtSetArg(al[ac], XmNtopPosition, 66); ac++;
1193         XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
1194         XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
1195         XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
1196         XtSetArg(al[ac], XmNmonth, month(nextmonth(c->view->date))); ac++;
1197         XtSetArg(al[ac], XmNyear, year(nextmonth(c->view->date))); ac++;
1198         d->month_panels[2] = XmCreateMonthPanel(d->panel_form, "nextMonth", al, ac);
1199         XtAddCallback(d->month_panels[2], XmNactivateCallback,
1200                         day_btn_cb, (XtPointer) c);
1201         XtAddCallback(d->month_panels[2], XmNhelpCallback, 
1202                         (XtCallbackProc)help_view_cb, NULL);
1203
1204         ManageChildren(d->panel_form);
1205
1206 }
1207
1208 /*
1209  * This redisplays the 3 month panels 2 show the correct 3-month
1210  * window, centred around the month containing the "current" date.
1211  */
1212 static void
1213 update_quarter(Calendar *c)
1214 {
1215         Day *d = (Day *)c->view->day_info;
1216         int year_num, month_num;
1217
1218         /* previous month */
1219         year_num = year(previousmonth(c->view->date));
1220         month_num = month(previousmonth(c->view->date));
1221         XtVaSetValues(d->month_panels[0],
1222                 XmNyear, year_num,
1223                 XmNmonth, month_num,
1224                 NULL);
1225         
1226         /* current month */
1227         year_num = year(c->view->date);
1228         month_num = month(c->view->date);
1229         XtVaSetValues(d->month_panels[1],
1230                 XmNyear, year_num,
1231                 XmNmonth, month_num,
1232                 NULL);
1233         
1234         /* next month */
1235         year_num = year(nextmonth(c->view->date));
1236         month_num = month(nextmonth(c->view->date));
1237         XtVaSetValues(d->month_panels[2],
1238                 XmNyear, year_num,
1239                 XmNmonth, month_num,
1240                 NULL);
1241         
1242 }
1243
1244 static void
1245 day_btn_cb(Widget w, XtPointer client, XtPointer call)
1246 {
1247         XmMonthPanelCallbackStruct *cbs = (XmMonthPanelCallbackStruct *) call;
1248         Calendar *c = (Calendar *)client;
1249         int monthno, year;
1250         int date = c->view->date;
1251  
1252         invalidate_cache(c);
1253
1254         XtVaGetValues(w, XmNmonth, &monthno, XmNyear, &year, NULL);
1255  
1256         if (cbs->type == MONTH_SELECTION) {
1257
1258                 XtUnmapWidget(c->canvas);
1259
1260                 /*
1261                  * Date update:
1262                  *      if month chosen is not current month
1263                  *      set date to 1st of new month, otherwise
1264                  *      don't change date.
1265                  */
1266                 if (month(c->view->date) != monthno) {
1267                         calendar_deselect (c);
1268                         c->view->olddate = c->view->date;
1269                         c->view->date = monthdayyear(monthno, 1, year);
1270                         c->view->nwks = numwks(c->view->date);
1271                         calendar_select (c, monthSelect, NULL);
1272                 }
1273  
1274                 /* switch to month view */
1275                 c->view->glance = monthGlance;
1276                 cleanup_after_dayview(c);
1277                 prepare_to_paint_monthview(c, NULL);
1278
1279                 XtMapWidget(c->canvas);
1280         }
1281         else {  /* type == DAY_SELECTION */
1282                 c->view->olddate = c->view->date;
1283                 c->view->date = monthdayyear(monthno, cbs->day, year);
1284                 gr_clear_area(c->xcontext, 0, 0, c->view->winw, c->view->winh);
1285                 paint_dayview(c, True, NULL, False); 
1286                 calendar_select(c, hourSelect, (caddr_t)NULL);
1287         }
1288 }