dtcm/reminders.c: NULL is not 0
[oweals/cde.git] / cde / programs / dtcm / dtcm / calendarA.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 **  calendarA.c
26 **
27 **  $TOG: calendarA.c /main/22 1999/09/20 10:29:08 mgreess $
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[] = "@(#)calendarA.c 1.196 95/04/12 Copyr 1991 Sun Microsystems, Inc.";
52 #endif
53
54 #include <EUSCompat.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <sys/stat.h>
58 #include <sys/param.h> /* MAXPATHLEN defined here */
59 #ifdef SVR4
60 #include <sys/utsname.h> /* SYS_NMLN */
61 #endif /* SVR4 specific includes */
62 #include <locale.h>
63 #include <nl_types.h>
64 #include <dirent.h>
65 #include <ctype.h>
66 #include <string.h>
67 #include <sys/time.h>
68 #include <sys/signal.h>
69 #include <signal.h>
70 #include <rpc/rpc.h>
71 #include <sys/resource.h>
72 #include <sys/wait.h>
73 #include <netinet/in.h>
74 #include <X11/Xlib.h>
75 #include <Xm/Xm.h>
76 #include <Xm/ArrowBG.h>
77 #include <Xm/DrawingA.h>
78 #include <Xm/Form.h>
79 #include <Xm/Frame.h>
80 #include <Xm/LabelG.h>
81 #include <Xm/List.h>
82 #include <Xm/PushB.h>
83 #include <Xm/PushBG.h>
84 #include <Xm/ToggleBG.h>
85 #include <Xm/RowColumn.h>
86 #include <Xm/SeparatoG.h>
87 #include <Xm/Text.h>
88 #include <Xm/CascadeBG.h>
89 #include <Xm/CascadeB.h>
90 #include <Dt/HourGlass.h>
91 #include <Dt/Dt.h>
92 #include <Xm/RepType.h>
93 #include <Xm/Protocols.h>
94 #include <Dt/EnvControlP.h>
95 #include <Tt/tt_c.h>
96 #include <LocaleXlate.h>        /* under DtHelp */
97 #include "calendar.h"
98 #include "revision.h"
99 #include "help.h"
100 #include "datefield.h"
101 #include "props.h"
102 #include "props_pu.h"
103 #include "misc.h"
104 #include "deskset.h"
105 #include "select.h"
106 #include "session.h"
107 #include "editor.h"
108 #include "group_editor.h"
109 #include "todo.h"
110 #include "format.h"
111 #include "getdate.h"
112 #include "print.h"
113 #include "util.h"
114 #include "browser.h"
115 #include "blist.h"
116 #include "alarm.h"
117 #include "dayglance.h"
118 #include "yearglance.h"
119 #include "monthglance.h"
120 #include "weekglance.h"
121 #include "find.h"
122 #include "timezone.h"
123 #include "goto.h"
124 #include "tempbr.h"
125 #include "dnd.h"
126 #include "fallback.h"
127 #include "rfp.h"
128 #ifdef FNS
129 #include "dtfns.h"
130 #include "cmfns.h"
131 #include "cmtt.h"
132 #endif
133
134 #if defined(linux)
135 #undef SVR4
136 #endif
137 #include <X11/Xos.h>
138 #include <errno.h>
139 #ifdef X_NOT_STDC_ENV
140 extern int errno;
141 #endif
142
143 #define ITIMER_NULL ((struct itimerval *) 0)
144 #define VIEWMARGIN              15
145 #define NUM_MITEMS_PERCOL       27
146 #define ICON_FG                 18
147 #define ICON_BG                 14
148
149 #if !defined(NL_CAT_LOCALE)
150 #define NL_CAT_LOCALE       0
151 #endif
152
153
154 extern time_t timelocal();      /* LINT */
155 extern char * getlogin();       /* LINT */
156 extern void(*sigset())();
157 extern int cmtt_init(char *, Calendar *, XtAppContext, Widget);
158 extern void show_about(Widget, XtPointer, XtPointer);
159
160
161 static struct itimerval timer;
162 extern u_long gettransient();
163 extern void xtcallback(XtPointer, int *, XtInputId *);
164 extern int getfdset(fd_set);
165 extern Tick prevnday_exacttime();
166 extern void quit_handler(Widget, XtPointer, XtPointer);
167 static void sig_int_handler(int sig);
168 extern void find_cb(Widget, XtPointer, XtPointer);
169 extern void goto_cb(Widget, XtPointer, XtPointer);
170 #ifdef __osf__
171 extern void sigchld_handler(int);
172 #endif /* __osf__ */
173 extern void timezone_cb(Widget, XtPointer, XtPointer);
174 extern void print_cb(Widget, XtPointer, XtPointer);
175
176 extern int cm_register_calendar(const char *username, const char *location);
177 extern void paint_icon(Calendar *c);
178 extern void load_app_font(Calendar *, Font_Weight, Cal_Font *, Cal_Font *);
179 extern void repaint_damaged_month(Calendar *c, XRectangle *rect);
180
181 /* routine to get common locale/charset name */
182 extern void _DtI18NXlateOpToStdLocale(
183                 char       *operation,
184                 char       *opLocale,
185                 char       **ret_stdLocale,
186                 char       **ret_stdLang,
187                 char       **ret_stdSet);
188
189 static void resize_proc(Widget, XtPointer, XtPointer);
190 static void update_handler (CSA_session_handle, CSA_flags, CSA_buffer, CSA_buffer, CSA_extension *);
191 static Boolean init_fonts(Calendar *);
192 static XFontSet get_bold_font(Widget, String);
193 static void logon_retry(XtPointer data, XtIntervalId *dummy);
194 static int newXErrorHandler(Display *, XErrorEvent *);
195
196 static int (*oldXErrorHandler)(Display *, XErrorEvent *);
197
198 void init_strings();
199
200 int             child;
201 int             yyylineno;
202 int             debug=0;
203 int             expert=0;
204
205 int             cmicon=3;
206 Calendar        *calendar;
207
208 int             gargc;          /* saved for tooltalk initialization */
209 char            **gargv;
210
211 Display *dpy;
212 XtAppContext    app;
213
214 extern void
215 destroy_paint_cache(Paint_cache *cache, int num_entries) {
216
217         int i;
218
219         if (cache == NULL)
220                 return;
221
222         for (i = 0; i < num_entries; i++) {
223                 if (cache[i].summary)
224                         free(cache[i].summary);
225         }
226
227         free(cache);
228 }
229
230 extern void
231 invalidate_cache(Calendar *c) {
232
233         Browselist      *bl = (Browselist *)c->browselist;
234         BlistData       *bd;
235         int             i;
236
237         if (c->paint_cache) {
238                 destroy_paint_cache(c->paint_cache, c->paint_cache_size);
239                 c->paint_cache = NULL;
240                 c->paint_cache_size = 0;
241         }
242
243         if (bl) {
244                 i = 1;
245                 while (bd = (BlistData *)CmDataListGetData(bl->blist_data, i)) {
246                         if (bd->cal_handle == c->cal_handle) {
247                                 destroy_paint_cache(bd->cache, bd->cache_size);
248                                 bd->cache = NULL;
249                                 bd->cache_size = 0;
250                                 break;
251                         }
252                         i++;
253                 }
254
255         }
256 }
257
258 CSA_return_code
259 allocate_paint_cache(CSA_entry_handle *list, int num_entries, Paint_cache **return_cache) {
260         Dtcm_appointment        *appt;
261         Calendar                *c=calendar;
262         CSA_return_code         stat = CSA_SUCCESS;
263         Paint_cache     *cache = (Paint_cache *) calloc(sizeof(Paint_cache), num_entries);
264         int                     i;
265
266
267         appt = allocate_appt_struct(appt_read,
268                                     c->general->version,
269                                     CSA_ENTRY_ATTR_START_DATE_I,
270                                     CSA_ENTRY_ATTR_END_DATE_I,
271                                     CSA_ENTRY_ATTR_SUMMARY_I,
272                                     CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,
273                                     NULL);
274
275         /* loop thru the list of appointments twice, first displaying 
276            the no time appointments, and then the appointments with times 
277            associated. */
278
279         for (i = 0; i < num_entries; i++) {
280                 
281                 stat = query_appt_struct(c->cal_handle, list[i], appt);
282                 if (stat != CSA_SUCCESS) {
283                         destroy_paint_cache(cache, i);
284                         *return_cache = NULL;
285                         free_appt_struct(&appt);
286                         return(stat);
287                 }
288                 _csa_iso8601_to_tick(appt->time->value->item.date_time_value,
289                         &cache[i].start_time);
290                 if (appt->end_time)
291                         _csa_iso8601_to_tick(appt->end_time->value->item.\
292                                 date_time_value, &cache[i].end_time);
293                 else
294                         cache[i].end_time = 0;
295
296                 cache[i].summary = strdup(appt->what->value->item.string_value);
297                 cache[i].show_time = showtime_set(appt);
298         }
299
300         free_appt_struct(&appt);
301         *return_cache = cache;
302         return(stat);
303 }
304
305 extern void
306 cache_dims(Calendar *c, Dimension w, Dimension h) 
307 {
308         Glance glance;
309         Props *p = (Props*)c->properties;
310         int begin = get_int_prop(p, CP_DAYBEGIN);
311         int end = get_int_prop(p, CP_DAYEND);
312         int margin;
313         XFontSetExtents regfontextents, boldfontextents;
314         
315         CalFontExtents(c->fonts->viewfont, &regfontextents);
316         CalFontExtents(c->fonts->boldfont, &boldfontextents);
317
318         c->view->winw = w;
319         c->view->winh = h;
320
321         margin = c->view->outside_margin;
322         glance = c->view->glance;
323         switch(glance) {
324                 case weekGlance:
325                         c->view->boxw = (int)(w-2*margin)/5;
326                         break;
327                 case monthGlance:
328                         c->view->boxw = (int)(w-2*margin)/7;
329                         c->view->topoffset =  boldfontextents.max_logical_extent.height + 30;
330                         c->view->boxh = (int)(h-c->view->topoffset-
331                                                 (margin + boldfontextents.max_logical_extent.height + 6))/c->view->nwks;
332                         break;
333                 case yearGlance:
334                         /* revisit for i18n  - is max_bounds correct? */
335                         c->view->boxw = 20 * (short)
336                                         regfontextents.max_logical_extent.width
337                                         + margin;
338                         c->view->boxh = 7 * (short)
339                                         regfontextents.max_ink_extent.height 
340                                         + 2 * (short)
341                                         boldfontextents.max_ink_extent.height;
342                         c->view->topoffset=20;
343                         break;
344                 case dayGlance:
345                         c->view->topoffset = boldfontextents.max_logical_extent.height + 15;
346                         c->view->boxw = APPT_AREA_WIDTH;
347                         c->view->boxh = (int)(h - c->view->topoffset)
348                                 / (end - begin + 1); 
349                         break;
350                 default:
351                         break;
352         }
353 }
354
355 static void
356 resize_proc(
357         Widget           w, 
358         XtPointer        client, 
359         XtPointer        call)
360 {
361         Dimension        width, 
362                          height;
363         Calendar        *c = calendar;
364         Glance           glance = c->view->glance;
365
366         XtVaGetValues(w, XmNwidth, &width, XmNheight, &height, NULL);
367         cache_dims(c, width, height);
368
369         /* If the weekGlance has been initialized then we need to update
370          * its size information reguardless of the current view.
371          */
372         if (glance != weekGlance && c->view->week_info != NULL) {
373                 Boundary        b;
374                 resize_weekview(c, &b);
375         }
376
377         switch(glance) {
378         case monthGlance:
379                 XtUnmapWidget(c->canvas);
380                 prepare_to_paint_monthview(c, NULL);
381                 XtMapWidget(c->canvas);
382                 break;
383         case yearGlance:
384                 return;
385         case weekGlance: {
386                 Boundary        b;
387                 XtUnmapWidget(c->canvas);
388                 resize_weekview(c, &b);
389                 XtMapWidget(c->canvas);
390                 break;
391         }
392         case dayGlance:
393                 /*
394                  * If the resize is caused by a Window Manager maximize
395                  * or minimize, many of the dayview's lengths need to
396                  * be updated.
397                  */
398                 init_dayview (c);
399                 break;
400         default:
401                 paint_grid(c, NULL);
402                 break;
403         }
404 }
405
406 /*
407  * repaint_proc: the XmNexposeCallback handler for the main canvas.
408  *
409  * Does nothing till the last expose in a possible sequence, then
410  * calls the canvas update procedure paint_canvas.
411  *
412  * This could be optimized to only refresh the damaged areas, by
413  * maintaining a smallest-enclosing-rectangle in the Calendar structure
414  * until ev.xexpose.count becomes 0, then setting clip accordingly.
415  * For now, crude but effective will suffice
416  */
417
418 static XRectangle new_clip;
419 static Boolean clip_set = False;
420
421 void
422 repaint_proc(Widget canvas, XtPointer unused, XtPointer data)
423 {
424         Calendar        *c = calendar;
425         XmDrawingAreaCallbackStruct *cbs = (XmDrawingAreaCallbackStruct *) data;
426         XEvent *ev = cbs->event;
427         int             max_height, old_abs_height, new_abs_height;
428         int             max_width, old_abs_width, new_abs_width;
429         unsigned long   valuemask;
430         XSetWindowAttributes attrs;
431         static short    set_bit_gravity = True; 
432
433         if (set_bit_gravity) {
434                 set_bit_gravity = False;
435                 /* 
436                  * Set the bit gravity on the canvas to ForgetGravity to 
437                  * insure we receive an exposure event when the canvas is 
438                  * resized smaller.
439                  */
440                 valuemask = CWBitGravity;
441                 attrs.bit_gravity = ForgetGravity;;
442                 XChangeWindowAttributes(calendar->xcontext->display, 
443                                 XtWindow(calendar->canvas), valuemask, &attrs);
444         }
445
446         if (clip_set == True) {
447                 old_abs_height = new_clip.y + new_clip.height;
448                 new_abs_height = ev->xexpose.height + ev->xexpose.y;
449                 max_height = new_abs_height > old_abs_height ? new_abs_height : old_abs_height;
450                 old_abs_width = new_clip.x + new_clip.width;
451                 new_abs_width = ev->xexpose.width + ev->xexpose.x;
452                 max_width = new_abs_width > old_abs_width ? new_abs_width : old_abs_width;
453         
454                 if (ev->xexpose.x < new_clip.x)
455                         new_clip.x = ev->xexpose.x;
456                 if (ev->xexpose.y < new_clip.y)
457                         new_clip.y = ev->xexpose.y;
458         
459                 new_clip.height = max_height - new_clip.y;
460                 new_clip.width = max_width - new_clip.x;
461         }
462         else {
463                 new_clip.x = ev->xexpose.x;
464                 new_clip.y = ev->xexpose.y;
465                 new_clip.height = ev->xexpose.height;
466                 new_clip.width = ev->xexpose.width;
467
468                 clip_set = True;
469         }
470
471         if (ev->xexpose.count == 0) {
472                 XRectangle      clip;
473                 Dimension       w, h;
474                 new_XContext    *xc;
475
476                 if ((xc = c->xcontext)==NULL)
477                         return;
478
479                 XtVaGetValues(canvas, XmNwidth, &w, XmNheight, &h, NULL);
480
481                 gr_set_clip_rectangles(calendar->xcontext, 0, 0, 
482                                        &new_clip, 1, Unsorted);
483
484                 paint_canvas(c, &new_clip, RENDER_REPAINT);
485
486                 clip.x = 0; clip.y = 0; clip.width = w; clip.height = h;
487                 gr_set_clip_rectangles(calendar->xcontext, 0, 0, &clip, 1, Unsorted);
488
489                 
490                 clip_set = False;
491
492         }
493
494 }
495
496 static void
497 show_tempbr(Calendar *c)
498 {
499         Tempbr *t;
500
501         t = (Tempbr*)c->tempbr; 
502
503         if (t == NULL || t->frame == NULL) {
504                 c->tempbr = (caddr_t)make_tempbr(c);
505                 t = (Tempbr*)c->tempbr; 
506         }
507         else {
508                 XtManageChild(t->form);
509                 XtPopup(t->frame, XtGrabNone);
510         }
511
512         XmProcessTraversal(t->name_text, XmTRAVERSE_CURRENT);
513         XtVaSetValues(t->form, XmNinitialFocus, t->name_text, NULL);
514 }
515
516 static void
517 show_browser(Calendar *c) {
518         extern void     set_entry_date(Calendar *);
519         Browser         *b;
520         Props           *p = (Props*) c->properties;
521         OrderingType    ord_t = get_int_prop(p, CP_DATEORDERING);
522         SeparatorType   sep_t = get_int_prop(p, CP_DATESEPARATOR);
523         char            buf[BUFSIZ];
524
525
526         if (c->browser == NULL)
527                 make_browser(c);
528         b = (Browser *)c->browser; 
529
530
531         b->date = c->view->date;
532         format_tick(b->date, ord_t, sep_t, buf);
533         XmTextSetString(b->datetext, buf);
534
535         set_entry_date(c);
536
537         XtPopup(b->frame, XtGrabNone);
538 }
539
540 static void
541 show_goto(Calendar *c)
542 {
543         Goto *g;
544
545         g = (Goto*)c->goTo; 
546
547         if (g == NULL || g->frame == NULL) {
548                 c->goTo = (caddr_t)make_goto(c);
549                 g = (Goto*)c->goTo; 
550         }
551         else {
552                 XtManageChild(g->form);
553                 XtPopup(g->frame, XtGrabNone);
554         }
555         
556         XmProcessTraversal(g->datetext, XmTRAVERSE_CURRENT);
557         XtVaSetValues(g->form, XmNinitialFocus, g->datetext, NULL);
558
559         set_message(g->goto_message, "\0");
560 }
561
562 static void
563 show_timezone(Calendar *c)
564 {
565         Timezone *t;
566
567         t = (Timezone*)c->timezone; 
568
569         if (t == NULL || t->frame == NULL) {
570                 c->timezone = (caddr_t)make_timezone(c);
571                 t = (Timezone*)c->timezone; 
572         }
573         else {
574                 refresh_timezone(t);
575                 XtManageChild(t->form);
576                 XtPopup(t->frame, XtGrabNone);
577         }
578 }
579
580 static void
581 show_find(Calendar *c)
582 {
583         Find *f;
584
585         f = (Find*)c->find;
586
587         if (f == NULL || f->frame == NULL) {
588                 c->find = (caddr_t)make_find(c);
589                 f = (Find*)c->find;
590         }
591         else {
592                 XtManageChild(f->form);
593                 XtPopup(f->frame, XtGrabNone);
594         }
595
596         XmProcessTraversal(f->apptstr, XmTRAVERSE_CURRENT);
597         XtVaSetValues(f->form, XmNinitialFocus, f->apptstr, NULL);
598
599         set_message(f->find_message, "\0");
600 }
601
602 /* ARGSUSED */
603 /* revisit - this will have to be hacked for motif
604 static void
605 event_proc(Notify_client     canvas,
606     Event                 *event,
607     Notify_arg        arg,
608     Notify_event_type when)
609 {
610         Calendar *c;
611         Props *p;
612         Glance glance;
613         Find *f;
614
615         c = (Calendar *) xv_get(canvas, WIN_CLIENT_DATA); 
616         XtVaGetValues(canvas, XmNuserData, c, NULL);
617         p = (Props *) c->properties;
618         glance = c->view->glance;
619
620         switch(event_action(event)) {
621                 case ACTION_PROPS:
622                         (void)p_show_proc(p->frame);
623                         break;
624                 case ACTION_SELECT:
625                 case ACTION_MENU:
626                 case LOC_DRAG:
627                         switch(glance) {
628                                 case monthGlance:
629                                         month_event(c, event);
630                                         break;
631                                 case weekGlance:
632                                         week_event(c, event);
633                                         break;
634                                 case dayGlance:
635                                         day_event(c, event);
636                                         break;
637                                 case yearGlance:
638                                         year_event(c, event);
639                                         break;
640                         }
641                         c->general->last_canvas_touched = main_win;
642                         break;
643                 case ACTION_FIND_FORWARD:
644                 case ACTION_FIND_BACKWARD:
645                         f = (Find*)c->find;
646                         if (f == NULL || f->frame == NULL) { 
647                                 c->find = (caddr_t)make_find(c);
648                                 f = (Find*)c->find;
649                         }
650                         (void)xv_set(f->frame, XV_SHOW, TRUE, NULL);
651                         XtVaSetValues(bl->frame, XmNmappedWhenManaged, TRUE, NULL);
652                         break;
653                 default:
654                         break;
655         }
656         
657         if (event_action(event) == ACTION_HELP && event_is_up(event))
658         {
659                 switch(glance) {
660                         case monthGlance:
661                                 xv_help_show(canvas, "cm:MonthView", event);
662                                 break;
663                         case weekGlance:
664                                 xv_help_show(canvas, "cm:WeekView", event);
665                                 break;
666                         case dayGlance:
667                                 xv_help_show(canvas, "cm:DayView", event);
668                                 break;
669                         case yearGlance:
670                                 xv_help_show(canvas, "cm:YearView", event);
671                                 break;
672                 }
673                 return(NOTIFY_DONE);
674         } else
675                 return (notify_next_event_func(canvas, (Notify_event)event, arg, when));
676 }
677 */
678
679 void
680 prev_button(Widget w, XtPointer client_data, XtPointer cbs)
681 {
682         Tick date;
683         Calendar *c = calendar;
684         new_XContext *xc;
685         Editor *e = (Editor *) calendar->editor;
686
687         invalidate_cache(c);
688
689         xc = c->xcontext;
690         switch(c->view->glance) {
691                 case weekGlance:
692                         date = last_ndays(c->view->date, 7);
693                         if (timeok(date) ||
694                             ((date = get_bot()) != c->view->date)) {
695                                 c->view->olddate = c->view->date;
696                                 c->view->date = date;
697                                 c->view->nwks = numwks(c->view->date);
698                                 paint_weekview(c, NULL);
699                         }
700                         break;
701                 case monthGlance:
702                         date = previousmonth(c->view->date);
703                         if (timeok(date)) {
704                                 XtUnmapWidget(c->canvas);
705                                 c->view->nwks = numwks(date);
706                                 c->view->olddate = c->view->date;
707                                 c->view->date = date;
708                                 c->view->nwks = numwks(c->view->date);
709                                 (void)prepare_to_paint_monthview(c, NULL);
710                                 XtMapWidget(c->canvas);
711                         }
712                         break;
713                 case yearGlance:
714                         date = lastjan1(c->view->date);
715                         if (timeok(date)) {
716                                 c->view->olddate = c->view->date;
717                                 c->view->date = date;
718                                 c->view->nwks = numwks(c->view->date); 
719 /*
720  * Since we know year view is already showing, just directly force a new
721  * year to be displayed without first managing all the year stuff.
722  */
723                                 paint_year(c);
724                                 calendar_select(c, monthSelect, NULL);
725                         }
726                         break;
727                 case dayGlance:
728                         date = last_ndays(c->view->date, 1);
729                         if (timeok(date)) {
730                                 c->view->olddate = c->view->date;
731                                 c->view->date = date;
732                                 c->view->nwks = numwks(c->view->date);
733                                 calendar_deselect(c);
734                                 if (c->view->date <
735                                     lowerbound(((Day *)(c->view->day_info))->month1)) { 
736                                         ((Day *)(c->view->day_info))->month3
737                                                 = c->view->date;
738                                         ((Day *)(c->view->day_info))->month2
739                                                 = previousmonth(c->view->date);
740                                         ((Day *)(c->view->day_info))->month1
741                                                 = previousmonth(((Day *)(c->view->day_info))->month2);
742                                         init_dayview(c);
743                                         paint_dayview(c, True, NULL, False);
744                                 } else { 
745                                         monthbox_deselect(c);
746                                         monthbox_datetoxy(c);
747                                         paint_dayview(c, False, NULL, False);
748                                         monthbox_select(c);
749                                 }
750                                 calendar_select(c, hourSelect, NULL);
751                         }
752                         break;
753                 default:
754                         break;
755         }
756 }
757
758 void
759 next_button(Widget w, XtPointer client_data, XtPointer cbs)
760 {
761         Tick date;
762         Calendar *c = calendar;
763         new_XContext *xc;
764         Editor *e = (Editor *) calendar->editor;
765
766         invalidate_cache(c);
767
768         xc = c->xcontext;
769         switch(c->view->glance) {
770                 case weekGlance:
771                         date = next_ndays(c->view->date, 7);
772                         if (timeok(date) ||
773                             ((date = get_eot()) != c->view->date)) {
774                                 c->view->olddate = c->view->date;
775                                 c->view->date = date;
776                                 c->view->nwks = numwks(c->view->date);
777                                 paint_weekview(c, NULL);
778                         }
779                         break;
780                 case monthGlance:
781                         date = nextmonth(c->view->date);
782                         if (timeok(date)) {
783                                 XtUnmapWidget(c->canvas);
784                                 c->view->olddate = c->view->date;
785                                 c->view->date = date;
786                                 c->view->nwks = numwks(date);
787                                 (void)prepare_to_paint_monthview(c, NULL);
788                                 XtMapWidget(c->canvas);
789                         }
790                         break;
791                 case yearGlance:
792                         date = nextjan1(c->view->date);
793                         if (timeok(date)) {
794                                 c->view->olddate = c->view->date;
795                                 c->view->date = date;
796                                 c->view->nwks = numwks(date);
797 /*
798  * Since we know year view is already showing, just directly force a new
799  * year to be displayed without first managing all the year stuff.
800  */
801                                 paint_year(c);
802                                 calendar_select(c, monthSelect, NULL);
803                         }
804                         break;
805                 case dayGlance:
806                         date = next_ndays(c->view->date, 1);
807                         if (timeok(date)) {
808                                 c->view->olddate = c->view->date;
809                                 c->view->date = date;
810                                 c->view->nwks = numwks(c->view->date);
811                                 /* beyond month range displayed */
812                                 if (c->view->date > upperbound(last_dom(
813                                     (((Day *)(c->view->day_info))->month3)))) {
814                                         ((Day *)(c->view->day_info))->month1
815                                                 = c->view->date;
816                                         ((Day *)(c->view->day_info))->month2
817                                                 = nextmonth(c->view->date);
818                                         ((Day *)(c->view->day_info))->month3
819                                                 = nextmonth(((Day *)(c->view->day_info))->month2);
820                                         calendar_deselect(c);
821                                         init_dayview(c);
822                                         paint_dayview(c, True, NULL, False);
823                                         calendar_select(c, hourSelect, NULL);
824                                 } else {
825                                         calendar_deselect(c);
826                                         monthbox_deselect(c);
827                                         monthbox_datetoxy(c);
828                                         paint_dayview(c, False, NULL, False);
829                                         calendar_select(c, hourSelect, NULL);
830                                         monthbox_select(c);
831                                 }
832                         }
833                         break;
834                 default:
835                         break;
836         }
837 }
838
839 void
840 today_button(Widget w, XtPointer client_data, XtPointer cbs)
841 {
842         Tick today, date;
843         Calendar *c = calendar;
844         new_XContext *xc;
845         int mo_da, mo_to;
846         pr_pos xy;
847         Editor *e = (Editor *) calendar->editor;
848
849         invalidate_cache(c);
850
851         date = c->view->date;
852         c->view->olddate = c->view->date;
853         c->view->date = today = now();
854         mo_da = month(date);
855         mo_to = month(today);
856         c->view->nwks = numwks(today);
857         calendar_deselect(c);
858         switch(c->view ->glance) {
859         case weekGlance:
860                 if (mo_da != mo_to || dom(date) != dom(today) ||
861                         year(date) != year(today)) {
862                         paint_weekview(c, NULL);
863                 }
864                 calendar_select(c, weekdaySelect, NULL);
865                 break;
866         case monthGlance:
867                 if (mo_da != mo_to || year(date) != year(today)) {
868                         XtUnmapWidget(c->canvas);
869                         xc = c->xcontext;
870                         (void)prepare_to_paint_monthview(c, NULL);
871                         XtMapWidget(c->canvas);
872                 }
873                 calendar_select(c, daySelect, (caddr_t)NULL);
874                 break;
875         case yearGlance:
876 /*
877  * Since we know year view is already showing, just directly force a new
878  * year to be displayed without first managing all the year stuff.
879  */
880                 if (year(date) != year(today)) 
881                         paint_year(c);
882                 else calendar_deselect(c); 
883                 xy.y = month_row_col[mo_to-1][ROW];
884                 xy.x = month_row_col[mo_to-1][COL];
885                 calendar_select(c, monthSelect, (caddr_t)&xy);
886                 break;
887         case dayGlance:
888                 if (mo_da != mo_to || dom(date) != dom(today) ||
889                                 year(date) != year(today)) {
890                         if (mo_to < month(((Day *)(c->view->day_info))->month1) ||
891                                 mo_to > month(((Day *)(c->view->day_info))->month3)) {
892                                 calendar_deselect(c);
893                                 init_mo(c);
894                                 init_dayview(c);
895                                 paint_dayview(c, True, NULL, True);
896                         }
897                         else {
898                                 calendar_deselect(c);
899                                 monthbox_deselect(c);
900                                 monthbox_datetoxy(c);
901                                 paint_dayview(c, False, NULL, True);
902                                 monthbox_select(c);
903                         }
904                 }
905                 calendar_select(c, hourSelect,(caddr_t)NULL);
906                 break;
907         default:
908                 break;
909         }
910 }
911
912 /*
913 static Menu
914 gen_tzmenu(item, op)
915         Menu_item item;
916         Menu_generate op;
917 {
918         char *path;
919         static Menu pullright;
920
921         switch(op) {
922         case MENU_DISPLAY       : 
923                 if (pullright == NULL) {
924 */
925 /*
926                         path = (char *) xv_get(item, MENU_CLIENT_DATA);
927 */
928 /*
929                         XtVaGetArgs(item, XmNuserData, path, NULL);
930                         pullright = make_tzmenu(path);
931                         break;
932                 }
933         case MENU_DISPLAY_DONE :
934         case MENU_NOTIFY        :
935         case MENU_NOTIFY_DONE   : break ;
936         }
937         return(pullright);
938 }
939 */
940
941 static void
942 set_default_view(Calendar *c)
943 {
944         /* See if the view is set via a command line option */
945         if (calendar->app_data->default_view) {
946                 if (!strcmp(calendar->app_data->default_view, "year"))
947                         calendar->view->glance = yearGlance;
948                 else if (!strcmp(calendar->app_data->default_view, "month"))
949                         calendar->view->glance = monthGlance;
950                 else if (!strcmp(calendar->app_data->default_view, "week"))
951                         calendar->view->glance = weekGlance;
952                 else if (!strcmp(calendar->app_data->default_view, "day")) 
953                         calendar->view->glance = dayGlance;
954                 else
955                         calendar->view->glance = dayGlance;
956         } else
957                 calendar->view->glance = dayGlance;
958 }
959
960 /*
961  * Changed the code that calls these to directly call the callbacks
962  * called from here... not sure why there was this indirection.
963  * It should be safe to remove these.
964  */
965 void view_day_cb(Widget w, XtPointer data, XtPointer cbs)
966 {
967         if ((int) data == 0)
968                 day_button(w, data, cbs);
969 }
970
971 void view_week_cb(Widget w, XtPointer data, XtPointer cbs)
972 {
973         if ((int) data == 0)
974                 week_button(w, data, cbs);
975 }
976
977 void view_month_cb(Widget w, XtPointer data, XtPointer cbs)
978 {
979         if ((int) data == 0)
980                 month_button(w, data, cbs);
981 }
982
983 void view_year_cb( Widget w, XtPointer data, XtPointer cbs)
984 {
985         if ((int) data == 0)
986                 (void) year_button(w, data, cbs);
987 }
988
989 static void
990 make_view_menu(Calendar *c)
991 {
992         void view_appt_cb(), view_todo_cb();
993         Widget view_menu, day, week, month, year, appt_list, tz,
994                 view_btn, sep, find, go_to;
995         XmString day_str, week_str, month_str, year_str, tz_str, apptlist_str,
996                 todo_str, view_str, findappts, gotodate;
997         Arg al[10];
998         int ac;
999
1000         day_str = XmStringCreateLocalized(catgets(c->DT_catd, 1, 33, "Day"));
1001         week_str = XmStringCreateLocalized(catgets(c->DT_catd, 1, 34, "Week"));
1002         month_str = XmStringCreateLocalized(
1003                         catgets(c->DT_catd, 1, 35, "Month"));
1004         year_str = XmStringCreateLocalized(catgets(c->DT_catd, 1, 36, "Year"));
1005         tz_str = XmStringCreateLocalized(
1006                         catgets(c->DT_catd, 1, 37, "Time Zone..."));
1007         apptlist_str = XmStringCreateLocalized(
1008                         catgets(c->DT_catd, 1, 38, "Appointment List..."));
1009         todo_str = XmStringCreateLocalized(
1010                         catgets(c->DT_catd, 1, 965, "To Do List..."));
1011         view_str = XmStringCreateLocalized(catgets(c->DT_catd, 1, 40, "View"));
1012         findappts = XmStringCreateLocalized(
1013                         catgets(c->DT_catd, 1, 41, "Find..."));
1014         gotodate = XmStringCreateLocalized(
1015                         catgets(c->DT_catd, 1, 42, "Go to Date..."));
1016
1017         view_menu = XmCreatePulldownMenu(c->menu_bar, "viewMenu", NULL, 0);
1018
1019         ac = 0;
1020         XtSetArg(al[ac], XmNlabelString, day_str); ac++;
1021         day = XmCreatePushButtonGadget(view_menu, "day", al, ac);
1022         XtAddCallback(day, XmNactivateCallback, day_button, NULL);
1023
1024         ac = 0;
1025         XtSetArg(al[ac], XmNlabelString, week_str); ac++;
1026         week = XmCreatePushButtonGadget(view_menu, "week", al, ac);
1027         XtAddCallback(week, XmNactivateCallback, week_button, NULL);
1028
1029         ac = 0;
1030         XtSetArg(al[ac], XmNlabelString, month_str); ac++;
1031         month = XmCreatePushButtonGadget(view_menu, "month", al, ac);
1032         XtAddCallback(month, XmNactivateCallback, month_button, NULL);
1033
1034         ac = 0;
1035         XtSetArg(al[ac], XmNlabelString, year_str); ac++;
1036         year = XmCreatePushButtonGadget(view_menu, "year", al, ac);
1037         XtAddCallback(year, XmNactivateCallback, year_button, NULL);
1038
1039         ac = 0;
1040         sep = XmCreateSeparatorGadget(view_menu, "separator1", al, ac);
1041
1042         ac = 0;
1043         XtSetArg(al[ac], XmNlabelString, apptlist_str); ac++;
1044         appt_list = XmCreatePushButtonGadget(view_menu, "apptList", al, ac);
1045         XtAddCallback(appt_list, XmNactivateCallback, view_appt_cb, NULL);
1046
1047         ac = 0;
1048         XtSetArg(al[ac], XmNlabelString, todo_str); ac++;
1049         c->todo_view_menu = XmCreatePushButtonGadget(view_menu, "toDoList", 
1050                         al, ac);
1051         XtAddCallback(c->todo_view_menu, XmNactivateCallback, 
1052                         view_todo_cb, NULL);
1053
1054         ac = 0;
1055         sep = XmCreateSeparatorGadget(view_menu, "separator2", al, ac);
1056
1057         ac = 0;
1058         XtSetArg(al[ac], XmNlabelString, findappts); ac++;
1059         find = XmCreatePushButtonGadget(view_menu, "find", al, ac);
1060         XtAddCallback(find, XmNactivateCallback, find_cb, NULL);
1061
1062         ac = 0;
1063         XtSetArg(al[ac], XmNlabelString, gotodate); ac++;
1064         go_to = XmCreatePushButtonGadget(view_menu, "goTo", al, ac);
1065         XtAddCallback(go_to, XmNactivateCallback, goto_cb, NULL);
1066
1067         ac = 0;
1068         XtSetArg(al[ac], XmNlabelString, tz_str); ac++;
1069         tz = XmCreatePushButtonGadget(view_menu, "timeZone", al, ac);
1070         XtAddCallback(tz, XmNactivateCallback, timezone_cb, NULL);
1071
1072         ManageChildren(view_menu);
1073
1074         XtSetArg(al[ac], XmNsubMenuId, view_menu); ac++;
1075         XtSetArg(al[ac], XmNlabelString, view_str); ac++;
1076         view_btn = (Widget) XmCreateCascadeButton(c->menu_bar, "view", al, ac);
1077         XtAddCallback(view_btn, XmNhelpCallback, (XtCallbackProc)help_cb, 
1078                         (XtPointer) CALENDAR_HELP_VIEW_BUTTON);
1079
1080         XmStringFree(day_str);
1081         XmStringFree(week_str);
1082         XmStringFree(month_str);
1083         XmStringFree(year_str);
1084         XmStringFree(tz_str);
1085         XmStringFree(apptlist_str);
1086         XmStringFree(todo_str);
1087         XmStringFree(view_str);
1088         XmStringFree(findappts);
1089         XmStringFree(gotodate);
1090 }
1091
1092 extern void
1093 print_cb(Widget ignore1, XtPointer ignore2, XtPointer ignore3)
1094 {
1095   _DtTurnOnHourGlass(calendar->frame);
1096   post_print_dialog(calendar);
1097   _DtTurnOffHourGlass(calendar->frame);
1098 }
1099
1100 extern void
1101 print_current(Widget widget, XtPointer client_data, XtPointer reason)
1102 {
1103   _DtTurnOnHourGlass(calendar->frame);
1104   create_print_dialog(calendar);
1105   print_report(calendar);
1106   _DtTurnOffHourGlass(calendar->frame);
1107 }
1108
1109 void 
1110 edit_cb( Widget w, XtPointer item_no, XtPointer cbs)
1111 {
1112         Calendar *c = calendar;
1113
1114         _DtTurnOnHourGlass(c->frame);
1115         if ((int) item_no == 1)
1116                 show_props_pu(c);
1117         else if ((int) item_no == 3)
1118                 make_find(c);
1119         _DtTurnOffHourGlass(c->frame);
1120 }
1121
1122 void 
1123 find_cb(Widget w, XtPointer item_no, XtPointer cbs)
1124 {
1125         Calendar *c = calendar;
1126
1127         _DtTurnOnHourGlass(c->frame);
1128         show_find(calendar);
1129         _DtTurnOffHourGlass(c->frame);
1130 }
1131
1132 void 
1133 goto_cb(Widget w, XtPointer item_no, XtPointer cbs)
1134 {
1135         Calendar *c = calendar;
1136
1137         _DtTurnOnHourGlass(c->frame);
1138         show_goto(calendar);
1139         _DtTurnOffHourGlass(c->frame);
1140 }
1141
1142 void 
1143 timezone_cb(Widget w, XtPointer item_no, XtPointer cbs)
1144 {
1145         Calendar *c = calendar;
1146
1147         _DtTurnOnHourGlass(c->frame);
1148         show_timezone(calendar);
1149         _DtTurnOffHourGlass(c->frame);
1150 }
1151
1152 void
1153 view_appt_cb(Widget w, XtPointer item_no, XtPointer cbs)
1154 {
1155         Calendar        *c = calendar;
1156
1157         _DtTurnOnHourGlass(c->frame);
1158         show_editor_view(c, c->view->glance);
1159         _DtTurnOffHourGlass(c->frame);
1160 }
1161
1162 void
1163 view_todo_cb(Widget w, XtPointer item_no, XtPointer cbs)
1164 {
1165         Calendar        *c = calendar;
1166
1167         _DtTurnOnHourGlass(c->frame);
1168         show_todo_view(c, VIEW_PENDING);
1169         _DtTurnOffHourGlass(c->frame);
1170 }
1171
1172 void 
1173 appt_cb(Widget w, XtPointer item_no, XtPointer cbs)
1174 {
1175         Calendar *c = calendar;
1176
1177         _DtTurnOnHourGlass(c->frame);
1178         switch((int) item_no) {
1179         case 0:
1180                 show_editor(c, 0, 0, False);
1181                 break;
1182         case 1:
1183                 show_geditor(c, 0, 0);
1184                 break;
1185         case 2:
1186                 show_todo(c);
1187                 break;
1188         default:
1189                 break;
1190         }
1191         _DtTurnOffHourGlass(c->frame);
1192 }
1193
1194 static void 
1195 show_other_cb(Widget w, XtPointer cl_data, XtPointer cbs)
1196 {
1197         Calendar *c = calendar;
1198
1199         _DtTurnOnHourGlass(c->frame);
1200         show_tempbr(c);
1201         _DtTurnOffHourGlass(c->frame);
1202 }
1203
1204 static void 
1205 compare_cb(Widget w, XtPointer cl_data, XtPointer cbs)
1206 {
1207         Calendar *c = calendar;
1208
1209         _DtTurnOnHourGlass(c->frame);
1210         show_browser(c);
1211         _DtTurnOffHourGlass(c->frame);
1212 }
1213
1214 static void 
1215 edit_menu_cb(Widget w, XtPointer cl_data, XtPointer cbs)
1216 {
1217         Calendar        *c = (Calendar *)cl_data;
1218
1219         _DtTurnOnHourGlass(c->frame);
1220         show_browselist(c);
1221         _DtTurnOffHourGlass(c->frame);
1222 }
1223
1224 static void 
1225 browse_cb(Widget w, XtPointer client_data, XtPointer cbs) {
1226         int             rcode, idx = (int)client_data;
1227         char            buf[MAXNAMELEN];
1228         Calendar        *c = calendar;
1229         Props_pu        *p = (Props_pu *)c->properties_pu;
1230         BlistData       *bd;
1231         Browselist      *bl = (Browselist *)c->browselist;
1232
1233         if (!(bd = (BlistData *)CmDataListGetData(bl->blist_data, idx))) {
1234                 char *title = XtNewString(catgets(c->DT_catd, 1, 1072,
1235                                 "Calendar : Error - Browse"));
1236                 char *text = XtNewString(catgets(c->DT_catd, 1, 610,
1237                                 "Internal error retrieving calendar name."));
1238                 char *ident = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
1239                 dialog_popup(c->frame,
1240                         DIALOG_TITLE, title,
1241                         DIALOG_TEXT, text,
1242                         BUTTON_IDENT, 1, ident,
1243                         DIALOG_IMAGE, p->xm_error_pixmap,
1244                         NULL);
1245                 XtFree(ident);
1246                 XtFree(text);
1247                 XtFree(title);
1248                 return;
1249         }
1250
1251         _DtTurnOnHourGlass(c->frame);
1252 #ifdef FNS
1253         if (cmfns_use_fns((Props *)c->properties)) {
1254                 rcode = cmfns_lookup_calendar(bd->name, buf, sizeof(buf));
1255         } else {
1256                 rcode = -1;
1257         }
1258
1259         if (rcode > 0)
1260                 switch_it(c, buf, main_win);
1261         else
1262 #endif
1263                 switch_it(c, bd->name, main_win);
1264         _DtTurnOffHourGlass(c->frame);
1265 }
1266
1267 static void
1268 make_file_menu(Calendar *c)
1269 {
1270         Widget file_menu, print, pr_current, opts, exit, file_btn, sep;
1271         XmString xmstr;
1272         Arg al[10];
1273         int ac;
1274
1275         file_menu = XmCreatePulldownMenu(c->menu_bar, "fileMenu", NULL, 0);
1276
1277         ac = 0;
1278         xmstr = XmStringCreateLocalized(
1279                         catgets(c->DT_catd, 1, 68, "Print Current View"));
1280         XtSetArg(al[ac], XmNlabelString, xmstr); ac++;
1281         pr_current = XmCreatePushButtonGadget(file_menu, "printCurrent", 
1282                                               al, ac);
1283         XtAddCallback(pr_current, XmNactivateCallback, print_current, NULL);
1284         XmStringFree(xmstr);
1285
1286         ac = 0;
1287         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 69, "Print..."));
1288         XtSetArg(al[ac], XmNlabelString, xmstr); ac++;
1289         print = XmCreatePushButtonGadget(file_menu, "print", al, ac);
1290         XtAddCallback(print, XmNactivateCallback, print_cb, NULL);
1291         XmStringFree(xmstr);
1292
1293         ac = 0;
1294         sep = XmCreateSeparatorGadget(file_menu, "separator1", al, ac);
1295
1296         ac = 0;
1297         xmstr = XmStringCreateLocalized(
1298                                 catgets(c->DT_catd, 1, 72, "Options..."));
1299         XtSetArg(al[ac], XmNlabelString, xmstr); ac++;
1300         opts = XmCreatePushButtonGadget(file_menu, "options", al, ac);
1301         XtAddCallback(opts, XmNactivateCallback, edit_cb, (XtPointer) 1);
1302         XmStringFree(xmstr);
1303
1304         ac = 0;
1305         sep = XmCreateSeparatorGadget(file_menu, "separator2", al, ac);
1306
1307         ac = 0;
1308         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 73, "Exit"));
1309         XtSetArg(al[ac], XmNlabelString, xmstr); ac++;
1310         exit = XmCreatePushButtonGadget(file_menu, "exit", al, ac);
1311         XtAddCallback(exit, XmNactivateCallback, quit_handler, (XtPointer) c);
1312         XmStringFree(xmstr);
1313
1314         ManageChildren(file_menu);
1315
1316         ac = 0;
1317         XtSetArg(al[ac], XmNsubMenuId, file_menu); ac++;
1318         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 65, "File"));
1319         XtSetArg(al[ac], XmNlabelString, xmstr); ac++;
1320         file_btn = (Widget) XmCreateCascadeButton(c->menu_bar, "file", al, ac);
1321         XtAddCallback(file_btn, XmNhelpCallback, (XtCallbackProc)help_cb, 
1322                                         (XtPointer) CALENDAR_HELP_FILE_BUTTON);
1323         XmStringFree(xmstr);
1324 }
1325
1326 static void
1327 make_edit_menu(Calendar *c)
1328 {
1329         Widget edit_menu, edit_button;
1330         Widget appt, props;
1331         XmString edit_str, appt_str, todo_str;
1332         Arg al[10];
1333         int ac;
1334
1335         appt_str = XmStringCreateLocalized(
1336                         catgets(c->DT_catd, 1, 74, "Appointment..."));
1337         todo_str = XmStringCreateLocalized(
1338                         catgets(c->DT_catd, 1, 966, "To Do..."));
1339         edit_str = XmStringCreateLocalized(
1340                         catgets(c->DT_catd, 1, 76, "Edit"));
1341
1342         edit_menu = XmCreatePulldownMenu(c->menu_bar, "editMenu", NULL, 0);
1343
1344         ac = 0;
1345         XtSetArg(al[ac], XmNlabelString, appt_str); ac++;
1346         appt = XmCreatePushButtonGadget(edit_menu, "appt", al, ac);
1347         XtAddCallback(appt, XmNactivateCallback, appt_cb, (XtPointer) 0);
1348
1349         ac = 0;
1350         XtSetArg(al[ac], XmNlabelString, todo_str); ac++;
1351         c->todo_edit_menu = XmCreatePushButtonGadget(edit_menu, "toDo", al, ac);
1352         XtAddCallback(c->todo_edit_menu, XmNactivateCallback, 
1353                         appt_cb, (XtPointer) 2);
1354
1355         ManageChildren(edit_menu);
1356
1357         ac = 0;
1358         XtSetArg(al[ac], XmNsubMenuId, edit_menu); ac++;
1359         XtSetArg(al[ac], XmNlabelString, edit_str); ac++;
1360         edit_button = XmCreateCascadeButton(c->menu_bar, "edit", al, ac);
1361         XtAddCallback(edit_button, XmNhelpCallback, (XtCallbackProc)help_cb,
1362                         (XtPointer) CALENDAR_HELP_EDIT_BUTTON);
1363
1364         XmStringFree(appt_str);
1365         XmStringFree(todo_str);
1366         XmStringFree(edit_str);
1367 }
1368
1369 static void
1370 make_help_menu(Calendar *c)
1371 {
1372         Arg al[10];
1373         int ac;
1374         XmString help, overview, tasks, ref, onitem, using, about;
1375         Widget  cascade, help_menu, w_overview, w_tasks, w_ref, w_onitem, 
1376                 w_using, w_about, w_sep;
1377
1378         help = XmStringCreateLocalized(catgets(c->DT_catd, 1, 77, "Help"));
1379         overview = XmStringCreateLocalized(
1380                         catgets(c->DT_catd, 1, 612, "Overview..."));
1381         tasks = XmStringCreateLocalized(catgets(c->DT_catd, 1, 79, "Tasks..."));
1382         ref = XmStringCreateLocalized(
1383                         catgets(c->DT_catd, 1, 80, "Reference..."));
1384         onitem = XmStringCreateLocalized(
1385                         catgets(c->DT_catd, 1, 964, "On Item"));
1386         using = XmStringCreateLocalized(
1387                         catgets(c->DT_catd, 1, 82, "Using Help..."));
1388         about = XmStringCreateLocalized(
1389                         catgets(c->DT_catd, 1, 613, "About Calendar..."));   
1390
1391         help_menu = XmCreatePulldownMenu(c->menu_bar, "helpMenu", NULL, 0);
1392
1393         ac = 0;
1394         XtSetArg(al[ac], XmNlabelString, overview); ac++;
1395         w_overview = XmCreatePushButtonGadget(help_menu, "overview", al, ac);
1396         XtAddCallback(w_overview, XmNactivateCallback, show_main_help, 
1397                         (XtPointer)HELP_OVERVIEW); 
1398
1399         ac = 0;
1400         w_sep = XmCreateSeparatorGadget(help_menu, "separator1", al, ac);
1401
1402         ac = 0;
1403         XtSetArg(al[ac], XmNlabelString, tasks); ac++;
1404         w_tasks = XmCreatePushButtonGadget(help_menu, "tasks", al, ac);
1405         XtAddCallback(w_tasks, XmNactivateCallback, show_main_help, 
1406                         (XtPointer)HELP_TASKS);
1407
1408         ac = 0;
1409         XtSetArg(al[ac], XmNlabelString, ref); ac++;
1410         w_ref = XmCreatePushButtonGadget(help_menu, "reference", al, ac);
1411         XtAddCallback(w_ref, XmNactivateCallback, show_main_help, 
1412                         (XtPointer)HELP_REFERENCE);
1413
1414         ac = 0;
1415         XtSetArg(al[ac], XmNlabelString, onitem); ac++;
1416         w_onitem = XmCreatePushButtonGadget(help_menu, "onItem", al, ac);
1417         XtAddCallback(w_onitem, XmNactivateCallback, show_main_help, 
1418                         (XtPointer)HELP_ONITEM);
1419
1420         ac = 0;
1421         w_sep = XmCreateSeparatorGadget(help_menu, "separator2", al, ac);
1422
1423         ac = 0;
1424         XtSetArg(al[ac], XmNlabelString, using); ac++;
1425         w_using = XmCreatePushButtonGadget(help_menu, "using", al, ac);
1426         XtAddCallback(w_using, XmNactivateCallback, show_main_help, 
1427                         (XtPointer)HELP_USINGHELP);
1428
1429         ac = 0;
1430         w_sep = XmCreateSeparatorGadget(help_menu, "separator2", al, ac);
1431
1432         ac = 0;
1433         XtSetArg(al[ac], XmNlabelString, about); ac++;
1434         w_about = XmCreatePushButtonGadget(help_menu, "about", al, ac);
1435         XtAddCallback(w_about, XmNactivateCallback, show_about, 
1436                         (XtPointer)NULL);
1437         XtAddCallback(w_about, XmNactivateCallback, show_main_help, 
1438                         (XtPointer)HELP_ABOUTCALENDAR);
1439
1440         ManageChildren(help_menu);
1441
1442         ac = 0;
1443         XtSetArg(al[ac], XmNlabelString, help); ac++;
1444         XtSetArg(al[ac], XmNsubMenuId, help_menu); ac++;
1445         cascade = (Widget)XmCreateCascadeButton(c->menu_bar, "help", al, ac);
1446         XtAddCallback(cascade, XmNhelpCallback, (XtCallbackProc)help_cb, 
1447                         (XtPointer) CALENDAR_HELP_HELP_BUTTON);
1448
1449         ac = 0;
1450         XtSetArg(al[ac], XmNmenuHelpWidget, cascade); ac++;
1451         XtSetValues(c->menu_bar, al, ac);
1452
1453         XmStringFree(help);
1454         XmStringFree(overview);
1455         XmStringFree(tasks);
1456         XmStringFree(ref);
1457         XmStringFree(onitem);
1458         XmStringFree(using);
1459         XmStringFree(about);
1460 }
1461
1462 static void
1463 map_browse_menu(Widget menu, XtPointer client_data, XtPointer call_data)
1464
1465 {
1466         Position y;
1467         Dimension h, w;
1468         short   maxcols, newcols, columns;
1469         int     screenheight = HeightOfScreen(XtScreen(menu));
1470         int     fudgefact = 20; /* to allow for decorations on menu */
1471
1472         XtVaGetValues(menu,
1473         XmNheight, &h,
1474         XmNwidth, &w,
1475         XmNy, &y,
1476         XmNnumColumns, &columns,
1477         NULL);
1478
1479
1480         if ((int) (h + fudgefact) > ((int) screenheight / 2)) {
1481
1482         /* the menu is taller than half the screen.  We need to find out how 
1483            many more columns to specify for the menu to make it fit. */
1484
1485                 newcols = (columns * (int) ((int) (h + fudgefact)/(int) (screenheight/2))) + 1;
1486                 maxcols = WidthOfScreen(XtScreen(menu))/(int) ((int)w/(int)columns);
1487
1488                 if (newcols > maxcols)
1489                         newcols = maxcols;
1490
1491                 XtVaSetValues(menu, XmNnumColumns, newcols, NULL);
1492         }
1493
1494 }
1495
1496
1497 /*
1498  * This a seperate routine so that it may be called when a new name is added
1499  * from the edit list
1500  */
1501 extern void
1502 update_browse_menu_names(Calendar *c) {
1503         int             i, ac;
1504         Arg             al[10];
1505         char            *str;
1506         Widget          item;
1507         XmString        xmstr;
1508         BlistData       *bd;
1509         Browselist      *bl = (Browselist *)c->browselist;
1510  
1511         c->browse_menu =
1512                 XmCreatePulldownMenu(c->menu_bar, "browseMenu", NULL, 0);
1513         XtVaSetValues(c->browse_menu, 
1514                 XmNnumColumns, 1, 
1515                 XmNpacking, XmPACK_COLUMN,
1516                 XmNorientation, XmVERTICAL,
1517                 NULL);
1518
1519         ac = 0;
1520         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 84,
1521                                                 "Show Other Calendar..."));
1522         XtSetArg(al[ac], XmNlabelString, xmstr); ac++;
1523         item = XmCreatePushButtonGadget(c->browse_menu, "showOther", al, ac);
1524         XtAddCallback(item, XmNactivateCallback, show_other_cb, NULL);
1525         XmStringFree(xmstr);
1526
1527         ac = 0;
1528         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 85,
1529                                                 "Compare Calendars..."));
1530         XtSetArg(al[ac], XmNlabelString, xmstr); ac++;
1531         item = XmCreatePushButtonGadget(c->browse_menu, "compare", al, ac);
1532         XtAddCallback(item, XmNactivateCallback, compare_cb, NULL);
1533         XmStringFree(xmstr);
1534
1535         ac = 0;
1536         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 86,
1537                                                 "Menu Editor..."));
1538         XtSetArg(al[ac], XmNlabelString, xmstr); ac++;
1539         item = XmCreatePushButtonGadget(c->browse_menu, "editMenu", al, ac);
1540         XtAddCallback(item, XmNactivateCallback, edit_menu_cb, (XtPointer)c);
1541         XmStringFree(xmstr);
1542
1543         ac = 0;
1544         item = XmCreateSeparatorGadget(c->browse_menu, "separator", al, ac);
1545
1546         blist_clean(bl, TRUE);
1547         blist_init_names(c);
1548         for (i = 1; i <= bl->blist_data->count; i++) {
1549                 bd = (BlistData *)CmDataListGetData(bl->blist_data, i);
1550                 if (!bd || blank_buf(bd->name) || bd->tag != BLIST_ACTIVE)
1551                         continue;
1552
1553                 ac = 0;
1554                 xmstr = XmStringCreateLocalized(bd->name);
1555                 XtSetArg(al[ac], XmNlabelString, xmstr); ac++;
1556                 str = (!strcmp(bd->name, c->calname)) ? "calName" : "myName";
1557                 item = XmCreatePushButtonGadget(c->browse_menu, str, al, ac);
1558                 XtAddCallback(item, XmNactivateCallback, browse_cb,
1559                               (XtPointer)i);
1560                 XmStringFree(xmstr);
1561         }
1562
1563         XtAddCallback(c->browse_menu, XmNmapCallback, map_browse_menu, NULL); 
1564         ManageChildren(c->browse_menu);
1565 }
1566
1567
1568 static void
1569 make_browse_menu(Calendar *c) {
1570         Arg             al[10];
1571         int             ac = 0;
1572         XmString        xmstr;
1573
1574         /*
1575          * This needs to be a seperate routine so it can be called when the
1576          * edit list changes the browse menu
1577          */
1578         update_browse_menu_names(c);
1579
1580         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 87, "Browse"));
1581         XtSetArg(al[ac], XmNsubMenuId, c->browse_menu); ac++;
1582         XtSetArg(al[ac], XmNlabelString, xmstr); ac++;
1583         c->browse_button = XmCreateCascadeButton(c->menu_bar, "browse", al, ac);
1584         XtAddCallback(c->browse_button, XmNhelpCallback,(XtCallbackProc)help_cb,
1585                       (XtPointer)CALENDAR_HELP_BROWSE_BUTTON);
1586         XtManageChild(c->browse_button);
1587         XmStringFree(xmstr);
1588 }
1589
1590 /*
1591  * Create the menu bar and all the pulldowns it manages
1592  * Menu bar is associated with its MainWindow parent after this returns
1593  */
1594 static void
1595 make_menus(Calendar *c)
1596 {
1597         int     ac = 0;
1598         Arg     al[10];
1599
1600         XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
1601         XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
1602         XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
1603         c->menu_bar = XmCreateMenuBar(c->form, "menuBar", al, ac);
1604
1605         make_file_menu(c);
1606         make_edit_menu(c);
1607         make_view_menu(c);
1608         make_browse_menu(c);
1609         make_help_menu(c);
1610         ManageChildren(c->menu_bar);
1611 }
1612
1613 /*
1614  * Create the toolbar in the main window
1615  */
1616 static void
1617 make_buttons(Calendar *c)
1618 {
1619         XmString        today_str;
1620         Arg             al[10];
1621         int             ac = 0;
1622         Dimension       today_width;
1623         Widget          toolform;
1624         Props_pu        *pu = (Props_pu *)c->properties_pu;
1625         Pixel           fg, bg;
1626         Screen          *s;
1627
1628         today_str = XmStringCreateLocalized(
1629                         catgets(c->DT_catd, 1, 88, "Today"));
1630         ac=0;
1631         XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
1632         XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
1633         XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
1634         XtSetArg(al[ac], XmNtopWidget, c->menu_bar); ac++;
1635         calendar->toolbar = XmCreateFrame(c->form, "toolbar", al, ac);
1636
1637         s = XtScreen(calendar->toolbar);
1638         XtVaGetValues(calendar->toolbar, 
1639                         XmNforeground,  &fg, 
1640                         XmNbackground,  &bg,
1641                         NULL);
1642
1643         pu->appt_button_xbm = XmGetPixmap(s, "DtCMapt.s.pm", fg, bg);
1644         pu->todo_button_xbm = XmGetPixmap(s, "DtCMtdo.s.pm", fg, bg);
1645         pu->year_button_xbm = XmGetPixmap(s, "DtCMyr.s.pm", fg, bg);
1646         pu->month_button_xbm = XmGetPixmap(s, "DtCMmth.s.pm", fg, bg);
1647         pu->week_button_xbm = XmGetPixmap(s, "DtCMwk.s.pm", fg, bg);
1648         pu->day_button_xbm = XmGetPixmap(s, "DtCMday.s.pm", fg, bg);
1649
1650         ac=0;
1651         XtSetArg(al[ac], XmNfractionBase, 100); ac++;
1652         toolform = XmCreateForm(c->toolbar, "toolform", al, ac);
1653
1654         ac=0;
1655         XtSetArg(al[ac], XmNlabelString, today_str); ac++;
1656         XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
1657         XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
1658         XtSetArg(al[ac], XmNleftAttachment, XmATTACH_POSITION); ac++;
1659         XtSetArg(al[ac], XmNleftPosition, 50); ac++;
1660         XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
1661         c->today = XmCreatePushButton(toolform, "today", al, ac);
1662         XmStringFree(today_str);
1663         XtAddCallback(calendar->today, XmNactivateCallback, today_button, NULL);
1664         XtAddCallback(c->today, XmNhelpCallback, (XtCallbackProc)help_cb, 
1665                         (XtPointer) CALENDAR_HELP_TODAY_BUTTON);
1666
1667         /*
1668          * Need to centre the today button, as it shrink-wraps its
1669          * label, and will now be out of position.  Unpleasant, but
1670          * necessary because XmForm doesn't provide direct means of centring.
1671          */
1672         XtVaGetValues(c->today, XmNwidth, &today_width, NULL);
1673         XtVaSetValues(c->today, XmNleftOffset, (int) today_width/-2, NULL);
1674
1675         ac=0;
1676         XtSetArg(al[ac], XmNarrowDirection, XmARROW_LEFT); ac++;
1677         XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
1678         XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
1679         XtSetArg(al[ac], XmNrightAttachment, XmATTACH_WIDGET); ac++;
1680         XtSetArg(al[ac], XmNrightWidget, c->today); ac++;
1681         XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
1682         c->previous = XmCreateArrowButtonGadget(toolform, "previous", al, ac);
1683         XtAddCallback(c->previous, XmNactivateCallback, prev_button, NULL);
1684         XtAddCallback(c->previous, XmNhelpCallback, (XtCallbackProc)help_cb, 
1685                         (XtPointer) CALENDAR_HELP_PREV_BUTTON);
1686
1687         ac=0;
1688         XtSetArg(al[ac], XmNarrowDirection, XmARROW_RIGHT); ac++;
1689         XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
1690         XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
1691         XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
1692         XtSetArg(al[ac], XmNleftWidget, c->today); ac++;
1693         XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
1694         c->next = XmCreateArrowButtonGadget(toolform, "next", al, ac);
1695         XtAddCallback(c->next, XmNactivateCallback, next_button, NULL);
1696         XtAddCallback(c->next, XmNhelpCallback, (XtCallbackProc)help_cb, 
1697                         (XtPointer) CALENDAR_HELP_NEXT_BUTTON);
1698
1699         /* toolbar "editor" buttons */
1700         ac=0;
1701         XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
1702         XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
1703         XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
1704         XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
1705         XtSetArg(al[ac], XmNlabelPixmap, pu->appt_button_xbm); ac++;
1706         XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
1707         c->appt_btn = XmCreatePushButtonGadget(toolform, "appt", al, ac);
1708         XtAddCallback(c->appt_btn, XmNactivateCallback, appt_cb, (XtPointer) 0);
1709         XtAddCallback(c->appt_btn, XmNhelpCallback, (XtCallbackProc)help_cb, 
1710                         (XtPointer) CALENDAR_HELP_APPT_BUTTON);
1711
1712         ac=0;
1713         XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
1714         XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
1715         XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
1716         XtSetArg(al[ac], XmNleftWidget, c->appt_btn); ac++;
1717         XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
1718         XtSetArg(al[ac], XmNlabelPixmap, pu->todo_button_xbm); ac++;
1719         XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
1720         c->todo_btn = XmCreatePushButtonGadget(toolform, "todo", al, ac);
1721         XtAddCallback(c->todo_btn, XmNactivateCallback, appt_cb, (XtPointer) 2);
1722         XtAddCallback(c->todo_btn, XmNhelpCallback, (XtCallbackProc)help_cb, 
1723                         (XtPointer) CALENDAR_HELP_TODO_BUTTON);
1724
1725         ac=0;
1726         XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
1727         XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
1728         XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
1729         XtSetArg(al[ac], XmNorientation, XmHORIZONTAL); ac++;
1730         c->radio = XmCreateRadioBox(toolform, "radio", al, ac);
1731
1732         /* toolbar "scope navigation" buttons */
1733         ac=0;
1734         XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
1735         XtSetArg(al[ac], XmNlabelPixmap, pu->day_button_xbm); ac++;
1736         XtSetArg(al[ac], XmNfillOnSelect, True); ac++;
1737         XtSetArg(al[ac], XmNindicatorOn, False); ac++;
1738         XtSetArg(al[ac], XmNshadowThickness, 1); ac++;
1739         XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
1740         c->day_scope = XmCreateToggleButtonGadget(c->radio, "day", al, ac);
1741         XtAddCallback(c->day_scope, XmNvalueChangedCallback, day_button, NULL);
1742         XtAddCallback(c->day_scope, XmNhelpCallback, (XtCallbackProc)help_cb, 
1743                         (XtPointer) CALENDAR_HELP_DAY_BUTTON);
1744
1745         ac=0;
1746         XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
1747         XtSetArg(al[ac], XmNlabelPixmap, pu->week_button_xbm); ac++;
1748         XtSetArg(al[ac], XmNfillOnSelect, True); ac++;
1749         XtSetArg(al[ac], XmNindicatorOn, False); ac++;
1750         XtSetArg(al[ac], XmNshadowThickness, 1); ac++;
1751         XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
1752         c->week_scope = XmCreateToggleButtonGadget(c->radio, "week", al, ac);
1753         XtAddCallback(c->week_scope, XmNvalueChangedCallback, 
1754                                                 week_button, NULL);
1755         XtAddCallback(c->week_scope, XmNhelpCallback, (XtCallbackProc)help_cb, 
1756                         (XtPointer) CALENDAR_HELP_WEEK_BUTTON);
1757
1758         ac=0;
1759         XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
1760         XtSetArg(al[ac], XmNlabelPixmap, pu->month_button_xbm); ac++;
1761         XtSetArg(al[ac], XmNfillOnSelect, True); ac++;
1762         XtSetArg(al[ac], XmNindicatorOn, False); ac++;
1763         XtSetArg(al[ac], XmNshadowThickness, 1); ac++;
1764         XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
1765         c->month_scope = XmCreateToggleButtonGadget(c->radio, "month", al, ac);
1766         XtAddCallback(c->month_scope, XmNvalueChangedCallback, 
1767                         month_button, NULL);
1768         XtAddCallback(c->month_scope, XmNhelpCallback, (XtCallbackProc)help_cb,
1769                         (XtPointer) CALENDAR_HELP_MONTH_BUTTON);
1770
1771         ac=0;
1772         XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
1773         XtSetArg(al[ac], XmNlabelPixmap, pu->year_button_xbm); ac++;
1774         XtSetArg(al[ac], XmNfillOnSelect, True); ac++;
1775         XtSetArg(al[ac], XmNindicatorOn, False); ac++;
1776         XtSetArg(al[ac], XmNshadowThickness, 1); ac++;
1777         XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
1778         c->year_scope = XmCreateToggleButtonGadget(c->radio, "year", al, ac);
1779         XtAddCallback(c->year_scope, XmNvalueChangedCallback, 
1780                         year_button, NULL);
1781         XtAddCallback(c->year_scope, XmNhelpCallback, (XtCallbackProc)help_cb, 
1782                         (XtPointer) CALENDAR_HELP_YEAR_BUTTON);
1783
1784         ManageChildren(c->radio);
1785         ManageChildren(toolform);
1786         XtManageChild(toolform);
1787
1788 }
1789
1790 /*
1791  * Ask the server for the list of reminders
1792  */
1793 static CSA_return_code
1794 get_next_reminder(Calendar *c, time_t tick, CSA_uint32 *num_reminders, CSA_reminder_reference **reminders) {
1795         CSA_return_code stat;
1796         char    buffer[BUFSIZ];
1797
1798         _csa_tick_to_iso8601(tick, buffer);
1799
1800         stat = csa_read_next_reminder(c->my_cal_handle, 0, NULL, buffer, num_reminders, reminders, NULL);
1801
1802         return stat;
1803 }
1804
1805 static char *daystring[31] = {"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31"};
1806
1807
1808 /*
1809 **  Reset the reminders
1810 */
1811 extern void
1812 reset_alarm(Calendar *c)
1813 {
1814         if (c->view->next_alarm != NULL) {
1815                 csa_free(c->view->next_alarm);
1816                 c->view->next_alarm = NULL;
1817         }
1818         reset_timer(c);
1819 }
1820
1821 /*
1822 **  Set the timer to call the reminder_driver for the next reminder.
1823 */
1824 extern CSA_return_code
1825 reset_timer(Calendar *c) {
1826         time_t                  tick;
1827         CSA_reminder_reference  *last_r = c->view->next_alarm;
1828         CSA_return_code         stat;
1829         CSA_reminder_reference  *reminders;
1830         CSA_uint32              num_reminders;
1831         Tick                    reminder_tick;
1832
1833         /*
1834          * set the reference time to now() or the time the
1835          * last reminder is to happen whichever is earlier
1836          */
1837         tick = now();
1838         if (last_r)
1839                 _csa_iso8601_to_tick(last_r->run_time, &reminder_tick);
1840         
1841         if (last_r != NULL) {
1842                 if (tick > reminder_tick)
1843                         tick = reminder_tick;
1844
1845                 csa_free(last_r);
1846                 c->view->next_alarm = NULL;
1847         }
1848
1849         stat = get_next_reminder(c, tick, &num_reminders, &reminders);
1850         if (stat == SUCCESS && num_reminders > 0) {
1851                 if (c->view->next_alarm_id)
1852                         XtRemoveTimeOut(c->view->next_alarm_id);
1853                 c->view->next_alarm = reminders;
1854                 c->view->next_alarm_count = num_reminders;
1855                 _csa_iso8601_to_tick(reminders[0].run_time, &reminder_tick);
1856                 c->view->next_alarm_id = XtAppAddTimeOut(c->xcontext->app,
1857                         (max(reminder_tick - now(), 1) * 1000), reminder_driver, c);
1858         }
1859
1860         return stat;
1861 }
1862
1863 void
1864 center_today_button(Calendar *c)
1865 {
1866         char buf[BUFSIZ];
1867         XmString today_buf;
1868         Dimension width;
1869
1870         /*
1871          * Need to re-centre the today button, as it shrink-wraps its
1872          * label, and will now be out of position.  Unpleasant, but
1873          * necessary because XmForm doesn't provide direct means of centring.
1874          */
1875         XtVaGetValues(c->today, XmNwidth, &width, NULL);
1876         XtVaSetValues(c->today, XmNleftOffset, (int) width/-2, NULL);
1877 }
1878
1879 void
1880 move_to_new_day(XtPointer data, XtIntervalId *dummy)
1881 {
1882         Tick midnight;
1883         unsigned long tomorrow;
1884         Calendar        *c = (Calendar *) data;
1885
1886         if (c->form==NULL) return;
1887
1888         /* figure out time for next timeout invocation */
1889         midnight = next_ndays(now(), 1)+30;
1890         tomorrow = (max(midnight-now(), 1));
1891         tomorrow = tomorrow * 1000;
1892
1893         /* if date displayed is yesterday, update it to today */
1894         if (next_ndays(c->view->date, 1) == next_ndays(now()-daysec, 1)) {
1895                 c->view->olddate = c->view->date;
1896                 c->view->date = next_ndays(c->view->olddate, 1);
1897                 invalidate_cache(c);
1898                 paint_canvas(c, NULL, RENDER_UNMAP);
1899         }
1900
1901         /* update the icon */
1902         paint_icon(c);
1903
1904         /* reinstall this function as timeout handler for tomorrow */
1905         XtAppAddTimeOut(c->xcontext->app, tomorrow, move_to_new_day, c);
1906 }
1907
1908 static void
1909 setup_new_day_handler(c)
1910         Calendar *c;
1911 {
1912         Tick midnight;
1913         unsigned long next_day;
1914
1915         if (c->form==NULL) return;
1916         midnight = next_ndays(now(), 1)+30;
1917         next_day = (max(midnight-now(), 1));
1918         next_day = next_day * 1000;
1919         XtAppAddTimeOut(c->xcontext->app, next_day, move_to_new_day, c);
1920 }
1921         
1922
1923 /* ARGSUSED */
1924 /* Revisit ...
1925 static Notify_value
1926 wait3_handler(frame, pid, status, rusage)
1927         Notify_client frame;
1928         int pid;
1929         int status;
1930         struct rusage *rusage;
1931 {
1932         exit(1);
1933         return NOTIFY_DONE;
1934 }
1935 */
1936
1937 /*
1938  * Miscellaneous cleanup before the application exits.
1939  * Unregister current calendar.
1940  *
1941  * This is used as the activateCallback handler form the File->Exit
1942  * menu item, and overloaded as the handler from termination by Motif/Xt as
1943  * the XmAddWMProtocolCallback handler for delete_window.  
1944  */
1945 void
1946 quit_handler(Widget w, XtPointer cdata, XtPointer cbs) {
1947         Calendar        *c = (Calendar *)cdata;
1948
1949         if (debug)
1950           fprintf(stderr, "%s", catgets(c->DT_catd, 1, 89, "in quit_handler\n"));
1951
1952         if (editor_showing((Editor*) c->editor) ||
1953             todo_showing((ToDo*) c->todo))
1954         {
1955             if (editor_showing((Editor*) c->editor))
1956               show_editor(c, 0, 0, False);
1957             if (todo_showing((ToDo*) c->todo))
1958               show_todo(c);
1959             if (NULL != c->frame)
1960               XBell(XtDisplayOfObject(c->frame), 50);
1961             return;
1962         } 
1963
1964         if (c->view->next_alarm)
1965           csa_free(c->view->next_alarm);
1966
1967         props_clean_up((Props *)c->properties);
1968         if (c->cal_handle != c->my_cal_handle)
1969           csa_logoff(c->cal_handle, NULL);
1970         csa_logoff(c->my_cal_handle, NULL);
1971
1972         exit(0);
1973 }
1974
1975 static void
1976 sig_int_handler(
1977         int     sig)
1978 {
1979         if (!calendar) exit(1);
1980
1981         if (calendar->cal_handle != calendar->my_cal_handle)
1982                 csa_logoff(calendar->cal_handle, NULL);
1983
1984         if (calendar->my_cal_handle)
1985                 csa_logoff(calendar->my_cal_handle, NULL);
1986
1987         exit(0);
1988 }
1989
1990 static int myabort(dpy, event)
1991         Display *dpy;
1992         XErrorEvent  *event;
1993 {
1994 /*
1995 char buffer[MAXNAMELEN];
1996   char mesg[MAXNAMELEN];
1997   char number[32];
1998   char *mtype = "XlibMessage";
1999   FILE *fp = stdout;
2000
2001   XGetErrorText( dpy, event->error_code, buffer, MAXNAMELEN );
2002   XGetErrorDatabaseText( dpy, mtype, "XError", "X Error (intercepted)",
2003                          mesg, MAXNAMELEN );
2004   ( void )fprintf( fp, "%s:  %s\n  ", mesg, buffer );
2005   XGetErrorDatabaseText( dpy, mtype, "MajorCode", "Request Major code %d",
2006                          mesg, MAXNAMELEN );
2007   ( void )fprintf( fp, mesg, event->request_code );
2008   sprintf( number, "%d", event->request_code );
2009   XGetErrorDatabaseText( dpy, "XRequest", number, "", buffer, MAXNAMELEN );
2010  ( void )fprintf(fp, " (%s)", buffer );
2011   fputs("\n  ", fp );
2012   XGetErrorDatabaseText( dpy, mtype, "MinorCode", "Request Minor code",
2013                          mesg, MAXNAMELEN );
2014   ( void )fprintf( fp, mesg, event->minor_code );
2015   fputs("\n  ", fp );
2016   XGetErrorDatabaseText( dpy, mtype, "ResourceID", "ResourceID 0x%x",
2017                          mesg, MAXNAMELEN );
2018   ( void )fprintf(fp, mesg, event->resourceid );
2019   fputs("\n  ", fp );
2020   XGetErrorDatabaseText( dpy, mtype, "ErrorSerial", "Error Serial #%d",
2021                          mesg, MAXNAMELEN );
2022   ( void )fprintf( fp, mesg, event->serial );
2023    fputs("\n  ", fp );
2024   XGetErrorDatabaseText( dpy, mtype, "CurrentSerial", "Current Serial #%d",
2025                          mesg, MAXNAMELEN );
2026   ( void )fprintf( fp, mesg, NextRequest(dpy)-1 );
2027 fputs( "\n", fp );
2028         abort();
2029 */
2030 return(0);
2031 }
2032
2033 static void
2034 error_open(Calendar *c) {
2035         char            buf[MAXNAMELEN], buf2[MAXNAMELEN];
2036         char            *name, *host;
2037         Props_pu        *p = (Props_pu *)c->properties_pu;
2038
2039         char *nl_user = XtNewString(catgets(c->DT_catd, 1, 92, "User name"));
2040         char *nl_host = XtNewString(catgets(c->DT_catd, 1, 93, "Host"));
2041         char *ident = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
2042         char *title = 
2043           XtNewString(catgets(c->DT_catd, 1, 94, "Calendar : Error"));
2044
2045         name = cm_target2name(c->calname);
2046         host = cm_target2host(c->calname);
2047
2048         sprintf(buf, "%s %s", catgets(c->DT_catd, 1, 90,
2049                         "Error opening Calendar file"), c->calname);
2050         set_message(c->message_text, buf);
2051
2052         sprintf(buf, "%s\n%s: %s, %s: %s", catgets(c->DT_catd, 1, 91,
2053                                                 "rpc.cmsd is not responding for your user name.\nMake sure the inetd process is running and the entry\nin inetd.conf for rpc.cmsd is correct for your host."),
2054                 nl_user, name,
2055                 nl_host, host);
2056
2057         dialog_popup(c->frame,
2058                 DIALOG_TITLE, title,
2059                 DIALOG_TEXT, buf,
2060                 BUTTON_IDENT, 1, ident,
2061                 BUTTON_HELP, CMSD_ERROR_HELP,
2062                 DIALOG_IMAGE, p->xm_error_pixmap,
2063                 NULL);
2064
2065         XtFree(title);
2066         XtFree(ident);
2067         XtFree(nl_host);
2068         XtFree(nl_user);
2069
2070         free(name);
2071         free(host);
2072 }
2073
2074 static void
2075 error_noloc(Calendar *c, char *name) 
2076 {
2077         char            buf[BUFSIZ];
2078         Props_pu        *p = (Props_pu *)c->properties_pu;
2079
2080         char *ident = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
2081         char *title = 
2082           XtNewString(catgets(c->DT_catd, 1, 94, "Calendar : Error"));
2083
2084         sprintf(buf, "%s %s",
2085                 catgets(c->DT_catd, 1, 108, "No Calendar Location specified for"),
2086                 name);
2087         set_message(c->message_text, buf);
2088
2089         sprintf(buf, "%s", catgets(c->DT_catd, 1, 109, "No location specified; add a hostname to the\nInitial Calendar View in Properties/Display Settings.  If\nyou ran Calendar (dtcm) with the -c option, verify you specified a hostname."));
2090         dialog_popup(c->frame,
2091                 DIALOG_TITLE, title,
2092                 DIALOG_TEXT, buf,
2093                 BUTTON_IDENT, 1, ident,
2094                 BUTTON_HELP, CAL_LOCATION_ERROR_HELP,
2095                 DIALOG_IMAGE, p->xm_error_pixmap,
2096                 NULL);
2097         XtFree(title);
2098         XtFree(ident);
2099 }
2100
2101 /*
2102  * this routine is used to logon to user's own calendar.
2103  * If the calendar does not exist, it will create it and logon to it.
2104  * It then registers callback for updates.
2105  * If it fails to logon due to server timeout and retry is True,
2106  * it will set a timer to retry.
2107  */
2108 static Boolean
2109 open_user_calendar(Calendar *c, Boolean retry)
2110 {
2111         char            buf[MAXNAMELEN], *loc, *user;
2112         CSA_return_code status;
2113         CSA_calendar_user csa_user;
2114         CSA_flags       flags;
2115         CSA_extension   cb_ext;
2116         CSA_extension   logon_ext;
2117         CSA_attribute   attr;
2118         CSA_attribute_value val;
2119         Boolean         viewother;
2120
2121         c->general->version = 0;
2122         if ((loc = cm_target2location(c->calname)) == NULL) {
2123                 error_noloc(c, c->calname);
2124                 return False;
2125         }
2126         if ((user = cm_target2name(c->calname)) == NULL) {
2127                 error_noloc(c, c->calname);
2128                 free(loc);
2129                 return False;
2130         }
2131
2132 #ifdef FNS
2133         if (cmfns_use_fns((Props *)c->properties)) {
2134                 cm_register_calendar(c->calname, loc);
2135         }
2136 #endif
2137
2138         csa_user.user_name = c->calname;
2139         csa_user.user_type = 0;
2140         csa_user.calendar_user_extensions = NULL;
2141         csa_user.calendar_address = c->calname;
2142
2143         logon_ext.item_code = CSA_X_DT_GET_USER_ACCESS_EXT;
2144         logon_ext.item_data = 0;
2145         logon_ext.item_reference = NULL;
2146         logon_ext.extension_flags = CSA_EXT_LAST_ELEMENT;
2147
2148         status = csa_logon(NULL, &csa_user, NULL, NULL, NULL,
2149                         &c->my_cal_handle, &logon_ext);
2150
2151         if (status == CSA_E_CALENDAR_NOT_EXIST) {
2152                 /* get common locale/charset name */
2153                 attr.name = CSA_CAL_ATTR_CHARACTER_SET;
2154                 attr.value = &val;
2155                 attr.attribute_extensions = NULL;
2156                 val.type = CSA_VALUE_STRING;
2157                 val.item.string_value = NULL;
2158                 _DtI18NXlateOpToStdLocale(DtLCX_OPER_SETLOCALE,
2159                         setlocale(LC_CTYPE, NULL), &val.item.string_value,
2160                         NULL, NULL);
2161
2162                 /* create the calendar */
2163                 if ((status = csa_add_calendar(NULL, &csa_user, 1, &attr, NULL))
2164                     == CSA_E_UNSUPPORTED_ATTRIBUTE) {
2165                         /* server with version 4 or less does not support
2166                          * the CSA_CAL_ATTR_CHARACTER_SET cal attribute
2167                          */
2168                         status = csa_add_calendar(NULL, &csa_user, 0, NULL,
2169                                         NULL);
2170                 }
2171                 if (val.item.string_value) free(val.item.string_value);
2172
2173                 if (status == CSA_SUCCESS)
2174                         status = csa_logon(NULL, &csa_user, NULL, NULL, NULL,
2175                                         &c->my_cal_handle, &logon_ext);
2176         }
2177
2178         free(loc);
2179         free(user);
2180
2181         viewother = strcmp(c->calname, c->view->current_calendar);
2182
2183         if (status != CSA_SUCCESS) {
2184                 if (status == CSA_X_DT_E_SERVER_TIMEOUT && retry) {
2185                         XtAppAddTimeOut(c->xcontext->app,
2186                                 (viewother ? 15*1000 : 0), logon_retry, c);
2187                         return False;
2188                 } else {
2189                         error_open(c);
2190                         return False;
2191                 }
2192         } else
2193                 c->my_access = logon_ext.item_data;
2194
2195         c->my_cal_version = get_data_version(c->my_cal_handle);
2196
2197         flags = CSA_CB_ENTRY_ADDED | CSA_CB_ENTRY_DELETED |
2198                 CSA_CB_ENTRY_UPDATED;
2199         cb_ext.item_code = CSA_X_XT_APP_CONTEXT_EXT;
2200         cb_ext.item_data = (CSA_uint32)c->xcontext->app;
2201         cb_ext.extension_flags = CSA_EXT_LAST_ELEMENT;
2202         csa_register_callback(c->my_cal_handle, flags, update_handler,
2203                         NULL, &cb_ext);
2204
2205         if (c->my_cal_version < DTCM_DATA_VER)
2206                 set_message(c->message_text, catgets(c->DT_catd, 1, 186,
2207                        "Calendar (dtcm) and rpc.cmsd versions are different."));
2208
2209         if (!viewother) {
2210                 /* NL_COMMENT
2211
2212                    Message 113 : ``Calendar'' is used in the main titlebar 
2213                    of the tool: Calendar : user@host.
2214                  */
2215                 sprintf(buf, "%s : %s", catgets(c->DT_catd, 1, 113, "Calendar"),
2216                                         c->calname);
2217                 XtVaSetValues(c->frame, XmNtitle, buf, NULL);
2218         }
2219
2220         return True;
2221 }
2222
2223 static Boolean
2224 open_initial_calendar(
2225         Calendar        *c,
2226         CSA_return_code *status)
2227 {
2228         char            buf[MAXNAMELEN], *loc, *user;
2229         CSA_flags       flags = NULL;
2230         CSA_extension   cb_ext;
2231         CSA_extension   logon_ext;
2232         CSA_calendar_user csa_user;
2233
2234         if ((user = cm_target2name(c->view->current_calendar)) == NULL) {
2235                 error_noloc(c, c->view->current_calendar);
2236                 return False;
2237         }
2238
2239         if ((loc = cm_target2location(c->view->current_calendar)) == NULL) {
2240                 error_noloc(c, c->view->current_calendar);
2241                 return False;
2242         }
2243
2244         csa_user.user_name = c->view->current_calendar;
2245         csa_user.user_type = 0;
2246         csa_user.calendar_user_extensions = NULL;
2247         csa_user.calendar_address = c->view->current_calendar;
2248
2249         logon_ext.item_code = CSA_X_DT_GET_USER_ACCESS_EXT;
2250         logon_ext.item_data = 0;
2251         logon_ext.item_reference = NULL;
2252         logon_ext.extension_flags = CSA_EXT_LAST_ELEMENT;
2253
2254         *status = csa_logon(NULL, &csa_user, NULL, NULL, NULL, &c->cal_handle,
2255                         &logon_ext);
2256         free(loc);
2257         free(user);
2258         if (*status != CSA_SUCCESS)
2259                 return False; 
2260         else
2261                 c->user_access = logon_ext.item_data;
2262
2263         /*
2264          * Get the version number of the new calendar
2265          */
2266
2267         c->general->version = get_data_version(c->cal_handle);
2268
2269         if (c->general->version < DTCM_DATA_VER)
2270                 set_message(c->message_text, catgets(c->DT_catd, 1, 186,
2271                        "Calendar (dtcm) and rpc.cmsd versions are different."));
2272
2273
2274         flags = CSA_CB_ENTRY_ADDED | CSA_CB_ENTRY_DELETED |
2275                 CSA_CB_ENTRY_UPDATED;
2276         cb_ext.item_code = CSA_X_XT_APP_CONTEXT_EXT;
2277         cb_ext.item_data = (CSA_uint32)c->xcontext->app;
2278         cb_ext.extension_flags = CSA_EXT_LAST_ELEMENT;
2279         csa_register_callback(c->cal_handle, flags,
2280                         update_handler, NULL, &cb_ext);
2281
2282         sprintf(buf, "%s : %s", catgets(c->DT_catd, 1, 113, "Calendar"),
2283                                         c->view->current_calendar);
2284         XtVaSetValues(c->frame, XmNtitle, buf, NULL);
2285
2286         return True;
2287 }
2288
2289 /*
2290  * try to logon to user's own calendar
2291  */
2292 static void
2293 logon_retry(XtPointer data, XtIntervalId *dummy)
2294 {
2295         Calendar        *c = (Calendar *)data;
2296         /* retry once */
2297         if (c->my_cal_handle == NULL && (open_user_calendar(c, False) == True))
2298         {
2299                 _DtTurnOnHourGlass(c->frame);
2300                 reset_timer(c);
2301                 if (!strcmp(c->calname, c->view->current_calendar)) {
2302                         c->cal_handle = c->my_cal_handle;
2303                         c->user_access = c->my_access;
2304                         c->general->version = c->my_cal_version;
2305                         invalidate_cache(c);
2306                         paint_canvas((Calendar *)data, NULL, RENDER_UNMAP);
2307                 }
2308                 _DtTurnOffHourGlass(c->frame);
2309         }
2310 }
2311
2312 static void
2313 view_event(Widget w, XtPointer client_data, XtPointer cbs)
2314 {
2315         Calendar *c = calendar;
2316         XEvent  *event = (XEvent *) client_data;
2317
2318         if (event == NULL)
2319                 return;
2320         if (c->view->glance == monthGlance)
2321                 month_event(event);
2322         else if (c->view->glance == weekGlance)
2323                 week_event(event);
2324         else if (c->view->glance == dayGlance)
2325                 day_event(event);
2326 /* REVISIT - dac
2327         else if (c->view->glance == yearGlance)
2328                 year_event(event);
2329 */
2330 }
2331
2332 static void
2333 cm_usage()
2334 {
2335         (void)fprintf(stderr, "Usage: dtcm [ -c calendar ] [-v view ]");
2336         (void)fprintf(stderr, " [ -p printer ] [ generic-tool-arguments ]\n" );
2337         if (child != 0)
2338                 (void)kill(child, SIGKILL);
2339         exit(1);
2340 }
2341
2342 /*
2343  * Calculation of default calendar name for the application
2344  * Must return srting value in val_ret->addr
2345  * Invoked by the XtRCallProc resource initialization mechanism.
2346  */
2347 static void
2348 def_cal(Widget w, int offset, XrmValue *val_ret)
2349 {
2350         val_ret->addr = cm_strdup(get_char_prop((Props *)calendar->properties, 
2351                                                                 CP_DEFAULTCAL));
2352 }
2353
2354 static void
2355 def_view(Widget w, int offset, XrmValue *val_ret)
2356 {
2357         ViewType value_p;
2358
2359         value_p = get_int_prop((Props *)calendar->properties, CP_DEFAULTVIEW);
2360         switch (value_p) {
2361                 case YEAR_VIEW:
2362                         val_ret->addr = cm_strdup("year");
2363                         break;
2364                 case MONTH_VIEW:
2365                         val_ret->addr = cm_strdup("month");
2366                         break;
2367                 case WEEK_VIEW:
2368                         val_ret->addr = cm_strdup("week");
2369                         break;
2370                 case DAY_VIEW:
2371                         val_ret->addr = cm_strdup("day");
2372                         break;
2373         }
2374 }
2375
2376 /*
2377  * Command line options definition
2378  */
2379 static XrmOptionDescRec options[] = {
2380         { "-v", "__defaultView", XrmoptionSepArg, NULL },
2381         { "-c", "__defaultCalendar", XrmoptionSepArg, NULL },
2382         { "-p", "__defaultPrinter", XrmoptionSepArg, NULL },
2383         { "-trace", "__trace", XrmoptionNoArg, (caddr_t)"FALSE" },
2384         { "-session", "__session", XrmoptionSepArg, NULL }
2385 };
2386
2387 /*
2388  * Application-defined resources
2389  */
2390 static XtResource resources[] = {
2391 /* initial view */
2392         { "__defaultView", "__DefaultView", XtRString, sizeof(String),
2393         XtOffset(DtCmAppResourcesPtr, default_view), XtRCallProc, 
2394         (XtPointer)def_view},
2395 /* default calendar */
2396         { "__defaultCalendar", "__DefaultCalendar", XtRString, sizeof(String),
2397         XtOffset(DtCmAppResourcesPtr, default_calendar), XtRCallProc,
2398         (XtPointer)def_cal},
2399 /* default printer */
2400         { "__defaultPrinter", "__DefaultPrinter", XtRString, sizeof(String),
2401         XtOffset(DtCmAppResourcesPtr, default_printer), XtRString,
2402         (XtPointer)NULL},
2403 /* label font */
2404         { "labelFont", "LabelFont", XmRFontList, sizeof(XmFontList),
2405         XtOffset(DtCmAppResourcesPtr, labelfontlist), XtRString,
2406         NULL},
2407         { "labelFont", "LabelFont", XtRString, sizeof(String),
2408         XtOffset(DtCmAppResourcesPtr, labelfont), XtRString,
2409         NULL},
2410 /* view font */
2411         { "viewFont", "ViewFont", XmRFontList, sizeof(XmFontList),
2412         XtOffset(DtCmAppResourcesPtr, viewfontlist), XtRString,
2413         NULL},
2414 /* user font (backup for view font */
2415         { "userFont", "UserFont", XtRString, sizeof(String),
2416         XtOffset(DtCmAppResourcesPtr, userfont), XtRString,
2417         "-b&h-lucidatypewriter-medium-r-*-sans-*-120-*-*-*-*-*-*:"},
2418         { "userFont", "UserFont", XmRFontList, sizeof(XmFontList),
2419         XtOffset(DtCmAppResourcesPtr, userfontlist), XtRString,
2420         "-b&h-lucidatypewriter-medium-r-*-sans-*-120-*-*-*-*-*-*:"},
2421 /* system font (backup for label font */
2422         { "systemFont", "SystemFont", XmRFontList, sizeof(XmFontList),
2423         XtOffset(DtCmAppResourcesPtr, systemfontlist), XtRString,
2424         "-b&h-lucida-medium-r-*-sans-*-120-*-*-*-*-*-*:"},
2425         { "systemFont", "SystemFont", XtRString, sizeof(String),
2426         XtOffset(DtCmAppResourcesPtr, systemfont), XtRString,
2427         "-b&h-lucida-medium-r-*-sans-*-120-*-*-*-*-*-*:"},
2428 /* bold font */
2429         { "boldFont", "BoldFont", XmRFontList, sizeof(XmFontList),
2430         XtOffset(DtCmAppResourcesPtr, boldfontlist), XtRString,
2431         NULL},
2432 /* font for icon */
2433         { "iconFont", "IconFont", XmRFontList, sizeof(XmFontList), 
2434         XtOffset(DtCmAppResourcesPtr, iconfontlist), XtRString, 
2435         NULL}, 
2436 /* application font family */
2437         { "applicationFontFamily", "ApplicationFontFamily", XtRString, 
2438         sizeof(XmString), XtOffset(DtCmAppResourcesPtr, app_font_family), 
2439         XtRString, "application"},
2440 /* Session file from -session option */
2441         { "__session", "__Session", XtRString, 
2442         sizeof(XmString), XtOffset(DtCmAppResourcesPtr, session_file), 
2443         XtRString, NULL},
2444 /* trace flag */
2445         { "__trace", "__trace", XtRBoolean, 
2446         sizeof(Boolean), XtOffset(DtCmAppResourcesPtr, debug), 
2447         XtRBoolean, FALSE},
2448 };
2449
2450 /*
2451  * This routine returns the user's calendar in the format, user@location.
2452  * "user" is the user's login name.  If the calendar location is not
2453  * specified in the "user calendar location" option, "location" defaults
2454  * to the local host.
2455  */
2456 char *
2457 get_user_calendar()
2458 {
2459         char    *name, *uname, *loc;
2460         Boolean needfree = False;
2461
2462         uname = cm_get_uname();
2463         if ((loc = get_char_prop((Props *)calendar->properties, CP_CALLOC)) &&
2464             *loc != NULL) {
2465                 loc = strdup(loc);
2466                 needfree = True;
2467         } else
2468                 loc = cm_get_local_host();
2469
2470         name = malloc(strlen(uname) + strlen(loc) + 2);
2471         sprintf(name, "%s@%s", uname, loc);
2472
2473         if (needfree) free(loc);
2474
2475         return (name);
2476 }
2477
2478 static void
2479 init_calendar(argc, argv)
2480         int argc; char **argv;
2481 {
2482         int start, stop;
2483         register int i;
2484         register char *s_ptr, *d_ptr;
2485         Props *p;
2486         Tick today;
2487         char bind_home[MAXPATHLEN];
2488         XRectangle clip;
2489         Dimension w, h, label_width;
2490         String translations =
2491                 "<Btn1Down>: view_event()               \n\
2492                 <Btn1Motion>: view_event()";
2493         static XtActionsRec action_table[] = {
2494                 {(String) "view_event", (XtActionProc) view_event},
2495                 {(String) "TranslationDragStart", 
2496                    TranslationDragStart},
2497                 {"dtcm-process-press",
2498                    DtcmProcessPress}
2499         };
2500         DtCmAppResources app_data;
2501         Atom xa_WM_SAVE_YOURSELF;
2502         unsigned long valuemask;
2503         XSetWindowAttributes attrs;
2504         Arg al[20];
2505         int ac=0;
2506         Tt_status status;
2507
2508         init_time();
2509         today = now();
2510         calendar = (Calendar*) ckalloc(sizeof(Calendar));
2511         calendar->view = (View*) ckalloc(sizeof(View));
2512         calendar->general = (General*) ckalloc(sizeof(General));
2513         calendar->view->nwks = numwks(today);
2514         calendar->app_data = (DtCmAppResourcesPtr)
2515                 ckalloc(sizeof(DtCmAppResources));
2516         calendar->editor = (caddr_t)ckalloc(sizeof(Editor));
2517         calendar->geditor = (caddr_t)ckalloc(sizeof(GEditor));
2518         calendar->todo = (caddr_t)ckalloc(sizeof(ToDo));
2519         calendar->browselist = (caddr_t)ckalloc(sizeof(Browselist));
2520         calendar->fonts = (Cal_Fonts *) ckalloc(sizeof(Cal_Fonts));
2521         calendar->fonts->labelfont = (Cal_Font *) ckalloc(sizeof(Cal_Font));
2522         calendar->fonts->viewfont = (Cal_Font *) ckalloc(sizeof(Cal_Font));
2523         calendar->fonts->boldfont = (Cal_Font *) ckalloc(sizeof(Cal_Font));
2524         calendar->fonts->iconfont = (Cal_Font *) ckalloc(sizeof(Cal_Font));
2525         calendar->fonts->userfont = (Cal_Font *) ckalloc(sizeof(Cal_Font));
2526
2527         /*
2528          * Save the argv list into a WM_COMMAND format string for
2529          * later use when the application is asked to save itself.  
2530          * The format is a buffer with a series of null terminated 
2531          * strings within it, one for each string in the argv list.  
2532          * Thus the total length is that of the arguments plus a null 
2533          * byte for each argument.
2534          */
2535         for (i = 0, calendar->view->wm_cmdstrlen = 0; i < argc; i++) {
2536                 /* Do not record the -session option as we add that
2537                  * automatically when we save the session.
2538                  */
2539                 if (!strcmp("-session", argv[i])) {
2540                         i++;
2541                         continue;
2542                 }
2543                 calendar->view->wm_cmdstrlen += strlen(argv[i]) + 1;
2544         }
2545
2546         d_ptr = calendar->view->wm_cmdstr =
2547                                         malloc(calendar->view->wm_cmdstrlen);
2548         for (i = 0; i < argc; i++)
2549         {
2550                 char *s_ptr = argv[i];
2551
2552                 /* Do not record the -session option as we add that
2553                  * automatically when we save the session.
2554                  */
2555                 if (!strcmp("-session", argv[i])) {
2556                         i++;
2557                         continue;
2558                 }
2559                 
2560                 while (*s_ptr)
2561                         *d_ptr++ = *s_ptr++;
2562                 *d_ptr++ = NULL;
2563         }
2564         d_ptr = NULL;
2565
2566         p = (Props *)ckalloc(sizeof(Props));
2567         calendar->properties = (caddr_t)p;
2568         calendar->properties_pu = (caddr_t) ckalloc(sizeof(Props_pu));
2569         calendar->items = (Items *) ckalloc(sizeof(Items));
2570         read_props(p);
2571         cal_convert_cmrc(p);
2572         if ((start = get_int_prop(p, CP_DAYBEGIN)) < 0)
2573                 start = 0;
2574         else if (start > 23)
2575                 start = 23;
2576         if ((stop = get_int_prop(p, CP_DAYEND)) <= start)
2577                 stop = start + 1;
2578         else if (stop > 24)
2579                 stop = 24;
2580         set_int_prop(p, CP_DAYBEGIN, start);
2581         set_int_prop(p, CP_DAYEND, stop);
2582
2583         calendar->frame = XtVaAppInitialize(&app, "Dtcm",
2584                                 options, XtNumber(options), &argc, argv,
2585                                 fallback_resources,
2586                                 XmNwidth, 650, XmNheight, 730, 
2587                                 XmNmappedWhenManaged, False,
2588                                 NULL);
2589
2590         if (argc > 1)
2591                 cm_usage();
2592
2593         dpy = XtDisplayOfObject(calendar->frame); 
2594
2595         /*
2596          * Initialize DtSvc for drag and drop stuff
2597          */
2598         DtInitialize(dpy, calendar->frame, argv[0], "Dtcm");
2599
2600         /*
2601          * Add X error handler to handle BadAlloc errors on the print server.
2602          */
2603         oldXErrorHandler = XSetErrorHandler(newXErrorHandler);
2604
2605         /*
2606          * Load the application resources and set the quit handler for the main
2607          * frame.
2608          */
2609         XtGetApplicationResources(calendar->frame, calendar->app_data,
2610                 resources, XtNumber(resources), NULL, 0);
2611
2612         /* Handle the -session option */
2613         if (calendar->app_data->session_file)
2614                 GetSessionInfo(calendar);
2615
2616         if (!init_fonts(calendar)) {
2617                 fprintf (stderr, "%s: Failed to find required fonts ", argv[0]);
2618                 fprintf (stderr, "(``fixed'' and ``variable'')...exiting.\n"); 
2619                 exit(-1);
2620         }
2621
2622         setup_quit_handler(calendar->frame, quit_handler, (caddr_t)calendar);
2623
2624         /*
2625          * Setup the handlers for the saving of session information
2626          */
2627         xa_WM_SAVE_YOURSELF = XInternAtom(dpy, "WM_SAVE_YOURSELF", False);
2628         XmAddWMProtocolCallback(calendar->frame, xa_WM_SAVE_YOURSELF,
2629                                 CMSaveSessionCB, NULL);
2630
2631         /*
2632          * Must call this to cause Motif to recognise tear_off_enabled in a
2633          * resource file.  Mmm... :-)
2634          */
2635         XmRepTypeInstallTearOffModelConverter();
2636
2637         calendar->view->date = today;
2638         calendar->view->outside_margin = VIEWMARGIN;
2639         calendar->view->current_selection = (caddr_t)ckalloc(sizeof(Selection));
2640         calendar->user = cm_get_credentials();
2641
2642 #if 0   /* use this when we go with mapped names */
2643         cm_get_yptarget(cm_get_uname(), &calendar->calname);
2644         if (calendar->calname == NULL) 
2645                 /* No mapping in NIS+ db */
2646                 calendar->calname = cm_get_deftarget();
2647 #endif
2648
2649         calendar->calname = get_user_calendar();
2650         calendar->view->current_calendar =
2651                 cm_strdup(calendar->app_data->default_calendar);
2652
2653         /* Open the message catalog for internationalization */
2654         calendar->DT_catd = catopen(DTCM_CAT, NL_CAT_LOCALE);
2655
2656         ac=0;
2657         XtSetArg(al[ac], XmNfractionBase, 100); ac++;
2658         XtSetArg(al[ac], XmNmarginWidth, 0); ac++;
2659         calendar->form = XmCreateForm(calendar->frame, "form", al, ac);
2660
2661         make_menus(calendar);
2662         create_all_pixmaps((Props_pu *)calendar->properties_pu,
2663                            calendar->menu_bar);
2664         make_buttons(calendar);
2665
2666         ac=0;
2667         XtSetArg(al[ac], XmNtranslations, 
2668                         XtParseTranslationTable(translations)); ac++;
2669         XtSetArg(al[ac], XmNresizePolicy, XmRESIZE_ANY); ac++;
2670         XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
2671         XtSetArg(al[ac], XmNtopWidget, calendar->previous); ac++;
2672         XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
2673         XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
2674         XtSetArg(al[ac], XmNleftOffset, 1); ac++;
2675         calendar->canvas = XmCreateDrawingArea(calendar->form, "canvas",
2676                                 al, ac);
2677         XtAddCallback(calendar->canvas, XmNhelpCallback, 
2678                                         (XtCallbackProc)help_view_cb, NULL);
2679         ac=0;
2680         XtSetArg(al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
2681         XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
2682         XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
2683         XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
2684         XtSetArg(al[ac], XmNmarginHeight, 0); ac++;
2685         calendar->message_text = XmCreateLabelGadget(calendar->form, "message",
2686                                                      al, ac);
2687         set_message(calendar->message_text, " ");
2688
2689         XtVaSetValues(calendar->canvas,
2690                         XmNbottomAttachment, XmATTACH_WIDGET,
2691                         XmNbottomWidget, calendar->message_text,
2692                         NULL);
2693
2694         XtAppAddActions(app, (XtActionList) &action_table,
2695                         XtNumber(action_table));
2696
2697         ManageChildren(calendar->form);
2698         XtManageChild(calendar->form);
2699
2700 /*
2701  * Enforce a "reasonable" size.  Things are unreadable and ugly any
2702  * smaller than 400x400, including the grids.  (The text will likely
2703  * be unreadable even at this size, but it's all a matter of giving
2704  * enough rope.  No particular reason for the numbers used for maximums.
2705  */
2706         XtRealizeWidget(calendar->frame);
2707
2708         XtVaGetValues(calendar->frame, XmNwidth, &w, XmNheight, &h, NULL);
2709         XtVaSetValues(calendar->frame,
2710                 XmNminWidth, min(400,w),
2711                 XmNminHeight, min(450,h),
2712                 NULL);
2713
2714         XtMapWidget(calendar->frame);
2715
2716         XtAddCallback(calendar->canvas, XmNresizeCallback, resize_proc, NULL);
2717         XtAddCallback(calendar->canvas, XmNinputCallback, view_event, NULL);
2718         XtAddCallback(calendar->canvas, XmNexposeCallback, repaint_proc, NULL);
2719
2720         cm_register_drop_site(calendar, calendar->form);
2721
2722         calendar->xcontext = gr_create_xcontext(calendar, calendar->canvas,
2723                                                 gr_color, app);
2724
2725         gr_init(calendar->xcontext, calendar->canvas);
2726         set_default_view(calendar);
2727
2728         init_strings();   /* strings in timeops.c */
2729
2730         calendar->view->day_info = (caddr_t) ckalloc(sizeof(Day));
2731         init_mo(calendar);
2732
2733 #ifdef FNS
2734         /* Initialized FNS */
2735         dtfns_init();
2736 #endif
2737
2738         status = cmtt_init("Calendar", calendar, app, calendar->frame);
2739         if (TT_OK != status) {
2740             char *errfmt;
2741             errfmt = catgets(calendar->DT_catd, 2, 2,
2742                         "Could not connect to ToolTalk:\n%s\n");
2743             DieFromToolTalkError( calendar, errfmt, status );
2744         }
2745
2746         /* 
2747          * This needs to be done before we open the calendar because
2748          * if we fail to open the calendar an error dialog is displayed.
2749          * This causes the main canvas to be painted but this doesn't
2750          * happen correctly if we haven't cached the diminsions.
2751          */
2752         XtVaGetValues(calendar->canvas, XmNwidth, &w, XmNheight, &h, NULL);
2753         cache_dims(calendar, w, h);
2754
2755         /* 
2756          * Paint the icon before we log into the calendar to avoid the
2757          * user seeing the default icon while the logon process is
2758          * occurring.
2759          */
2760         paint_icon(calendar);
2761
2762         /*
2763          * set version of cms and register client
2764          */
2765         _DtTurnOnHourGlass(calendar->frame);
2766
2767         if (open_user_calendar(calendar, True) == True)
2768                 reset_timer(calendar);
2769
2770         if (strcmp(calendar->calname, calendar->view->current_calendar)) {
2771                 CSA_return_code         status = CSA_SUCCESS;
2772
2773                 if (open_initial_calendar(calendar, &status) == False) {
2774                         /* failed to logon to the initial calendar,
2775                          * display user's own calendar instead
2776                          */
2777                         free(calendar->view->current_calendar);
2778                         calendar->view->current_calendar =
2779                                 cm_strdup(calendar->calname);
2780
2781                         if (calendar->my_cal_handle) {
2782                                 char    buf[MAXNAMELEN];
2783
2784                                 calendar->cal_handle = calendar->my_cal_handle;
2785                                 calendar->user_access = calendar->my_access;
2786                                 calendar->general->version =
2787                                         calendar->my_cal_version;
2788                                 sprintf(buf, "%s : %s", 
2789                                         catgets(calendar->DT_catd, 1, 113, 
2790                                                                 "Calendar"),
2791                                         calendar->calname);
2792                                 XtVaSetValues(calendar->frame, XmNtitle, buf,
2793                                         NULL);
2794                         }
2795                         backend_err_msg(calendar->frame, 
2796                                 calendar->view->current_calendar, status,
2797                                 ((Props_pu *) 
2798                                      calendar->properties_pu)->xm_error_pixmap);
2799                 }
2800         } else {
2801                 calendar->cal_handle = calendar->my_cal_handle;
2802                 calendar->user_access = calendar->my_access;
2803                 calendar->general->version = calendar->my_cal_version;
2804         }
2805
2806         signal(SIGINT, sig_int_handler);
2807
2808         /* A cache will be allocated if error dialog has been displayed
2809          * this call is to clear the cache so that the main view
2810          * can be properly updated
2811          */
2812         invalidate_cache(calendar);
2813
2814         _DtTurnOffHourGlass(calendar->frame);
2815
2816         setup_new_day_handler(calendar);
2817         center_today_button(calendar);
2818
2819         /* Twiddle controls for old versions */
2820
2821         if (calendar->general->version && calendar->general->version < DATAVER2)
2822         {
2823                 if (todo_showing((ToDo *)calendar->todo))
2824                         XtPopdown(((ToDo *)calendar->todo)->frame);
2825                 XtUnmanageChild(calendar->todo_btn);
2826                 XtSetSensitive(calendar->todo_edit_menu, False);
2827                 XtSetSensitive(calendar->todo_view_menu, False);
2828         }
2829         else {
2830                 XtManageChild(calendar->todo_btn);
2831                 XtSetSensitive(calendar->todo_edit_menu, True);
2832                 XtSetSensitive(calendar->todo_view_menu, True);
2833         }
2834 }
2835
2836 #ifdef __osf__
2837 extern void
2838 sigchld_handler(int signo)      /* Do not use the arg signo at the moment */
2839 {
2840         pid_t   pid;
2841         int     stat_loc;
2842
2843         pid = waitpid(-1, &stat_loc, WNOHANG);
2844         /* Child exit handling code follows, if any */
2845 }
2846 #endif /* __osf__ */
2847
2848 static int
2849 newXErrorHandler(Display *dsp, XErrorEvent *event)
2850 {
2851     if ((event->error_code == BadAlloc) &&
2852         (dsp == pd_get_print_display(calendar)))
2853     {
2854         pd_set_bad_alloc_error(calendar, True);
2855         return 0;
2856     }
2857
2858     return (*oldXErrorHandler)(dsp, event);
2859 }
2860
2861 int
2862 main(int argc, char **argv) {
2863 /* Handle SIGCHLD for dtcm */
2864
2865         struct sigaction sa, osa;
2866
2867 #ifdef __osf__
2868         sa.sa_handler = sigchld_handler;
2869         sa.sa_flags   =  0;
2870 #else
2871         sa.sa_handler = SIG_IGN;
2872 # ifdef SA_NOCLDWAIT
2873         sa.sa_flags   =  SA_NOCLDWAIT;
2874 # else
2875         sa.sa_flags   =  0;
2876 # endif
2877 #endif
2878         sigemptyset(&sa.sa_mask);
2879
2880         sigaction(SIGCHLD, &sa, &osa);
2881
2882         XtSetLanguageProc(NULL, NULL, NULL);
2883         _DtEnvControl(DT_ENV_SET); /* set up environment variables */
2884
2885         init_calendar(argc, argv);
2886
2887         XtAppMainLoop (app);
2888
2889         exit(0);
2890
2891         return(0);
2892 }
2893
2894 extern CSA_return_code
2895 paint_canvas(
2896         Calendar        *c, 
2897         XRectangle      *rect,
2898         Render_Type      render_type)
2899 {
2900 /* REPAINT, CLEAR_FIRST, UNMAP */ 
2901         Glance glance = c->view->glance;
2902         CSA_return_code stat = CSA_SUCCESS;
2903
2904         switch(glance) {
2905         case monthGlance:
2906                 switch (render_type) {
2907                 case RENDER_REPAINT:
2908                         repaint_damaged_month(c, rect);
2909                         break;
2910                 case RENDER_CLEAR_FIRST:
2911                         gr_clear_area(c->xcontext, 0, 0, 
2912                                       c->view->winw, c->view->winh);
2913                         repaint_damaged_month(c, rect);
2914                         break;
2915                 case RENDER_UNMAP:
2916                         XtUnmapWidget(c->canvas);
2917                         prepare_to_paint_monthview(c, rect);
2918                         XtMapWidget(c->canvas);
2919                         break;
2920                 }
2921                 break;
2922         case yearGlance:
2923                 stat = paint_year(c);
2924                 break;
2925         case weekGlance:
2926                 paint_weekview(c, rect);
2927                 break;
2928         case dayGlance:
2929                 paint_day(c);
2930                 break;
2931         default:
2932                 stat = CSA_SUCCESS;
2933                 paint_grid(c, rect);
2934                 break;
2935         }
2936         return stat;
2937 }
2938
2939 #ifdef notdef
2940 extern char*
2941 cm_get_relname()
2942 {
2943         char s[BUFSIZ];
2944         static char *CM_name;
2945
2946         /* we now make a composite name for the tool, combining
2947          * "Calendar Manager" with a release identifier
2948          */
2949         if (CM_name == NULL) {
2950                 sprintf(s, "%s", catgets(calendar->DT_catd, 1, 113, "Calendar"));
2951                 CM_name = (char*)ckalloc(cm_strlen(s) + 2);
2952          
2953                 sprintf(CM_name, "%s", s);
2954         }
2955  
2956         return (char*)CM_name;
2957 }
2958 #endif 
2959
2960 extern Boolean
2961 in_range(time_t start, time_t stop, time_t tick) {
2962         if (tick >= start && tick <= stop)
2963                 return True;
2964         return False;
2965 }
2966
2967 extern Boolean
2968 today_inrange(Calendar *c, time_t day_in_range) {
2969         time_t  start, stop;
2970         Boolean inrange = False;
2971
2972         /* is today in range of current view? */
2973         get_range(c->view->glance, day_in_range, &start, &stop);
2974         inrange = in_range(start, stop, time(0));
2975         return inrange;
2976 }
2977 void
2978 init_strings()
2979 {
2980         char *display_lang="C";
2981
2982         months[1] = strdup(catgets(calendar->DT_catd, 1, 114, "January"));
2983         months[2] = strdup(catgets(calendar->DT_catd, 1, 115, "February"));
2984         months[3] = strdup(catgets(calendar->DT_catd, 1, 116, "March"));
2985         months[4] = strdup(catgets(calendar->DT_catd, 1, 117, "April"));
2986         months[5] = strdup(catgets(calendar->DT_catd, 1, 118, "May"));
2987         months[6] = strdup(catgets(calendar->DT_catd, 1, 119, "June"));
2988         months[7] = strdup(catgets(calendar->DT_catd, 1, 120, "July"));
2989         months[8] = strdup(catgets(calendar->DT_catd, 1, 121, "August"));
2990         months[9] = strdup(catgets(calendar->DT_catd, 1, 122, "September"));
2991         months[10] = strdup(catgets(calendar->DT_catd, 1, 123, "October"));
2992         months[11] = strdup(catgets(calendar->DT_catd, 1, 124, "November"));
2993         months[12] = strdup(catgets(calendar->DT_catd, 1, 125, "December"));
2994
2995         months2[1] = strdup(catgets(calendar->DT_catd, 1, 126, "Jan"));
2996         months2[2] = strdup(catgets(calendar->DT_catd, 1, 127, "Feb"));
2997         months2[3] = strdup(catgets(calendar->DT_catd, 1, 128, "Mar"));
2998         months2[4] = strdup(catgets(calendar->DT_catd, 1, 129, "Apr"));
2999         months2[5] = strdup(catgets(calendar->DT_catd, 1, 130, "May"));
3000         months2[6] = strdup(catgets(calendar->DT_catd, 1, 131, "Jun"));
3001         months2[7] = strdup(catgets(calendar->DT_catd, 1, 132, "Jul"));
3002         months2[8] = strdup(catgets(calendar->DT_catd, 1, 133, "Aug"));
3003         months2[9] = strdup(catgets(calendar->DT_catd, 1, 134, "Sep"));
3004         months2[10] = strdup(catgets(calendar->DT_catd, 1, 135, "Oct"));
3005         months2[11] = strdup(catgets(calendar->DT_catd, 1, 136, "Nov"));
3006         months2[12] = strdup(catgets(calendar->DT_catd, 1, 137, "Dec"));
3007         
3008         /* NL_COMMENT
3009            Attention Translator:
3010
3011            The strings (message number 138-144) are abbreviations to
3012            the days of the week:
3013
3014                 Sun --> Sunday
3015                 Mon --> Monday
3016                 Tue --> Tuesday
3017                 Wed --> Wednesday
3018                 Thu --> Thursday
3019                 Fri --> Friday
3020                 Sat --> Saturday
3021                 Sun --> Sunday
3022
3023         */
3024         days[0] = strdup(catgets(calendar->DT_catd, 1, 138, "Sun"));
3025         days[1] = strdup(catgets(calendar->DT_catd, 1, 139, "Mon"));
3026         days[2] = strdup(catgets(calendar->DT_catd, 1, 140, "Tue"));
3027         days[3] = strdup(catgets(calendar->DT_catd, 1, 141, "Wed"));
3028         days[4] = strdup(catgets(calendar->DT_catd, 1, 142, "Thu"));
3029         days[5] = strdup(catgets(calendar->DT_catd, 1, 143, "Fri"));
3030         days[6] = strdup(catgets(calendar->DT_catd, 1, 144, "Sat"));
3031         days[7] = strdup(catgets(calendar->DT_catd, 1, 138, "Sun"));
3032
3033         days2[0] = strdup(catgets(calendar->DT_catd, 1, 146, "Sunday"));
3034         days2[1] = strdup(catgets(calendar->DT_catd, 1, 147, "Monday"));
3035         days2[2] = strdup(catgets(calendar->DT_catd, 1, 148, "Tuesday"));
3036         days2[3] = strdup(catgets(calendar->DT_catd, 1, 149, "Wednesday"));
3037         days2[4] = strdup(catgets(calendar->DT_catd, 1, 150, "Thursday"));
3038         days2[5] = strdup(catgets(calendar->DT_catd, 1, 151, "Friday"));
3039         days2[6] = strdup(catgets(calendar->DT_catd, 1, 152, "Saturday"));
3040         days2[7] = strdup(catgets(calendar->DT_catd, 1, 146, "Sunday"));
3041
3042         /* NL_COMMENT
3043            Attention Translator:
3044
3045            The strings (message number 154-160, 168) are one letter 
3046            abbreviations to the days of the week:
3047
3048                 S --> Sunday (message 154)
3049                 M --> Monday
3050                 T --> Tuesday
3051                 W --> Wednesday
3052                 T --> Thursday
3053                 F --> Friday
3054                 S --> Saturday (message 160)
3055
3056         */
3057         days3[0] = strdup(catgets(calendar->DT_catd, 1, 154, "S"));
3058         days3[1] = strdup(catgets(calendar->DT_catd, 1, 155, "M"));
3059         days3[2] = strdup(catgets(calendar->DT_catd, 1, 156, "T"));
3060         days3[3] = strdup(catgets(calendar->DT_catd, 1, 157, "W"));
3061         days3[4] = strdup(catgets(calendar->DT_catd, 1, 158, "T"));
3062         days3[5] = strdup(catgets(calendar->DT_catd, 1, 159, "F"));
3063         days3[6] = strdup(catgets(calendar->DT_catd, 1, 160, "S"));
3064         days3[7] = strdup(catgets(calendar->DT_catd, 1, 154, "S"));
3065
3066         /* NL_COMMENT
3067            Attention Translator:
3068
3069            The strings (message number 170-176) are abbreviations to
3070            the days of the week:
3071
3072                 SUN --> Sunday
3073                 MON --> Monday
3074                 TUE --> Tuesday
3075                 WED --> Wednesday
3076                 THU --> Thursday
3077                 FRI --> Friday
3078                 SAT --> Saturday
3079
3080         */
3081         days4[0] = strdup(catgets(calendar->DT_catd, 1, 170, "SUN"));
3082         days4[1] = strdup(catgets(calendar->DT_catd, 1, 171, "MON"));
3083         days4[2] = strdup(catgets(calendar->DT_catd, 1, 172, "TUE"));
3084         days4[3] = strdup(catgets(calendar->DT_catd, 1, 173, "WED"));
3085         days4[4] = strdup(catgets(calendar->DT_catd, 1, 174, "THU"));
3086         days4[5] = strdup(catgets(calendar->DT_catd, 1, 175, "FRI"));
3087         days4[6] = strdup(catgets(calendar->DT_catd, 1, 176, "SAT"));
3088         days4[7] = strdup(catgets(calendar->DT_catd, 1, 170, "SUN"));
3089 }
3090
3091
3092 void
3093 switch_it(Calendar *c, char *new_calendar, WindowType win)
3094 {
3095         int                     new_version;
3096         char                    buf[MAXNAMELEN], *loc, *user;
3097         Tempbr                  *tb = (Tempbr*)c->tempbr;
3098         CSA_return_code         status;
3099         CSA_session_handle      new_cal_handle;
3100         Dtcm_calendar           *cal;
3101         CSA_calendar_user       csa_user;
3102         CSA_extension           logon_ext;
3103
3104         set_message(c->message_text, "\0");
3105  
3106         /*
3107          * Check to see if we're already browsing the requested calendar ...
3108          * If we have a valid calendar handle, we can return otherwise
3109          * try logon again
3110          */
3111         if (strcmp(new_calendar, c->view->current_calendar) == 0 &&
3112             c->cal_handle) {
3113                 sprintf(buf, catgets(c->DT_catd, 1, 178,
3114                         "You Are Already Browsing %s"), new_calendar);
3115                 set_message(c->message_text, buf);
3116                 if (tb && tb->show_message)
3117                         set_message(tb->show_message, buf);
3118                 return;
3119         }
3120
3121         invalidate_cache(c);
3122
3123         /*
3124          * Open the new calendar for browsing (or use my_cal_handle if we're
3125          * switching to our calendar).
3126          */
3127         if (strcmp(new_calendar, c->calname) == 0) {
3128                 if (c->my_cal_handle == 0) {
3129                         if (open_user_calendar(c, False) == True)
3130                                 reset_timer(c);
3131                         else
3132                                 return;
3133                 }
3134                 new_cal_handle = c->my_cal_handle;
3135                 c->user_access = c->my_access;
3136         } else {
3137                 if ((user = cm_target2name(new_calendar)) == NULL) {
3138                         if (!strcmp(new_calendar, ""))
3139                                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 619, "Please enter a calendar name in the format: <user>@<hostname>"));
3140                         else
3141                                 sprintf(buf, catgets(c->DT_catd, 1, 620,
3142                 "Unknown calendar. Calendar name needed: <name>%s"),
3143                                 new_calendar);
3144                         set_message(c->message_text, buf);
3145                         if (win == tempbrowser)
3146                                 set_message(tb->show_message, buf);
3147                         return;
3148                 }
3149
3150                 if ((loc = cm_target2location(new_calendar)) == NULL) {
3151                         if (!strcmp(new_calendar, ""))
3152                                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 619, "Please enter a calendar name in the format: <user>@<hostname>"));
3153                         else
3154                                 sprintf(buf, catgets(c->DT_catd, 1, 622,
3155         "Unknown calendar. Hostname needed: %s@<hostname>"),
3156                                 user);
3157                         set_message(c->message_text, buf);
3158                         if (win == tempbrowser)
3159                                 set_message(tb->show_message, buf);
3160                         free(user);
3161                         return;
3162                 }
3163
3164                 /*
3165                  * Note this assumes your calendar has already been opened;
3166                  * this should have been done at start-up by open_user_calendar.
3167                  */
3168
3169                 csa_user.user_name = new_calendar;
3170                 csa_user.user_type = 0;
3171                 csa_user.calendar_user_extensions = NULL;
3172                 csa_user.calendar_address = new_calendar;
3173
3174                 logon_ext.item_code = CSA_X_DT_GET_USER_ACCESS_EXT;
3175                 logon_ext.item_data = 0;
3176                 logon_ext.item_reference = NULL;
3177                 logon_ext.extension_flags = CSA_EXT_LAST_ELEMENT;
3178
3179                 status = csa_logon(NULL, &csa_user, NULL, NULL, NULL,
3180                                 &new_cal_handle, &logon_ext);
3181                 free(loc);
3182                 free(user);
3183
3184                 if (status != CSA_SUCCESS) {
3185                         backend_err_msg(c->frame, new_calendar, status,
3186                                 ((Props_pu *)c->properties_pu)->xm_error_pixmap);
3187                         if (tb && tb->show_message)
3188                                 set_message(tb->show_message, "\0");
3189                         return;
3190                 } else
3191                         c->user_access = logon_ext.item_data;
3192         }
3193
3194         set_message(((Editor *)c->editor)->message_text, " ");      
3195         set_message(((GEditor *)c->geditor)->message_text, " ");
3196         set_message(((ToDo *)c->todo)->message_text, " ");
3197
3198         /*
3199          * Get the version number of the new calendar
3200          */
3201
3202         new_version = get_data_version(new_cal_handle);
3203
3204         if (new_version < DTCM_DATA_VER)
3205                 set_message(c->message_text, catgets(c->DT_catd, 1, 186,
3206                        "Calendar (dtcm) and rpc.cmsd versions are different."));
3207
3208         /*
3209          * Close the calendar we were currently browsing (note we don't ever
3210          * close our calendar) and set the callback for the new calendar.
3211          */
3212         if (c->cal_handle != c->my_cal_handle)
3213                 csa_logoff(c->cal_handle, NULL);
3214
3215         if (new_cal_handle != c->my_cal_handle) {
3216
3217
3218                 CSA_flags       flags = NULL;
3219                 CSA_extension   cb_ext;
3220
3221                 flags = CSA_CB_ENTRY_ADDED | CSA_CB_ENTRY_DELETED |
3222                         CSA_CB_ENTRY_UPDATED;
3223                 cb_ext.item_code = CSA_X_XT_APP_CONTEXT_EXT;
3224                 cb_ext.item_data = (CSA_uint32)c->xcontext->app;
3225                 cb_ext.extension_flags = CSA_EXT_LAST_ELEMENT;
3226                 csa_register_callback(new_cal_handle, flags,
3227                                 update_handler, NULL, &cb_ext);
3228
3229         }
3230
3231         /*
3232          * Set variables in the Calendar structure for the new calendar and
3233          * repaint.
3234          */
3235         c->cal_handle = new_cal_handle;
3236         c->general->version = new_version;
3237         if (c->view->current_calendar != NULL)
3238                 free(c->view->current_calendar);
3239         c->view->current_calendar = cm_strdup(new_calendar);
3240         paint_canvas(c, NULL, RENDER_CLEAR_FIRST);
3241  
3242         /*
3243          * Set the title bars on all the windows!
3244          */
3245         sprintf(buf, "%s : %s", catgets(c->DT_catd, 1, 113, "Calendar"),
3246                                 new_calendar);
3247         XtVaSetValues(c->frame, XmNtitle, buf, NULL);
3248  
3249         set_editor_title((Editor *)c->editor, new_calendar);
3250         add_all_appt((Editor *)c->editor);
3251         set_geditor_title((GEditor *)c->geditor, new_calendar);
3252         add_all_gappt((GEditor *)c->geditor);
3253         set_todo_title((ToDo *)c->todo, new_calendar);
3254         add_all_todo((ToDo *)c->todo);
3255
3256         /* set up the repeat menus for all the editors. */
3257
3258         if (c->editor && (((Editor *)c->editor)->rfp.repeat_menu))
3259                 rfp_set_repeat_values(&((Editor *)c->editor)->rfp);
3260
3261         if (c->geditor && (((GEditor *)c->geditor)->rfp.repeat_menu))
3262                 rfp_set_repeat_values(&((GEditor *)c->geditor)->rfp);
3263
3264         if (c->todo && (((ToDo *)c->todo)->rfp.repeat_menu))
3265                 rfp_set_repeat_values(&((ToDo *)c->todo)->rfp);
3266
3267         if (c->general->version < DATAVER2) {
3268                 if (todo_showing((ToDo *)calendar->todo))
3269                         XtPopdown(((ToDo *)calendar->todo)->frame);
3270                 XtUnmanageChild(c->todo_btn);
3271                 XtSetSensitive(c->todo_edit_menu, False);
3272                 XtSetSensitive(c->todo_view_menu, False);
3273         }
3274         else {
3275                 XtManageChild(c->todo_btn);
3276                 XtSetSensitive(c->todo_edit_menu, True);
3277                 XtSetSensitive(c->todo_view_menu, True);
3278         }
3279
3280         if (tb && tb->show_message) {
3281                 char    buf[128];
3282                 char *calendar = 
3283                   XtNewString(catgets(c->DT_catd, 1, 919, "Calendar"));
3284
3285                 sprintf (buf, "%s %s %s",
3286                         calendar,
3287                         new_calendar,
3288                         catgets(c->DT_catd, 1, 920, "displayed."));
3289                 XtFree(calendar);
3290                 set_message(tb->show_message, buf);
3291         }
3292 }
3293
3294 /*
3295  * calendar callback function
3296  *
3297  * CSA callback that handles main canvas.
3298  * A separate one is used for the browser canvas (browser.c/mb_update_handler)
3299  * They get invoked from libcsa when there are changes to calendars we
3300  * have registered them on.
3301  *
3302  * This is a simple callback routine: it doesn't care what the
3303  * reason is for the call... it always refreshes all data & display.
3304  * An optimization would be to only refresh the canvas region affected
3305  * by the data changed.
3306  */
3307 static void
3308 update_handler(CSA_session_handle cal, CSA_flags reason,
3309                CSA_buffer call_data, CSA_buffer client_data, CSA_extension *ext)
3310 {
3311         Calendar        *c = calendar;
3312
3313         /* sync canvas */
3314         invalidate_cache(c);
3315         paint_canvas(c, NULL, RENDER_CLEAR_FIRST);
3316         reset_alarm(c);
3317
3318         /* sync editors */
3319         if (editor_showing((Editor *)c->editor))
3320                 add_all_appt((Editor *)c->editor);
3321         if (todo_showing((ToDo *)calendar->todo))
3322                 add_all_todo((ToDo *)calendar->todo);
3323
3324 }
3325
3326 static Boolean
3327 init_fonts(
3328         Calendar *cal)
3329 {
3330         XrmDatabase      db;
3331         Cal_Font         systemfont,
3332                          userfont;
3333
3334         /*
3335          * Some of the scrolling lists contain formatted text and thus
3336          * require a fixed width font to display the text correctly.
3337          * We want to use the fixed width font defined by *.userFont as
3338          * it will be localized to the system calendar is running on. 
3339          */
3340         db = XtScreenDatabase(XtScreen(cal->frame));
3341         if (db) {
3342                 XrmPutStringResource(&db, "*find_list.fontList", 
3343                                                        cal->app_data->userfont);
3344                 XrmPutStringResource(&db, "*view_list.fontList",
3345                                                        cal->app_data->userfont);
3346                 XrmPutStringResource(&db, "*todo_list.fontList",
3347                                                        cal->app_data->userfont);
3348                 XrmPutStringResource(&db, "*ge_appt_list.fontList",
3349                                                        cal->app_data->userfont);
3350                 XrmPutStringResource(&db, "*access_list.fontList",
3351                                                        cal->app_data->userfont);
3352                 XrmPutStringResource(&db, "*browseList.fontList",
3353                                                        cal->app_data->userfont);
3354                 XrmPutStringResource(&db, "Dtcm*canvas*week2day.fontList",
3355                                                      cal->app_data->systemfont);
3356                 if (cal->app_data->labelfont)
3357                         XrmPutStringResource(&db, "*monthLabel.fontList",
3358                                                       cal->app_data->labelfont);
3359                 else
3360                         XrmPutStringResource(&db, "*monthLabel.fontList",
3361                                                      cal->app_data->systemfont);
3362                 if (cal->app_data->labelfont)
3363                         XrmPutStringResource(&db, "*yearLabel.fontList",
3364                                                       cal->app_data->labelfont);
3365                 else
3366                         XrmPutStringResource(&db, "*yearLabel.fontList",
3367                                                      cal->app_data->systemfont);
3368         }
3369
3370         if (!fontlist_to_font(cal->app_data->systemfontlist, &systemfont)) {
3371                 /* Couldn't convert the system fontlist to a font - bad news. */
3372                 if (!(systemfont.f.cf_font = 
3373                              XLoadQueryFont(XtDisplay(cal->frame), "variable")))
3374                         return False;
3375                 else
3376                         systemfont.cf_type = XmFONT_IS_FONT; 
3377         }
3378         if (!fontlist_to_font(cal->app_data->userfontlist, &userfont)) {
3379                 /* Couldn't convert the user fontlist to a font - bad news. */
3380                 if (!(userfont.f.cf_font = 
3381                              XLoadQueryFont(XtDisplay(cal->frame), "fixed")))
3382                         return False;
3383                 else
3384                         userfont.cf_type = XmFONT_IS_FONT; 
3385         }
3386
3387         *cal->fonts->userfont =  userfont;
3388
3389         /*
3390          * If the application resources for the view, label, icon or bold
3391          * font are not set, default to the system/user font or application
3392          * font for the views.
3393          */
3394         if (cal->app_data->viewfontlist) {
3395                 if (!fontlist_to_font(cal->app_data->viewfontlist, 
3396                                       cal->fonts->viewfont))
3397                         *cal->fonts->viewfont = userfont;
3398         } else {
3399                         load_app_font(cal, MEDIUM, &userfont, 
3400                                       cal->fonts->viewfont);
3401         }
3402
3403         if (cal->app_data->labelfontlist) {
3404                 if (!fontlist_to_font(cal->app_data->labelfontlist, 
3405                                       cal->fonts->labelfont))
3406                         *cal->fonts->labelfont = systemfont;
3407         } else {
3408                         *cal->fonts->labelfont = systemfont;
3409         }
3410
3411         if (cal->app_data->iconfontlist) {
3412                 if (!fontlist_to_font(cal->app_data->iconfontlist, 
3413                                       cal->fonts->iconfont))
3414                         *cal->fonts->iconfont = systemfont;
3415         } else {
3416                         *cal->fonts->iconfont = systemfont;
3417         }
3418
3419         if (cal->app_data->boldfontlist) {
3420                 if (!fontlist_to_font(cal->app_data->boldfontlist, 
3421                                       cal->fonts->boldfont))
3422                         *cal->fonts->boldfont = userfont;
3423         } else {
3424                         load_app_font(cal, BOLD, &userfont, 
3425                                       cal->fonts->boldfont);
3426         }
3427
3428         return True;
3429 }