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