Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtcm / dtcm / todo.c
1 /* $TOG: todo.c /main/12 1999/07/01 09:24:05 mgreess $ */
2 /*
3  *  (c) Copyright 1993, 1994 Hewlett-Packard Company
4  *  (c) Copyright 1993, 1994 International Business Machines Corp.
5  *  (c) Copyright 1993, 1994 Novell, Inc.
6  *  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
7  */
8
9 #include <EUSCompat.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <ctype.h>
13 #include <string.h>
14 #include <Xm/Xm.h>
15 #include <Xm/DialogS.h>
16 #include <Xm/Form.h>
17 #include <Xm/List.h>
18 #include <Xm/Frame.h>
19 #include <Xm/PushB.h>
20 #include <Xm/PushBG.h>
21 #include <Xm/RowColumn.h>
22 #include <Xm/SeparatoG.h>
23 #include <Xm/ToggleB.h>
24 #include <Xm/Text.h>
25 #include <Xm/ToggleBG.h>
26 #include <Xm/LabelG.h>
27 #include <Xm/ScrolledW.h>
28 #include <Dt/HourGlass.h>
29 #include <Dt/Dt.h>
30 #include <Dt/Dnd.h>
31 #include <Dt/Icon.h>
32 #include "todo.h"
33 #include "datefield.h"
34 #include "deskset.h"
35 #include "getdate.h"
36 #include "format.h"
37 #include "timeops.h"
38 #include "props_pu.h"
39 #include "util.h"
40 #include "help.h"
41 #include "dnd.h"
42 #ifdef SVR4
43 #include <sys/param.h>
44 #endif /* SVR4 */
45
46 static void t_build_expand(ToDo *);
47
48 /* Absolute value macro */
49 #ifndef ABS
50 #define ABS(x) (((x) > 0) ? (x) : (-(x)))
51 #endif
52 static void set_todo_msg_defaults();
53 static void clear_flag_on_modify(Widget, XtPointer, XtPointer);
54
55 static CSA_return_code
56 t_execute_change(ToDo *, CSA_entry_handle , Dtcm_appointment *, Widget );
57 extern boolean_t compare_repeat_info(Dtcm_appointment *, RFP *, CSA_session_handle, int);
58 extern void change_rule_for_this_one_only(Calendar *, Dtcm_appointment *, Dtcm_appointment *);
59 extern Dimension ComputeMaxWidth(Widget, Widget, Widget, Widget);
60
61 /*******************************************************************************
62 **
63 **  Functions static to todo.c
64 **
65 *******************************************************************************/
66 /*
67 **  Return the nth appointment
68 */
69 extern CSA_entry_handle
70 t_nth_appt(ToDo *t, int idx) {
71         if (idx >= 0 && idx < t->todo_count)
72                 return t->todo_head[idx];
73         return 0;
74 }
75
76 static void
77 clear_flag_on_modify(Widget w, XtPointer uData, XtPointer cbData)
78 {
79   int *flagP = (int *)uData;
80
81   *flagP = 0;
82 }
83
84 /*
85 **  This function will take todo values and stuff them into a form.
86 */
87 static void
88 appt_to_form(ToDo *t, CSA_entry_handle a) {
89         char                    buf[MAXNAMELEN];
90         CSA_return_code         stat;
91         Dtcm_appointment        *appt;
92
93         if (!t->reminders.bfpm_form_mgr) {
94                 t_build_expand(t);
95                 set_rfp_defaults(&t->rfp);
96                 set_reminders_defaults(&t->reminders);
97         }
98
99         if (!dssw_appt_to_form(&t->dssw, a))
100                 return;
101         if (!rfp_appt_to_form(&t->rfp, a))
102                 return;
103         t->rfpFlags = 0;
104         if (!reminders_appt_to_form(&t->reminders, a))
105                 return;
106
107         appt = allocate_appt_struct(appt_read,
108                                     t->cal->general->version,
109                                     CSA_ENTRY_ATTR_STATUS_I,
110                                     CSA_ENTRY_ATTR_ORGANIZER_I,
111                                     NULL);
112         stat = query_appt_struct(t->cal->cal_handle, a, appt);
113         backend_err_msg(t->frame, t->cal->view->current_calendar, stat,
114                         ((Props_pu *)t->cal->properties_pu)->xm_error_pixmap);
115         if (stat != CSA_SUCCESS) {
116                 free_appt_struct(&appt);
117                 return;
118         }
119
120         if (appt->state->value->item.sint32_value == CSA_STATUS_COMPLETED)
121                 t->completed_val = True;
122         else
123                 t->completed_val = False;
124         XmToggleButtonGadgetSetState(t->completed_toggle,
125                 t->completed_val, True);
126         sprintf(buf, "%s:  %s", catgets(t->cal->DT_catd, 1, 565, "Author"),
127                 appt->author->value->item.calendar_user_value->user_name);
128         set_message(t->message_text, buf);
129         free_appt_struct(&appt);
130 }
131
132 /*
133 **  List selection procedure will get the correct todo, then call
134 **  appt_to_form to load it into the UI.
135 */
136 static void
137 t_list_select_proc(Widget w, XtPointer client_data, XtPointer data) {
138         CSA_entry_handle                a;
139         ToDo                    *t = (ToDo *)client_data;
140         XmListCallbackStruct    *cbs = (XmListCallbackStruct *)data;
141
142         if (a = t_nth_appt(t, cbs->item_position - 1))
143                 appt_to_form(t, a);
144         XtSetSensitive(t->delete_button, True);
145         XtSetSensitive(t->change_button, True);
146 }
147
148 /*
149 **  This function creates the expando stuff on a form manager.
150 */
151 static void
152 t_build_expand(ToDo *t) {
153         Props           *p = (Props *)t->cal->properties;
154         Widget          widgets[20];
155         WidgetList      children;
156         int             i = 0,
157                         j = 0,
158                         n;
159         Dimension highest;
160         Widget curr;
161
162         /*
163         **  Build the rfp "widget" then unmanage the privacy stuff ...
164         **  Since none of the other widgets in the rfp composite widget don't
165         **  depend on the privacy stuff for geometry mgmt, this is all we need
166         **  to do.
167         */
168         t->rfpFlags = 0;
169         build_rfp(&t->rfp, t->cal, t->base_form_mgr);
170         XtVaSetValues(t->rfp.rfp_form_mgr,
171                 XmNtopAttachment,       XmATTACH_WIDGET,
172                 XmNtopWidget,           t->separator1,
173                 XmNleftAttachment,      XmATTACH_FORM,
174                 XmNleftOffset,          5,
175                 NULL);
176         XtVaGetValues(t->rfp.rfp_form_mgr,
177                 XmNchildren,            &children,
178                 XmNnumChildren,         &n,
179                 NULL);
180
181         /* We don't want to manage the privacy widgets */
182         for (i = 0; i < n; i++) {
183                 if ((children[i] == t->rfp.privacy_label) ||
184                     (children[i] == t->rfp.privacy_menu))
185                     continue;
186                 widgets[j++] = children[i];
187         }
188         XtManageChildren(widgets, n - 2);
189
190         XtAddCallback(t->rfp.repeat_menu, XmNselectionCallback,
191                       clear_flag_on_modify, (XtPointer)&t->rfpFlags);
192
193         /*
194         **  Build the reminders widget, unmanage everything except the mail
195         **  stuff and make sure to reset the attachments so the form behaves
196         **  correctly.  Use the reminders widget (though it seems wasteful) to
197         **  share code and make future HIE decision changes easy to implement.
198         */
199         build_reminders(&t->reminders, t->cal, t->base_form_mgr);
200         widgets[0] = t->reminders.alarm_label;
201         widgets[1] = t->reminders.mail_toggle;
202         widgets[2] = t->reminders.mail_text;
203         widgets[3] = t->reminders.mail_menu;
204         widgets[4] = t->reminders.mailto_label;
205         widgets[5] = t->reminders.mailto_text;
206
207         _i18n_HighestWidget( 3, &curr, &highest, t->reminders.mail_toggle,
208                         t->reminders.mail_text, t->reminders.mail_menu );
209         XtVaSetValues( curr,
210                         XmNtopAttachment, XmATTACH_WIDGET,
211                         XmNtopWidget, t->reminders.alarm_label,
212                         NULL );
213         XtVaSetValues(t->reminders.bfpm_form_mgr,
214                 XmNtopAttachment,       XmATTACH_OPPOSITE_WIDGET,
215                 XmNtopWidget,           t->rfp.rfp_form_mgr,
216                 XmNrightAttachment,     XmATTACH_FORM,
217                 XmNrightOffset,         5,
218                 XmNleftAttachment,      XmATTACH_WIDGET,
219                 XmNleftWidget,          t->rfp.rfp_form_mgr,
220                 NULL);
221
222         XtManageChildren(widgets, 6);
223 }
224
225 static void
226 clear_view_changes(ToDo *t){
227         TodoView                *step, *last = NULL;
228
229         step = t->view_list;
230
231         if (t->view_list_modified == False)
232                 return;
233
234         _DtTurnOnHourGlass(t->view_frame);
235
236         while (step) {
237                 if (step->modified) {
238                         step->modified = False;
239                 }
240                 step = step->next;
241         }
242         _DtTurnOffHourGlass(t->view_frame);
243
244         t->view_list_modified = False;
245 }
246
247 static void
248 write_view_changes(ToDo *t){
249         Boolean                 toggle_state;
250         TodoView                *step = t->view_list;
251         CSA_return_code         stat;
252         Dtcm_appointment        *appt;
253         CSA_entry_handle        updated_a;
254         CSA_enum                scope;
255         Calendar                *c = t->cal;
256         Props_pu                *p = (Props_pu *)t->cal->properties_pu;
257
258         if (t->view_list_modified == False)
259                 return;
260
261         if (t->cal->general->version <= DATAVER3) {
262                 appt = allocate_appt_struct(appt_write, 
263                                             t->cal->general->version,
264                                             CSA_ENTRY_ATTR_STATUS_I, 
265                                             CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I,
266                                             NULL);
267                 appt->repeat_type->value->item.sint32_value = 
268                                                 CSA_X_DT_REPEAT_ONETIME;
269         }
270         else {
271                 appt = allocate_appt_struct(appt_write, 
272                                             t->cal->general->version,
273                                             CSA_ENTRY_ATTR_STATUS_I, 
274                                             CSA_ENTRY_ATTR_RECURRENCE_RULE_I, 
275                                             NULL); 
276                 appt->recurrence_rule->value->item.string_value = 
277                                                 strdup("D1 #1");
278         }
279                 
280         _DtTurnOnHourGlass(t->view_frame); 
281
282         scope = CSA_SCOPE_ONE;
283
284         while (step) { 
285                 if (step->modified) {
286
287                         toggle_state = XmToggleButtonGadgetGetState(
288                                         step->view_item_toggle);
289                         appt->state->value->item.sint32_value = 
290                                 (toggle_state) ?
291                                   CSA_STATUS_COMPLETED : CSA_X_DT_STATUS_ACTIVE;
292
293                         stat = csa_update_entry_attributes(c->cal_handle, 
294                                         step->appt, scope, 
295                                         CSA_FALSE, appt->count, 
296                                         appt->attrs, &updated_a, NULL);
297                         backend_err_msg(t->view_frame, 
298                                         c->view->current_calendar, stat,
299                                         p->xm_error_pixmap);
300                         if (stat != CSA_SUCCESS)
301                                 break;
302
303                         csa_free((CSA_buffer) step->appt);
304                         step->appt = updated_a;
305
306                         if (stat != CSA_SUCCESS)
307                                 XtVaSetValues(step->view_item_toggle,
308                                         XmNset, !toggle_state,
309                                         NULL);
310                         step->modified = False;
311                 }
312                 step = step->next;
313         }
314
315         free_appt_struct(&appt);
316                 
317         if (todo_showing(t)) {
318                 set_todo_msg_defaults(t);
319                 add_all_todo(t);
320         }
321         reset_alarm(c);
322         invalidate_cache(t->cal);
323
324         _DtTurnOffHourGlass(t->view_frame);
325
326         t->view_list_modified = False;
327 }
328 static Boolean
329 flush_view_changes(ToDo *t){
330         Calendar        *c = t->cal;
331         Props_pu        *pu = (Props_pu *) c->properties_pu;
332         int             answer;
333
334         if (t->view_list_modified) {
335                 char *title = XtNewString(catgets(c->DT_catd, 1, 778, "Calendar : To Do List - Help"));
336                 char *text = XtNewString(catgets(c->DT_catd, 1, 451, "You have made unsaved changes.\nYou may save your changes, discard your changes, \nor return to your previous place in the dialog."));
337                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 452, "Save"));
338                 char *ident2 = XtNewString(catgets(c->DT_catd, 1, 700, "Discard"));
339                 char *ident3 = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
340                 answer = dialog_popup(t->view_frame,
341                         DIALOG_TITLE, title,
342                         DIALOG_TEXT, text,
343                         BUTTON_IDENT, 1, ident1,
344                         BUTTON_IDENT, 2, ident2,
345                         BUTTON_IDENT, 3, ident3,
346                         DIALOG_IMAGE, pu->xm_warning_pixmap,
347                         NULL);
348                 XtFree(ident3);
349                 XtFree(ident2);
350                 XtFree(ident1);
351                 XtFree(text);
352                 XtFree(title);
353                 if (answer == 1) {
354                         write_view_changes(t);
355                         return(True);
356                 }
357                 else if (answer == 2) {
358                         clear_view_changes(t);
359                         return(True);
360                 }
361                 else
362                         return(False);
363         }
364
365         return(True);
366 }
367
368 /*
369 **  Quit handler for the view popup
370 */
371 static void
372 t_view_quit_handler(Widget w, XtPointer cdata, XtPointer data) {
373         ToDo *t = (ToDo *)cdata;
374
375         if (flush_view_changes(t) == False)
376                 return;
377
378         XtPopdown(t->view_frame);
379         t->todo_view_is_up = False;
380 }
381
382 static void
383 t_view_cancel_cb(
384         Widget  widget,
385         XtPointer client_data,
386         XmPushButtonCallbackStruct *cbs)
387 {
388         ToDo            *t = (ToDo *)client_data;
389
390         if (flush_view_changes(t) == False)
391                 return;
392
393         XtPopdown(t->view_frame);
394 }
395
396 static void
397 t_view_apply_cb(
398         Widget  widget,
399         XtPointer client_data,
400         XmPushButtonCallbackStruct *cbs)
401 {
402         ToDo            *t = (ToDo *)client_data;
403
404         write_view_changes(t);
405
406         build_todo_view(t, t->view_list_glance, False); 
407 }
408
409 static void
410 t_view_ok_cb(
411         Widget  widget,
412         XtPointer client_data,
413         XmPushButtonCallbackStruct *cbs)
414 {
415         ToDo            *t = (ToDo *)client_data;
416
417         write_view_changes(t);
418
419         XtPopdown(t->view_frame);
420 }
421
422 /*
423 **  Callbacks for the todo filter popup
424 */
425 static void
426 t_view_filter_proc(Widget w, XtPointer client_data, XtPointer cbs) {
427         ToDo            *t = (ToDo *)client_data; 
428         int             op;
429
430         if (!t)
431                 return; 
432
433         XtVaGetValues(w, XmNuserData, &op, NULL);
434
435         if (op == t->view_filter)
436                 return;
437
438         t->view_filter = op;
439
440         build_todo_view(t, t->view_list_glance, True); 
441 }
442
443 extern Widget
444 create_filter_menu(Widget parent, XtCallbackProc cb_func, XtPointer data) {
445         int                     i;
446         Widget                  menuitem;
447         Widget                  menu;
448         Widget                  cascade;
449         XmString                label;
450         XmString                option1;
451         XmString                option2;
452         XmString                option3;
453         extern                  Calendar *calendar;
454         int                     ac = 0;
455         Arg                     args[5];
456
457         label = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 40, "View"));
458         option1 = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 272, "All"));
459         option2 = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 783, "Pending"));
460         option3 = XmStringCreateLocalized(catgets(calendar->DT_catd, 1, 784, "Completed"));
461
462         menu = XmCreatePulldownMenu(parent, "_pulldown", NULL, 0);
463
464         XtSetArg(args[ac], XmNsubMenuId, menu); ac++;
465
466         cascade = XmCreateOptionMenu(parent, "option_m", args, ac);
467
468         menuitem = XtVaCreateWidget("all",
469                        xmPushButtonGadgetClass, menu,
470                        XmNlabelString, option1,
471                        XmNuserData, VIEW_ALL,
472                        NULL);
473
474         XtAddCallback(menuitem, XmNactivateCallback, cb_func, data);
475
476         menuitem = XtVaCreateWidget("pending",
477                        xmPushButtonGadgetClass, menu,
478                        XmNlabelString, option2,
479                        XmNuserData, VIEW_PENDING,
480                        NULL);
481
482         XtAddCallback(menuitem, XmNactivateCallback, cb_func, data);
483
484         menuitem = XtVaCreateWidget("completed",
485                        xmPushButtonGadgetClass, menu,
486                        XmNlabelString, option3,
487                        XmNuserData, VIEW_COMPLETED,
488                        NULL);
489
490         XtAddCallback(menuitem, XmNactivateCallback, cb_func, data);
491
492
493         XmStringFree(label);
494         XmStringFree(option1);
495         XmStringFree(option2);
496         XmStringFree(option3);
497
498         ManageChildren(menu);
499
500         return cascade;
501 }
502
503 /*
504 **  Build the popup to display, in list fashion, the todos for a given period.
505 */
506 static void
507 t_build_view_popup(ToDo *t) {
508
509         Calendar        *c = t->cal;
510         XmString        xmstr;
511         Widget          label, separator;
512         char            *title;
513
514         /*
515         **  Dialog shell and form
516         */
517         title = XtNewString(catgets(c->DT_catd, 1, 1012, "Calendar : To Do List"));
518         t->view_frame = XtVaCreatePopupShell("todo_list",
519                 xmDialogShellWidgetClass, c->frame,
520                 XmNtitle, title,
521                 XmNdeleteResponse, XmDO_NOTHING,
522                 XmNallowShellResize, True,
523                 XmNmappedWhenManaged, False,
524                 XmNautoUnmanage, False,
525                 NULL);
526         XtFree(title);
527         setup_quit_handler(t->view_frame, t_view_quit_handler, (caddr_t)t);
528
529         t->view_form = XtVaCreateWidget("apptform",
530                         xmFormWidgetClass, t->view_frame,
531                         XmNfractionBase, 4,
532                         XmNautoUnmanage, False,
533                         NULL);
534
535         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 655, "OK"));
536
537
538         t->view_ok_button = XtVaCreateWidget("ok",
539                                 xmPushButtonWidgetClass, t->view_form,
540                                 XmNlabelString, xmstr,
541                                 XmNleftAttachment, XmATTACH_POSITION,
542                                 XmNleftPosition, 0,
543                                 XmNleftOffset, 10,
544                                 XmNrightAttachment, XmATTACH_POSITION,
545                                 XmNrightPosition, 1,
546                                 XmNbottomAttachment, XmATTACH_FORM,
547                                 XmNbottomOffset,         5,
548                                 NULL);
549
550         XmStringFree(xmstr);
551
552
553         XtAddCallback(t->view_ok_button, XmNactivateCallback, (XtCallbackProc) t_view_ok_cb, t);
554
555
556         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 460, "Apply"));
557
558         t->view_apply_button = XtVaCreateWidget("apply",
559                                 xmPushButtonWidgetClass, t->view_form,
560                                 XmNlabelString, xmstr,
561                                 XmNleftAttachment, XmATTACH_POSITION,
562                                 XmNleftPosition, 1,
563                                 XmNrightAttachment, XmATTACH_POSITION,
564                                 XmNrightPosition, 2,
565                                 XmNbottomAttachment, XmATTACH_FORM,
566                                 XmNbottomOffset,         5,
567                                 NULL);
568         XmStringFree(xmstr);
569
570         XtAddCallback(t->view_apply_button, XmNactivateCallback, (XtCallbackProc) t_view_apply_cb, t);
571
572         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 923, "Cancel"));
573
574         t->view_cancel_button = XtVaCreateWidget("cancel",
575                                 xmPushButtonWidgetClass, t->view_form,
576                                 XmNlabelString, xmstr,
577                                 XmNleftAttachment, XmATTACH_POSITION,
578                                 XmNleftPosition, 2,
579                                 XmNrightAttachment, XmATTACH_POSITION,
580                                 XmNrightPosition, 3,
581                                 XmNbottomAttachment, XmATTACH_FORM,
582                                 XmNbottomOffset,         5,
583                                 NULL);
584
585         XmStringFree(xmstr);
586
587         XtAddCallback(t->view_cancel_button, XmNactivateCallback, (XtCallbackProc) t_view_cancel_cb, t);
588
589         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 77, "Help"));
590
591         t->view_help_button = XtVaCreateWidget("help",
592                                 xmPushButtonWidgetClass, t->view_form,
593                                 XmNlabelString, xmstr,
594                                 XmNleftAttachment, XmATTACH_POSITION,
595                                 XmNleftPosition, 3,
596                                 XmNrightAttachment, XmATTACH_POSITION,
597                                 XmNrightPosition, 4,
598                                 XmNrightOffset, 10,
599                                 XmNbottomAttachment, XmATTACH_FORM,
600                                 XmNbottomOffset,         5,
601                                 NULL);
602         XmStringFree(xmstr);
603
604
605         separator = XtVaCreateWidget("separator",
606                 xmSeparatorGadgetClass,
607                 t->view_form,
608                 XmNleftAttachment,      XmATTACH_FORM,
609                 XmNrightAttachment,     XmATTACH_FORM,
610                 XmNbottomAttachment,    XmATTACH_WIDGET,
611                 XmNbottomWidget,        t->view_ok_button,
612                 XmNbottomOffset,        5,
613                 NULL);
614
615         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 789, "To Do Type:"));
616         label= XtVaCreateWidget("type_label",
617                 xmLabelGadgetClass,     t->view_form,
618                 XmNtopAttachment,       XmATTACH_FORM,
619                 XmNleftAttachment,      XmATTACH_FORM,
620                 XmNleftOffset,          5,
621                 XmNtopOffset,           8,
622                 XmNlabelString,         xmstr,
623                 NULL);
624         XmStringFree(xmstr);
625
626
627         t->view_filter_menu = create_filter_menu(t->view_form, t_view_filter_proc, (XtPointer) t);
628
629         XtVaSetValues(t->view_filter_menu,
630                 XmNuserData,            REPEAT_DAYS,
631                 XmNtopAttachment,       XmATTACH_FORM,
632                 XmNleftAttachment,      XmATTACH_WIDGET,
633                 XmNleftWidget,          label,
634                 XmNtopOffset,           3,
635                 XmNleftOffset,          5,
636                 NULL);
637
638         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 790, "context"));
639         t->view_list_label= XtVaCreateWidget("type_label",
640                 xmLabelGadgetClass,     t->view_form,
641                 XmNtopAttachment,       XmATTACH_WIDGET,
642                 XmNtopWidget,           t->view_filter_menu, 
643                 XmNleftAttachment,      XmATTACH_FORM,
644                 XmNleftOffset,          5,
645                 XmNtopOffset,           5,
646                 XmNlabelString,         xmstr,
647                 NULL);
648         XmStringFree(xmstr);
649
650         t->view_sw_mgr = XtVaCreateWidget("view_sw_mgr",
651                 xmScrolledWindowWidgetClass, t->view_form,
652                 XmNscrollingPolicy,     XmAUTOMATIC,
653                 XmNlistSizePolicy,      XmCONSTANT,
654                 XmNscrolledWindowMarginHeight, 5,
655                 XmNscrolledWindowMarginWidth, 5,
656                 XmNwidth,               400,
657                 XmNheight,              200,
658                 XmNleftAttachment,      XmATTACH_FORM,
659                 XmNleftOffset,          5,
660                 XmNrightAttachment,     XmATTACH_FORM, 
661                 XmNrightOffset,         5,
662                 XmNtopAttachment,       XmATTACH_WIDGET,
663                 XmNtopWidget,           t->view_list_label, 
664                 XmNbottomAttachment,    XmATTACH_WIDGET,
665                 XmNbottomWidget,        separator,
666                 XmNbottomOffset,        5,
667                 NULL);
668         t->view_form_mgr = XtVaCreateWidget("view_form_mgr",
669                 xmFormWidgetClass, t->view_sw_mgr,
670                 NULL);
671
672         XtAddCallback(t->view_help_button, XmNactivateCallback,
673                 (XtCallbackProc)help_cb, TODO_LIST_HELP_BUTTON);
674         XtAddCallback(t->view_form, XmNhelpCallback,
675                 (XtCallbackProc)help_cb, (XtPointer) TODO_LIST_HELP_BUTTON);
676
677         ManageChildren(t->view_form); 
678         XtManageChild(t->view_sw_mgr);
679         XtManageChild(t->view_form_mgr); 
680         XtManageChild(t->view_form);
681
682         t->view_list = NULL;
683         t->view_filter = VIEW_ALL;
684         t->todo_view_is_up = False;
685         t->view_list_modified = False;
686 }
687
688 /*
689 **  Button action procedures manage and unmanage the "extra" stuff in the UI to
690 **  make it visible and invisible to the user.
691 */
692 static void
693 t_expand_ui_proc(Widget w, XtPointer client_data, XtPointer data) {
694         ToDo            *t = (ToDo *)client_data;
695         Props_pu        *p = (Props_pu *)t->cal->properties_pu;
696         XmString        xmstr;
697         Dimension       h1, h2;
698         Dimension       h, height, width;
699         static Boolean  expand_state_closed = True;
700
701         /* This is really hokey.  There is a problem in the Motif code 
702            that figures out traversals.  In the case of the appointment 
703            editor, when the widgets are traversed, that the appointment 
704            editor is them expanded, the traversal list is left in an 
705            incorrect state.  The only way to straighten this out is 
706            to trick the traversal code into re-evaluating the traversal 
707            list.  We do this by setting one of the forms insensitive, 
708            and then back to sensitive.  There is no visual impact, and 
709            it seems to work.  Do *not* remove these calls to 
710            XtSetSensitive(), of the synlib tests will stop working. */
711
712         XtVaGetValues(t->todo_list_sw, XmNwidth, &width, NULL);
713         if (expand_state_closed) {
714                 Widget  children[2];
715
716                 if (!t->reminders.bfpm_form_mgr)
717                         t_build_expand(t);
718
719                 XtRealizeWidget(t->rfp.rfp_form_mgr);
720                 XtRealizeWidget(t->reminders.bfpm_form_mgr);
721
722                 XtSetSensitive(t->rfp.rfp_form_mgr, False);
723
724                 xmstr = XmStringCreateLocalized(catgets(t->cal->DT_catd, 1, 625,
725                                                         "Less"));
726                 XtVaSetValues(t->expand_ui_button, XmNlabelString, xmstr,
727                               NULL);
728                 XmStringFree(xmstr);
729
730                 XtVaGetValues(t->rfp.rfp_form_mgr, XmNheight, &h1, NULL);
731                 XtVaGetValues(t->reminders.bfpm_form_mgr, XmNheight, &h2, NULL);
732                 h = ( h1 > h2 ) ? h1 : h2;
733                 XtVaSetValues(t->separator1, XmNbottomOffset, h + 10, NULL);
734
735                 children[0] = t->rfp.rfp_form_mgr;
736                 children[1] = t->reminders.bfpm_form_mgr;
737
738                 XtManageChildren(children, 2);
739                 if (t->reminders.bfpm_form_mgr) {
740                         set_rfp_defaults(&t->rfp);
741                         set_reminders_defaults(&t->reminders);
742                 }
743
744                 expand_state_closed = False;
745         } else {
746                 XtSetSensitive(t->rfp.rfp_form_mgr, False);
747                 xmstr = XmStringCreateLocalized(catgets(t->cal->DT_catd, 1, 626,
748                                                         "More"));
749                 XtVaSetValues(t->expand_ui_button, XmNlabelString, xmstr,
750                               NULL);
751                 XmStringFree(xmstr);
752                 XtUnmanageChild(t->rfp.rfp_form_mgr);
753                 XtUnmanageChild(t->reminders.bfpm_form_mgr);
754                 XtVaSetValues(t->separator1, XmNbottomOffset, 0, NULL);
755                 expand_state_closed = True;
756         }
757         XtVaSetValues(t->todo_list_sw, XmNwidth, width, NULL);
758         XtSetSensitive(t->rfp.rfp_form_mgr, True);
759 }
760
761 static Boolean
762 first_line_contains_text(char *str) {
763
764         if (!str)
765                 return(False);
766
767         while (*str && *str != '\n') {
768                 if (*str != ' ' && *str != '\t')
769                         return(True);
770
771                 str++;
772         }
773
774         return(False);
775 }
776 /*
777 **  This function will consume form values and stuff them into an appointment.
778 */
779 static Dtcm_appointment*
780 t_form_to_appt(ToDo *t) {
781         boolean_t               all_ok;
782         Dtcm_appointment        *appt;
783         char                    *str;
784         Calendar                *c = t->cal;
785         Props_pu                *p = (Props_pu *)t->cal->properties_pu;
786
787         if (t->cal->general->version < DATAVER4)
788                 appt = allocate_appt_struct(appt_write, t->cal->general->version, 
789                                 CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER_I,
790                                 CSA_ENTRY_ATTR_LAST_UPDATE_I,
791                                 CSA_ENTRY_ATTR_ORGANIZER_I,
792                                 CSA_ENTRY_ATTR_START_DATE_I,
793                                 CSA_ENTRY_ATTR_TYPE_I,
794                                 CSA_ENTRY_ATTR_CLASSIFICATION_I,
795                                 CSA_ENTRY_ATTR_END_DATE_I,
796                                 CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,
797                                 CSA_ENTRY_ATTR_SUMMARY_I,
798                                 CSA_ENTRY_ATTR_STATUS_I,
799                                 CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I,
800                                 CSA_X_DT_ENTRY_ATTR_REPEAT_TIMES_I,
801                                 CSA_X_DT_ENTRY_ATTR_REPEAT_INTERVAL_I,
802                                 CSA_X_DT_ENTRY_ATTR_REPEAT_OCCURRENCE_NUM_I,
803                                 CSA_ENTRY_ATTR_AUDIO_REMINDER_I,
804                                 CSA_ENTRY_ATTR_FLASHING_REMINDER_I,
805                                 CSA_ENTRY_ATTR_MAIL_REMINDER_I,
806                                 CSA_ENTRY_ATTR_POPUP_REMINDER_I,
807                                 NULL);
808         else
809                 appt = allocate_appt_struct(appt_write, t->cal->general->version, 
810                                 CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER_I,
811                                 CSA_ENTRY_ATTR_LAST_UPDATE_I,
812                                 CSA_ENTRY_ATTR_ORGANIZER_I,
813                                 CSA_ENTRY_ATTR_START_DATE_I,
814                                 CSA_ENTRY_ATTR_TYPE_I,
815                                 CSA_ENTRY_ATTR_CLASSIFICATION_I,
816                                 CSA_ENTRY_ATTR_END_DATE_I,
817                                 CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,
818                                 CSA_ENTRY_ATTR_SUMMARY_I,
819                                 CSA_ENTRY_ATTR_STATUS_I,
820                                 CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I,
821                                 CSA_X_DT_ENTRY_ATTR_REPEAT_TIMES_I,
822                                 CSA_X_DT_ENTRY_ATTR_REPEAT_INTERVAL_I,
823                                 CSA_X_DT_ENTRY_ATTR_REPEAT_OCCURRENCE_NUM_I,
824                                 CSA_ENTRY_ATTR_AUDIO_REMINDER_I,
825                                 CSA_ENTRY_ATTR_FLASHING_REMINDER_I,
826                                 CSA_ENTRY_ATTR_MAIL_REMINDER_I,
827                                 CSA_ENTRY_ATTR_POPUP_REMINDER_I,
828                                 CSA_ENTRY_ATTR_RECURRENCE_RULE_I,
829                                 NULL);
830
831         /* We have a special case in the "todo" department here.  The 
832            dialog only has the concept of a start time.  The backing 
833            widget structure dssw.* has an end time defined in it, and 
834            the generic routine dssw_form_to_appt() wants to check it's 
835            value.  Not good, as the unused widget may have an illegal 
836            value left around in it.  To get around this problem, before 
837            grabbing the results out of the form, we will copy the 
838            "start time" value into the "end time" value.  This will 
839            make the check come out OK, and the duration appear to be 0. */
840
841         str = XmTextGetString(t->dssw.start_text);
842         XmTextSetString(t->dssw.stop_text, str);
843         XtFree(str);
844         XmToggleButtonSetState(t->dssw.stop_am, XmToggleButtonGetState(t->dssw.start_am), True);
845         XmToggleButtonSetState(t->dssw.stop_pm, XmToggleButtonGetState(t->dssw.start_pm), True);
846
847         /* For todo items, since no time shows up in the todo dialog 
848            item chooser dialog, we really need the first line of the 
849            summary to contain some text, otherwise there isn't anything 
850            visible to choose.  Check that here. */
851
852         str = XmTextGetString(t->dssw.what_text);
853         if (!first_line_contains_text(str)) {
854                 char *title = XtNewString(catgets(c->DT_catd, 1, 837, "Calendar : Error - To Do Editor"));
855                 char *text = XtNewString(catgets(c->DT_catd, 1, 913,
856                                 "A To Do item must have text in the first line of the What item."));
857                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
858                 dialog_popup(t->frame,
859                         DIALOG_TITLE, title,
860                         DIALOG_TEXT, text,
861                         BUTTON_IDENT, 1, ident1,
862                         DIALOG_IMAGE, p->xm_error_pixmap,
863                         NULL);
864                 XtFree(ident1);
865                 XtFree(text);
866                 XtFree(title);
867                 XtFree(str);
868                 return(NULL);
869         }
870         XtFree(str);
871
872         /* 
873          * Type needs to be set before dssw_form_to_appt() to insure
874          * correct error message is used.
875          */
876         appt->type->value->item.sint32_value = CSA_TYPE_TODO;
877
878
879         all_ok = dssw_form_to_appt(&t->dssw, appt,
880                 t->cal->view->current_calendar, t->cal->view->date);
881         if (all_ok)
882                 all_ok = rfp_form_to_appt(&t->rfp, appt,
883                                           t->cal->view->current_calendar);
884         if (all_ok)
885                 all_ok = reminders_form_to_appt(&t->reminders, appt,
886                                           t->cal->view->current_calendar);
887
888         if (!all_ok) {
889                 free_appt_struct(&appt);
890                 return(NULL);
891         }
892
893         /* for todo appointments, we want to make sure that any reminder 
894            other than the mail reminder is not set up.  This can happen 
895            if the users default reminders have been set in this way. */
896
897
898         if (appt->beep->name) {
899                 free(appt->beep->name);
900                 appt->beep->name = NULL;
901         }
902
903         if (appt->flash->name) {
904                 free(appt->flash->name);
905                 appt->flash->name = NULL;
906         }
907
908         if (appt->popup->name) {
909                 free(appt->popup->name);
910                 appt->popup->name = NULL;
911         }
912
913         t->completed_val = XmToggleButtonGadgetGetState(t->completed_toggle);
914
915         appt->state->value->item.sint32_value = (t->completed_val) ?
916                 CSA_STATUS_COMPLETED : CSA_X_DT_STATUS_ACTIVE;
917         appt->show_time->value->item.sint32_value = True;
918
919         return appt;
920 }
921
922 /*
923 **  Action procedures
924 */
925 static void
926 t_insert_proc(Widget w, XtPointer client_data, XtPointer data) {
927         int                     wk;
928         ToDo                    *t = (ToDo *)client_data;
929         Props_pu                *p = (Props_pu *)t->cal->properties_pu;
930         CSA_entry_handle        new_a;
931         CSA_return_code         stat;
932         Dtcm_appointment        *appt;
933         CSA_enum                scope;
934         static int              answer;
935         Repeat_menu_op   op = ONE_TIME;
936         RFP             *rfp = &t->rfp;
937         Calendar        *c = t->cal;
938
939         _DtTurnOnHourGlass(t->frame);
940         if ((appt = t_form_to_appt(t)) == NULL) {
941                 _DtTurnOffHourGlass(t->frame);
942                 return;
943         }
944
945         /* the gui does not support specifying the sequence end date */
946         if (appt->sequence_end_date && appt->sequence_end_date->name) {
947                 free(appt->sequence_end_date->name);
948                 appt->sequence_end_date->name = NULL;
949         }
950         /*
951         **  First, get the value on the repeat menu
952         */
953         answer = 2;
954         if (rfp->repeat_menu)
955           op = rfp->repeat_type;
956         else
957           op = ONE_TIME;
958
959         if (op != ONE_TIME) {
960                 char *title = XtNewString(catgets(c->DT_catd, 1, 1102,
961                                         "Insert To Do"));
962                 char *text = XtNewString(catgets(c->DT_catd, 1, 1103,
963                                         "This To Do is part of a repeating series.\nDo you want to insert the item ...?"));
964                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
965                 char *ident4 = XtNewString(catgets(c->DT_catd, 1, 272, "All"));
966                 answer = dialog_popup(c->frame,
967                                 DIALOG_TITLE, title,
968                                 DIALOG_TEXT, text,
969                                 BUTTON_IDENT, 1, ident1,
970                                 BUTTON_IDENT, 4, ident4,
971                                 DIALOG_IMAGE, p->xm_question_pixmap,
972                                 NULL);
973                 XtFree(ident4);
974                 XtFree(ident1);
975                 XtFree(text);
976                 XtFree(title);
977         }
978
979         switch(answer) {
980         case 1:
981                 /*
982                  * Free the CSA_buffer here since before, this routine
983                  * only returned false when failure to obtain the CSA_structure
984                  * occurred.
985                  */
986                 _DtTurnOffHourGlass(t->frame);
987                 return;
988         case 4:
989         default:
990                 /*
991                  * scope is not used at this time.  However, to follow
992                  * the change/delete style, this is here so in case
993                  * later the same type of dialog is required.
994                  */
995                 scope = CSA_SCOPE_ALL;
996                 break;
997         }
998
999         stat = csa_add_entry(t->cal->cal_handle, appt->count, appt->attrs, &new_a, NULL);
1000         backend_err_msg(t->frame, t->cal->view->current_calendar, stat,
1001                         p->xm_error_pixmap);
1002         free_appt_struct(&appt);
1003         if (stat != CSA_SUCCESS) {
1004                 _DtTurnOffHourGlass(t->frame);
1005                 return;
1006         }
1007         csa_free((CSA_buffer) new_a);
1008
1009         set_todo_msg_defaults(t);
1010         add_all_todo(t);
1011         if (todo_view_showing(t))
1012                 build_todo_view(t, t->cal->view->glance, False);
1013         reset_alarm(t->cal);
1014         invalidate_cache(t->cal);
1015         _DtTurnOffHourGlass(t->frame);
1016 }
1017
1018 static void
1019 t_delete_proc(Widget w, XtPointer client_data, XtPointer data) {
1020         int                     *item_list = NULL, item_cnt = 0;
1021         ToDo                    *t = (ToDo *)client_data;
1022         Calendar                *c = t->cal;
1023         Props_pu                *p = (Props_pu *)t->cal->properties_pu;
1024         CSA_entry_handle        entry;
1025         CSA_return_code         stat;
1026         CSA_enum                scope;
1027         Dtcm_appointment        *appt;
1028         static int              answer;
1029
1030         _DtTurnOnHourGlass(t->frame);
1031         if (!XmListGetSelectedPos(t->todo_list, &item_list, &item_cnt)) {
1032                 char *title = XtNewString(catgets(c->DT_catd, 1, 566, "Calendar : Error - To Do Editor"));
1033                 char *text = XtNewString(catgets(c->DT_catd, 1, 567,
1034                                 "Select a To Do and DELETE again."));
1035                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
1036                 answer = dialog_popup(t->frame,
1037                         DIALOG_TITLE, title,
1038                         DIALOG_TEXT, text,
1039                         BUTTON_IDENT, 1, ident1,
1040                         DIALOG_IMAGE, p->xm_error_pixmap,
1041                         NULL);
1042                 XtFree(ident1);
1043                 XtFree(text);
1044                 XtFree(title);
1045                 _DtTurnOffHourGlass(t->frame);
1046                 return;
1047         } 
1048
1049         if (!(entry = t_nth_appt(t, item_list[0] - 1))) {
1050                 char *title = XtNewString(catgets(c->DT_catd, 1, 566, "Calendar : Error - To Do Editor"));
1051                 char *text = XtNewString(catgets(c->DT_catd, 1, 570,
1052                                 "Internal error selecting To Do.\nTo Do was not deleted."));
1053                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
1054                 answer = dialog_popup(t->frame,
1055                         DIALOG_TITLE, title,
1056                         DIALOG_TEXT, text,
1057                         BUTTON_IDENT, 1, ident1,
1058                         DIALOG_IMAGE, p->xm_error_pixmap,
1059                         NULL);
1060                 XtFree(ident1);
1061                 XtFree(text);
1062                 XtFree(title);
1063                 XtFree((XtPointer)item_list);
1064                 _DtTurnOffHourGlass(t->frame);
1065                 return;
1066         }
1067         XtFree((XtPointer)item_list);
1068
1069         answer = 0;
1070         appt = allocate_appt_struct(appt_read, 
1071                                         c->general->version,
1072                                         CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I, 
1073                                         NULL);
1074         stat = query_appt_struct(c->cal_handle, entry, appt);
1075         backend_err_msg(t->frame, c->view->current_calendar, stat,
1076                         p->xm_error_pixmap);
1077         if (stat != CSA_SUCCESS) {
1078                 free_appt_struct(&appt);
1079                 _DtTurnOffHourGlass(t->frame);
1080                 return;
1081         }
1082
1083         if (appt->repeat_type->value) {
1084                 if (appt->repeat_type->value->item.sint32_value !=
1085                     CSA_X_DT_REPEAT_ONETIME) {
1086                   char *title = XtNewString(catgets(c->DT_catd, 1, 591, "Calendar : To Do Editor"));
1087                   char *text = XtNewString(catgets(c->DT_catd, 1, 573,
1088                                         "This To Do is part of a repeating series.\nDo you want to delete ...?"));
1089                   char *ident1 = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
1090                   char *ident2 = XtNewString(catgets(c->DT_catd, 1, 270,
1091                                         "This One Only"));
1092                   char *ident3 = XtNewString(catgets(c->DT_catd, 1, 271, "Forward"));
1093                   char *ident4 = XtNewString(catgets(c->DT_catd, 1, 272, "All"));
1094                 answer = dialog_popup(t->frame,
1095                                 DIALOG_TITLE, title,
1096                                 DIALOG_TEXT, text,
1097                                 BUTTON_IDENT, 1, ident1,
1098                                 BUTTON_IDENT, 2, ident2,
1099                                 BUTTON_IDENT, 3, ident3,
1100                                 BUTTON_IDENT, 4, ident4,
1101                                 DIALOG_IMAGE, p->xm_question_pixmap,
1102                                 NULL);
1103                   XtFree(ident4);
1104                   XtFree(ident3);
1105                   XtFree(ident2);
1106                   XtFree(ident1);
1107                   XtFree(text);
1108                   XtFree(title);
1109               }
1110         }
1111         else if (appt->recurrence_rule->value) {
1112                 char *title = XtNewString(catgets(c->DT_catd, 1, 591,
1113                                         "Calendar : To Do Editor"));
1114                 char *text = XtNewString(catgets(c->DT_catd, 1, 791,
1115                                         "This To Do repeats in an unknown fashion.  All occurrences will be changed\nDo you still wish to delete it?"));
1116                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
1117                 char *ident4 = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
1118                 answer = dialog_popup(c->frame,
1119                                 DIALOG_TITLE, title,
1120                                 DIALOG_TEXT, text,
1121                                 BUTTON_IDENT, 1, ident1,
1122                                 BUTTON_IDENT, 4, ident4,
1123                                 DIALOG_IMAGE, p->xm_question_pixmap,
1124                                 NULL);
1125                 XtFree(ident4);
1126                 XtFree(ident1);
1127                 XtFree(text);
1128                 XtFree(title);
1129         }
1130         free_appt_struct(&appt);
1131
1132         switch(answer) {
1133         case 1:
1134                 _DtTurnOffHourGlass(t->frame);
1135                 return;
1136         case 2:
1137                 scope = CSA_SCOPE_ONE;
1138                 break;
1139         case 3:
1140                 scope = CSA_SCOPE_FORWARD;
1141                 break;
1142         case 4:
1143         default:
1144                 scope = CSA_SCOPE_ALL;
1145                 break;
1146         }
1147
1148         stat = csa_delete_entry(t->cal->cal_handle, entry, scope, NULL);
1149         backend_err_msg(t->frame, t->cal->view->current_calendar, stat,
1150                         p->xm_error_pixmap);    
1151
1152         set_todo_msg_defaults(t);
1153         add_all_todo(t);
1154         if (todo_view_showing(t))
1155                 build_todo_view(t, t->cal->view->glance, False);
1156         reset_alarm(t->cal);
1157         invalidate_cache(t->cal);
1158         _DtTurnOffHourGlass(t->frame);
1159 }
1160
1161 /*
1162 **  Static function actually does the change - used by the editor and the view
1163 **  list.
1164 */
1165 static CSA_return_code
1166 t_execute_change(ToDo *t, CSA_entry_handle old_a, Dtcm_appointment *new_a,
1167                  Widget frame) {
1168         Calendar                *c = t->cal;
1169         Props_pu                *p = (Props_pu *)t->cal->properties_pu;
1170         CSA_entry_handle        updated_a;
1171         CSA_return_code         stat;
1172         CSA_enum                scope;
1173         Dtcm_appointment        *appt;
1174         static int              answer;
1175
1176         answer = 0;
1177         appt = allocate_appt_struct(appt_read,
1178                                     c->general->version,
1179                                     CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I,
1180                                     CSA_X_DT_ENTRY_ATTR_REPEAT_TIMES_I,
1181                                     CSA_X_DT_ENTRY_ATTR_REPEAT_INTERVAL_I,
1182                                     CSA_X_DT_ENTRY_ATTR_REPEAT_OCCURRENCE_NUM_I,
1183                                     CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER_I,
1184                                     CSA_ENTRY_ATTR_START_DATE_I,
1185                                     CSA_ENTRY_ATTR_RECURRENCE_RULE_I,
1186                                     NULL);
1187         stat = query_appt_struct(c->cal_handle, old_a, appt);
1188         backend_err_msg(t->frame, c->view->current_calendar, stat,
1189                         p->xm_error_pixmap);
1190         if (stat != CSA_SUCCESS) {
1191                 free_appt_struct(&appt);
1192                 return stat;
1193         }
1194
1195         if ((appt->repeat_type->value->item.sint32_value == CSA_X_DT_REPEAT_OTHER) ||
1196             (appt->repeat_type->value->item.sint32_value == CSA_X_DT_REPEAT_OTHER_WEEKLY) ||
1197             (appt->repeat_type->value->item.sint32_value == CSA_X_DT_REPEAT_OTHER_MONTHLY) ||
1198             (appt->repeat_type->value->item.sint32_value == CSA_X_DT_REPEAT_OTHER_YEARLY)) {
1199                 char *title = XtNewString(catgets(c->DT_catd, 1, 591,
1200                                         "Calendar : To Do Editor"));
1201                 char *text = XtNewString(catgets(c->DT_catd, 1, 708,
1202                                         "This appointment repeats in an unknown fashion.  All occurrences will be changed\nDo you still wish to change it?"));
1203                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
1204                 char *ident4 = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
1205                 answer = dialog_popup(c->frame,
1206                                 DIALOG_TITLE, title,
1207                                 DIALOG_TEXT, text,
1208                                 BUTTON_IDENT, 1, ident1,
1209                                 BUTTON_IDENT, 4, ident4,
1210                                 DIALOG_IMAGE, p->xm_question_pixmap,
1211                                 NULL);
1212                 XtFree(ident4);
1213                 XtFree(ident1);
1214                 XtFree(text);
1215                 XtFree(title);
1216         }
1217         else if (appt->repeat_type->value->item.sint32_value != 
1218                 CSA_X_DT_REPEAT_ONETIME) {
1219                 char *title = XtNewString(catgets(c->DT_catd, 1, 591, "Calendar : To Do Editor"));
1220                 char *text = XtNewString(catgets(c->DT_catd, 1, 579,
1221                                 "This To Do is part of a repeating series.\nDo you want to change ...?"));
1222                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
1223                 char *ident2 = XtNewString(catgets(c->DT_catd, 1, 270,
1224                                 "This One Only"));
1225                 char *ident3 = XtNewString(catgets(c->DT_catd, 1, 271, "Forward"));
1226                 char *ident4 = XtNewString(catgets(c->DT_catd, 1, 272, "All"));
1227                 answer = dialog_popup(frame,
1228                         DIALOG_TITLE, title,
1229                         DIALOG_TEXT, text,
1230                         BUTTON_IDENT, 1, ident1,
1231                         BUTTON_IDENT, 2, ident2,
1232                         BUTTON_IDENT, 3, ident3,
1233                         (compare_repeat_info(appt, &(t->rfp), c->cal_handle, c->general->version) ?
1234                                 BUTTON_IDENT : BUTTON_INSENSITIVE),
1235                                         4, ident4,
1236                         DIALOG_IMAGE, p->xm_question_pixmap,
1237                         NULL);
1238                 XtFree(ident4);
1239                 XtFree(ident3);
1240                 XtFree(ident2);
1241                 XtFree(ident1);
1242                 XtFree(text);
1243                 XtFree(title);
1244                 if (answer == 2)
1245                         change_rule_for_this_one_only(c, new_a, appt);
1246         }
1247
1248         switch(answer) {
1249         case 1:
1250                 free_appt_struct(&appt);
1251                 return CSA_E_FAILURE;
1252         case 2:
1253                 scope = CSA_SCOPE_ONE;
1254                 break;
1255         case 3:
1256                 scope = CSA_SCOPE_FORWARD;
1257                 break;
1258         case 4:
1259         default:
1260                 scope = CSA_SCOPE_ALL;
1261                 break;
1262         }
1263
1264         /* We are not allowed to change the type of the entry, so we will
1265            remove that particular entry from the list for writing. */
1266  
1267         if (new_a->type) {
1268                 if (new_a->type->name){
1269                         free(new_a->type->name);
1270                         new_a->type->name = NULL;
1271                 }
1272         }
1273
1274         /* if the repeat type/times is changed, reset the sequence end date */
1275         if (c->general->version == DATAVER3 &&
1276             appt->repeat_type->value->item.sint32_value !=
1277             CSA_X_DT_REPEAT_ONETIME &&
1278             (appt->repeat_type->value->item.sint32_value !=
1279              new_a->repeat_type->value->item.sint32_value ||
1280              appt->repeat_times->value->item.uint32_value !=
1281              new_a->repeat_times->value->item.uint32_value))
1282         {
1283                 if (new_a->sequence_end_date && new_a->sequence_end_date->value)
1284                 {
1285                         if (new_a->sequence_end_date->value->item.date_time_value)
1286                                 free(new_a->sequence_end_date->value->\
1287                                         item.date_time_value);
1288                         free(new_a->sequence_end_date->value);
1289                         new_a->sequence_end_date->value = NULL;
1290                 }
1291         } else {
1292                 if (new_a->sequence_end_date && new_a->sequence_end_date->name)
1293                 {
1294                         free (new_a->sequence_end_date->name);
1295                         new_a->sequence_end_date->name = NULL;
1296                 }
1297         }
1298
1299         free_appt_struct(&appt);
1300
1301         stat = csa_update_entry_attributes(c->cal_handle, old_a, scope, CSA_FALSE, new_a->count, new_a->attrs, &updated_a, NULL);
1302         backend_err_msg(t->frame, c->view->current_calendar, stat,
1303                         p->xm_error_pixmap);
1304         if (stat != CSA_SUCCESS)
1305                 return stat;
1306         csa_free((CSA_buffer) updated_a);
1307
1308         if (todo_showing(t)) {
1309                 set_todo_msg_defaults(t);
1310                 add_all_todo(t);
1311         }
1312         if (todo_view_showing(t))
1313                 build_todo_view(t, c->view->glance, False);
1314         reset_alarm(c);
1315         invalidate_cache(t->cal);
1316
1317         return stat;
1318 }
1319
1320 static void
1321 t_view_change_proc(Widget w, XtPointer cdata, XtPointer cbs) {
1322         ToDo                    *t = (ToDo *)cdata;
1323         TodoView                *step = t->view_list;
1324
1325         while (step) {
1326                 if (step->view_item_toggle == w) {
1327                         step->modified = True;
1328                         t->view_list_modified = True;
1329                         return;
1330                 }
1331                 step = step->next;
1332         }
1333 }
1334
1335 static void
1336 t_change_proc(Widget w, XtPointer client_data, XtPointer data) {
1337         int                     *item_list = NULL, item_cnt = 0;
1338         ToDo                    *t = (ToDo *)client_data;
1339         Calendar                *c = t->cal;
1340         Props_pu                *p = (Props_pu *)t->cal->properties_pu;
1341         CSA_entry_handle        old_a;
1342         Dtcm_appointment        *new_a;
1343         static int              answer;
1344
1345         _DtTurnOnHourGlass(t->frame);
1346         if (!XmListGetSelectedPos(t->todo_list, &item_list, &item_cnt)) {
1347                 char *title = XtNewString(catgets(c->DT_catd, 1, 566, "Calendar : Error - To Do Editor"));
1348                 char *text = XtNewString(catgets(c->DT_catd, 1, 585,
1349                                 "Select a To Do and CHANGE again."));
1350                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
1351                 answer = dialog_popup(t->frame,
1352                         DIALOG_TITLE, title,
1353                         DIALOG_TEXT, text,
1354                         BUTTON_IDENT, 1, ident1,
1355                         DIALOG_IMAGE, p->xm_error_pixmap,
1356                         NULL);
1357                 XtFree(ident1);
1358                 XtFree(text);
1359                 XtFree(title);
1360                 _DtTurnOffHourGlass(t->frame);
1361                 return;
1362         } 
1363
1364         if (!(old_a = t_nth_appt(t, item_list[0] - 1))) {
1365                 char *title = XtNewString(catgets(c->DT_catd, 1, 566, "Calendar : Error - To Do Editor"));
1366                 char *text = XtNewString(catgets(c->DT_catd, 1, 1009,
1367                                 "Internal error selecting To Do.\nTo Do was not changed."));
1368                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
1369                 answer = dialog_popup(t->frame,
1370                         DIALOG_TITLE, title,
1371                         DIALOG_TEXT, text,
1372                         BUTTON_IDENT, 1, ident1,
1373                         DIALOG_IMAGE, p->xm_error_pixmap,
1374                         NULL);
1375                 XtFree(ident1);
1376                 XtFree(text);
1377                 XtFree(title);
1378                 XtFree((XtPointer)item_list);
1379                 _DtTurnOffHourGlass(t->frame);
1380                 return;
1381         }
1382         XtFree((XtPointer)item_list);
1383
1384         if ((new_a = t_form_to_appt(t)) != NULL) {
1385                 t_execute_change(t, old_a, new_a, t->frame);
1386                 free_appt_struct(&new_a);
1387         }
1388
1389         _DtTurnOffHourGlass(t->frame);
1390 }
1391
1392 static void
1393 t_clear_proc(Widget w, XtPointer client_data, XtPointer data) {
1394         ToDo *t = (ToDo *)client_data;
1395
1396         set_todo_defaults(t);
1397         add_all_todo(t);
1398 }
1399
1400 static void
1401 t_close_proc(Widget w, XtPointer client_data, XtPointer data) {
1402         ToDo *t = (ToDo *)client_data;
1403
1404         XtPopdown(t->frame);
1405         t->todo_is_up = False;
1406 }
1407
1408 static void
1409 t_quit_handler(Widget w, XtPointer cdata, XtPointer data) {
1410         ToDo *t = (ToDo *)cdata;
1411
1412         todo_clean_up(t);
1413         XtPopdown(t->frame);
1414         t->todo_is_up = False;
1415 }
1416
1417
1418 /*
1419  * dragMotionHandler
1420  *
1421  * Determine if the pointer has moved beyond the drag threshold while button 1
1422  * was being held down.
1423  */
1424 static void
1425 FormApptDragMotionHandler(
1426         Widget          dragInitiator,
1427         XtPointer       clientData,
1428         XEvent         *event)
1429 {
1430         int             diffX, diffY;
1431         Calendar        *c = (Calendar *) clientData;
1432         ToDo            *t = (ToDo *) c->todo;
1433         Dimension       source_height, source_width;
1434         Position        source_x, source_y;
1435  
1436         if (!t->doing_drag) {
1437
1438                 /* check to see if the iniital value was within the 
1439                    bounds for the drag source icon. */
1440
1441                 XtVaGetValues(t->drag_source, 
1442                                 XmNx, &source_x,
1443                                 XmNy, &source_y,
1444                                 XmNheight, &source_height,
1445                                 XmNwidth, &source_width,
1446                                 NULL);
1447
1448                 if ((event->xmotion.x < source_x) ||
1449                     (event->xmotion.y < source_y) ||
1450                     (event->xmotion.x > (int) (source_x + source_width)) ||
1451                     (event->xmotion.y > (int) (source_y + source_height)))
1452                         return;
1453
1454                 /*
1455                  * If the drag is just starting, set initial button down coords
1456                  */
1457                 if (t->initialX == -1 && t->initialY == -1) {
1458                         t->initialX = event->xmotion.x;
1459                         t->initialY = event->xmotion.y;
1460                 }
1461                 /*
1462                  * Find out how far pointer has moved since button press
1463                  */
1464                 diffX = t->initialX - event->xmotion.x;
1465                 diffY = t->initialY - event->xmotion.y;
1466  
1467                 if ((ABS(diffX) >= DRAG_THRESHOLD) ||
1468                     (ABS(diffY) >= DRAG_THRESHOLD)) {
1469                         t->doing_drag = True;
1470                         ApptDragStart(dragInitiator, event, c, TodoEditorIcon);
1471                         t->initialX = -1;
1472                         t->initialY = -1;
1473                 }
1474         }
1475 }
1476
1477 extern void
1478 t_make_todo(Calendar *c)
1479 {
1480         int             cnt = 0;
1481         Arg             args[15];
1482         ToDo            *t = (ToDo *)c->todo;
1483         Props_pu        *p = (Props_pu *)c->properties_pu;
1484         XmString        xmstr;
1485         Dimension       highest, widest;
1486         Widget          prev, curr;
1487         Dimension       _toLabel, _toText, _toMenu, _toRC;
1488         Dimension       label_height,
1489                         max_left_label_width;
1490         Boolean         btn1_transfer;
1491         XtTranslations  new_translations;
1492         XFontSetExtents listfontextents;
1493         static char     translations[] = "\
1494                 ~c ~s ~m ~a <Btn1Down>:\
1495                  dtcm-process-press(ListBeginSelect,TranslationDragStart)\n\
1496                 c ~s ~m ~a <Btn1Down>:\
1497                  dtcm-process-press(ListBeginToggle,TranslationDragStart)";
1498         static char     btn2_translations[] = "\
1499                 ~c ~s ~m ~a <Btn2Down>:\
1500                  dtcm-process-press(ListBeginSelect,TranslationDragStart)\n\
1501                 c ~s ~m ~a <Btn2Down>:\
1502                  dtcm-process-press(ListBeginToggle,TranslationDragStart)\n\
1503                 <Btn2Motion>:ListButtonMotion()\n\
1504                 ~c ~s ~m ~a <Btn2Up>:ListEndSelect()\n\
1505                 c ~s ~m ~a <Btn2Up>:ListEndToggle()";
1506         WidgetList      children;
1507         Widget          widgets[20];
1508         int             i = 0,
1509                         j = 0,
1510                         n;
1511         
1512
1513         new_translations = XtParseTranslationTable(translations);
1514
1515         t->cal = c;
1516
1517         /*
1518         **  Dialog shell and the base form
1519         */
1520         t->frame = XtVaCreatePopupShell("frame",
1521                 xmDialogShellWidgetClass, t->cal->frame,
1522                 XmNdeleteResponse,      XmDO_NOTHING,
1523                 XmNallowShellResize,    True,
1524                 XmNmappedWhenManaged,   False,
1525                 NULL);
1526         set_todo_title(t, c->view->current_calendar);
1527         setup_quit_handler(t->frame, t_quit_handler, (caddr_t)t);
1528
1529         t->base_form_mgr = XtVaCreateWidget("base_form_mgr",
1530                 xmFormWidgetClass,      t->frame,
1531                 XmNautoUnmanage,        False,
1532                 XmNfractionBase,        15,
1533                 NULL);
1534
1535         /*
1536         **  Build the stuff in the upper portion of the form
1537         */
1538
1539         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 797, "To Do"));
1540         t->list_label = XtVaCreateWidget("todo_label",
1541                 xmLabelGadgetClass,     t->base_form_mgr,
1542                 XmNtopAttachment,       XmATTACH_FORM,
1543                 XmNtopOffset,           5,
1544                 XmNlabelString,         xmstr,
1545                 NULL);
1546         XmStringFree(xmstr);
1547
1548         XtVaGetValues(t->list_label, XmNheight, &label_height, NULL);
1549
1550         t->message_text = XtVaCreateWidget("message",
1551                 xmLabelGadgetClass,     t->base_form_mgr,
1552                 XmNshadowThickness,     0,
1553                 XmNcursorPositionVisible, False,
1554                 XmNresizeWidth,         True,
1555                 XmNalignment,           XmALIGNMENT_BEGINNING,
1556                 XmNbottomAttachment,    XmATTACH_FORM,
1557                 XmNbottomOffset,        2,
1558                 XmNleftAttachment,      XmATTACH_FORM,
1559                 XmNleftOffset,          2,
1560                 XmNrightAttachment,     XmATTACH_FORM,
1561                 XmNrightOffset,         2,
1562                 NULL);
1563
1564         /*
1565         **  Create insert, delete, change, and clear buttons
1566         */
1567         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 342, "Insert"));
1568         t->insert_button = XtVaCreateWidget("insert",
1569                 xmPushButtonWidgetClass, t->base_form_mgr,
1570                 XmNbottomAttachment,    XmATTACH_WIDGET,
1571                 XmNbottomWidget,        t->message_text,
1572                 XmNleftAttachment,      XmATTACH_POSITION,
1573                 XmNleftPosition,        1,
1574                 XmNrightAttachment,     XmATTACH_POSITION,
1575                 XmNrightPosition,       3,
1576                 XmNlabelString,         xmstr,
1577                 NULL);
1578         XtAddCallback(t->insert_button, XmNactivateCallback, t_insert_proc, t);
1579         XmStringFree(xmstr);
1580
1581         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 343, "Change"));
1582         t->change_button = XtVaCreateWidget("change",
1583                 xmPushButtonWidgetClass, t->base_form_mgr,
1584                 XmNbottomAttachment,    XmATTACH_WIDGET,
1585                 XmNbottomWidget,        t->message_text,
1586                 XmNleftAttachment,      XmATTACH_POSITION,
1587                 XmNleftPosition,        3,
1588                 XmNrightAttachment,     XmATTACH_POSITION,
1589                 XmNrightPosition,       5,
1590                 XmNlabelString,         xmstr,
1591                 XmNsensitive,           False,
1592                 NULL);
1593         XtAddCallback(t->change_button, XmNactivateCallback, t_change_proc, t);
1594         XmStringFree(xmstr);
1595  
1596         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 802, "Delete"));
1597         t->delete_button = XtVaCreateWidget("delete",
1598                 xmPushButtonWidgetClass, t->base_form_mgr,
1599                 XmNbottomAttachment,    XmATTACH_WIDGET,
1600                 XmNbottomWidget,        t->message_text,
1601                 XmNleftAttachment,      XmATTACH_POSITION,
1602                 XmNleftPosition,        5,
1603                 XmNrightAttachment,     XmATTACH_POSITION,
1604                 XmNrightPosition,       7,
1605                 XmNlabelString,         xmstr,
1606                 XmNsensitive,   False,
1607                 NULL);
1608         XtAddCallback(t->delete_button, XmNactivateCallback, t_delete_proc, t);
1609         XmStringFree(xmstr);
1610
1611         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 803, "Clear"));
1612         t->clear_button = XtVaCreateWidget("clear",
1613                 xmPushButtonWidgetClass, t->base_form_mgr,
1614                 XmNbottomAttachment,    XmATTACH_WIDGET,
1615                 XmNbottomWidget,        t->message_text,
1616                 XmNleftAttachment,      XmATTACH_POSITION,
1617                 XmNleftPosition,        7,
1618                 XmNrightAttachment,     XmATTACH_POSITION,
1619                 XmNrightPosition,       9,
1620                 XmNlabelString,         xmstr,
1621                 NULL);
1622         XtAddCallback(t->clear_button, XmNactivateCallback, t_clear_proc, t);
1623         XmStringFree(xmstr);
1624
1625         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 923, "Cancel"));
1626         t->close_button = XtVaCreateWidget("close",
1627                 xmPushButtonWidgetClass, t->base_form_mgr,
1628                 XmNbottomAttachment,    XmATTACH_WIDGET,
1629                 XmNbottomWidget,        t->message_text,
1630                 XmNleftAttachment,      XmATTACH_POSITION,
1631                 XmNleftPosition,        9,
1632                 XmNrightAttachment,     XmATTACH_POSITION,
1633                 XmNrightPosition,       11,
1634                 XmNlabelString,         xmstr,
1635                 NULL);
1636         XtAddCallback(t->close_button, XmNactivateCallback, t_close_proc, t);
1637         XmStringFree(xmstr);
1638
1639         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 77, "Help"));
1640         t->help_button = XtVaCreateWidget("help",
1641                 xmPushButtonWidgetClass, t->base_form_mgr,
1642                 XmNbottomAttachment,    XmATTACH_WIDGET,
1643                 XmNbottomWidget,        t->message_text,
1644                 XmNleftAttachment,      XmATTACH_POSITION,
1645                 XmNleftPosition,        11,
1646                 XmNrightAttachment,     XmATTACH_POSITION,
1647                 XmNrightPosition,       13,
1648                 XmNlabelString,         xmstr,
1649                 NULL);
1650         XmStringFree(xmstr);
1651         XtAddCallback(t->help_button, XmNactivateCallback,
1652                 (XtCallbackProc)help_cb, TODO_EDITOR_HELP_BUTTON);
1653         XtAddCallback(t->base_form_mgr, XmNhelpCallback,
1654                 (XtCallbackProc)help_cb, (XtPointer) TODO_EDITOR_HELP_BUTTON);
1655
1656
1657         t->separator2 = XtVaCreateWidget("separator2",
1658                 xmSeparatorGadgetClass, t->base_form_mgr,
1659                 XmNbottomAttachment,    XmATTACH_WIDGET,
1660                 XmNbottomWidget,        t->insert_button,
1661                 XmNbottomOffset,        5,
1662                 XmNleftAttachment,      XmATTACH_FORM,
1663                 XmNleftOffset,          5,
1664                 XmNrightAttachment,     XmATTACH_FORM,
1665                 XmNrightOffset,         5,
1666                 NULL);
1667
1668         t->separator1 = XtVaCreateWidget("separator1",
1669                 xmSeparatorGadgetClass, t->base_form_mgr,
1670                 XmNleftAttachment,      XmATTACH_FORM,
1671                 XmNleftOffset,          5,
1672                 XmNrightAttachment,     XmATTACH_FORM,
1673                 XmNrightOffset,         5,
1674                 XmNbottomAttachment,    XmATTACH_WIDGET,
1675                 XmNbottomWidget,        t->separator2,
1676                 NULL);
1677
1678         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 626, "More"));
1679         t->expand_ui_button = XtVaCreateWidget("expando",
1680                 xmPushButtonWidgetClass, t->base_form_mgr,
1681                 XmNlabelString,         xmstr,
1682                 XmNleftAttachment,      XmATTACH_FORM,
1683                 XmNleftOffset,          5,
1684                 XmNbottomAttachment,    XmATTACH_WIDGET,
1685                 XmNbottomWidget,        t->separator1,
1686                 XmNbottomOffset,        3,
1687                 XmNnavigationType,      XmTAB_GROUP,
1688                 NULL);
1689         XmStringFree(xmstr);
1690         XtAddCallback(t->expand_ui_button, 
1691                         XmNactivateCallback, t_expand_ui_proc, t);
1692
1693         /*
1694         **  First, manipulate the dssw widget.  Why, you ask, don't you just
1695         **  recreate the stuff you need instead of using the entire widget.
1696         **  Three reasons:  first, to re-use the methods associated with the
1697         **  dssw structure; second, in case HIE changes their mind, adjusting
1698         **  the UI is trivial; and third, if the dssw widget changes or needs
1699         **  to be fixed, the code is in one place.
1700         */
1701         build_dssw(&t->dssw, c, t->base_form_mgr, True, False);
1702
1703         xmstr = XmStringCreateLocalized(
1704                                 catgets(c->DT_catd, 1, 590, "Due Date:"));
1705         XtVaSetValues(t->dssw.date_label,
1706                 XmNlabelString, xmstr,
1707                 NULL);
1708         XmStringFree(xmstr);
1709
1710         xmstr = XmStringCreateLocalized(
1711                                 catgets(c->DT_catd, 1, 798, "Time Due:"));
1712         XtVaSetValues(t->dssw.start_label,
1713                 XmNlabelString, xmstr,
1714                 NULL);
1715         XmStringFree(xmstr);
1716
1717         _i18n_WidestWidget( 3, &curr, &max_left_label_width, t->dssw.date_label,
1718                          t->dssw.start_label, t->dssw.what_label );
1719
1720         /*
1721          * t->dssw.date_label, t->dssw.date_text
1722          */
1723         _i18n_WidestWidget( 1, &curr, &widest, t->dssw.date_label );
1724         _toLabel = max_left_label_width + 2 * 5 - 5 - widest;
1725         _toText = max_left_label_width + 2 * 5;
1726         XtVaSetValues( t->dssw.date_label,
1727                         XmNleftOffset, _toLabel,
1728                         NULL );
1729         XtVaSetValues( t->dssw.date_text,
1730                         XmNleftOffset, _toText,
1731                         NULL );
1732         /*
1733          * t->dssw.start_label, t->dssw.start_text, t->dssw.start.menu,
1734          * t->dssw.start_ampm_rc_mgr
1735          */
1736         _i18n_WidestWidget( 1, &curr, &widest, t->dssw.start_label );
1737         _toLabel = max_left_label_width + 2 * 5 - 5 - widest;
1738         _toText = max_left_label_width + 2 * 5;
1739         _i18n_WidestWidget( 1, &curr, &widest, t->dssw.start_text );
1740         _toMenu = _toText + widest + 5;
1741         _i18n_WidestWidget( 1, &curr, &widest, t->dssw.start_menu );
1742         _toRC = _toMenu + widest + 5;
1743         XtVaSetValues( t->dssw.start_label,
1744                         XmNleftOffset, _toLabel,
1745                         NULL );
1746         XtVaSetValues( t->dssw.start_text,
1747                         XmNleftOffset, _toText,
1748                         NULL );
1749         XtVaSetValues( t->dssw.start_menu,
1750                         XmNleftOffset, _toMenu,
1751                         NULL );
1752         XtVaSetValues( t->dssw.start_ampm_rc_mgr,
1753                         XmNleftOffset, _toRC,
1754                         NULL );
1755
1756         _i18n_HighestWidget( 4, &prev, &highest, t->dssw.start_label,
1757         t->dssw.start_text, t->dssw.start_menu, t->dssw.start_ampm_rc_mgr );
1758         _i18n_WidestWidget( 1, &curr, &widest, t->dssw.what_label );
1759         _toLabel = max_left_label_width + 2 * 5 - 5 - widest;
1760         _toText = max_left_label_width + 2 * 5;
1761         XtVaSetValues( t->dssw.what_label,
1762                         XmNtopAttachment, XmATTACH_WIDGET,
1763                         XmNtopWidget, prev,
1764                         XmNleftOffset, _toLabel,
1765                         NULL ); 
1766
1767         /*
1768          * Add a drag source icon inside the dssw, lower right
1769          */
1770         xmstr = XmStringCreateLocalized(
1771                                 catgets(c->DT_catd, 1, 906, "Drag To Do"));
1772         t->drag_source = XtVaCreateWidget("drag_source",
1773                 dtIconGadgetClass,      t->dssw.dssw_form_mgr,
1774                 XmNpixmapPosition,      XmPIXMAP_TOP,
1775                 XmNstringPosition,      XmSTRING_BOTTOM,
1776                 XmNalignment,           XmALIGNMENT_CENTER,
1777                 XmNstring,              xmstr,
1778                 XmNbottomAttachment,    XmATTACH_FORM,
1779                 XmNrightAttachment,     XmATTACH_FORM,
1780                 XmNtraversalOn,         False,
1781                 NULL);
1782         XmStringFree(xmstr);
1783
1784         XtVaSetValues( t->dssw.what_scrollwindow,
1785                         XmNtopAttachment, XmATTACH_WIDGET,
1786                         XmNtopWidget, prev,
1787                         XmNleftOffset, _toText,
1788                         XmNrightAttachment, XmATTACH_WIDGET,
1789                         XmNrightWidget, t->drag_source,
1790                         NULL ); 
1791
1792         XtAddEventHandler(XtParent(t->drag_source), Button1MotionMask, False,
1793                 (XtEventHandler)FormApptDragMotionHandler, (XtPointer) c);
1794         
1795         XtVaGetValues((Widget)XmGetXmDisplay(XtDisplay(c->frame)), 
1796                 "enableBtn1Transfer",   &btn1_transfer, 
1797                 NULL); 
1798
1799         /* btn1_transfer is a tri-state variable - see 1195846 */ 
1800         if ((Boolean)btn1_transfer != True)
1801                 XtAddEventHandler(XtParent(t->drag_source), 
1802                                 Button2MotionMask, False, 
1803                                 (XtEventHandler)FormApptDragMotionHandler, 
1804                                 (XtPointer) c);
1805
1806
1807
1808         XtVaSetValues(t->drag_source, XmNpixmap, p->drag_icon_xbm, NULL);
1809
1810         xmstr = XmStringCreateLocalized(
1811                                 catgets(c->DT_catd, 1, 784, "Completed"));
1812
1813         t->completed_toggle = XtVaCreateManagedWidget("completed",
1814                 xmToggleButtonGadgetClass, t->dssw.dssw_form_mgr,
1815                 XmNlabelString,         xmstr,
1816                 XmNbottomAttachment,    XmATTACH_FORM,
1817                 XmNnavigationType,      XmTAB_GROUP,
1818                 NULL);
1819         XmStringFree(xmstr);
1820
1821         _toText = max_left_label_width + 2 * 5 - 4;
1822         XtVaSetValues( t->completed_toggle,
1823                         XmNleftAttachment, XmATTACH_FORM,
1824                         XmNleftOffset, _toText,
1825                         NULL );
1826
1827         _i18n_HighestWidget( 2, &prev, &highest, t->dssw.what_label,
1828                                 t->dssw.what_scrollwindow );
1829         XtVaSetValues( prev,
1830                         XmNbottomAttachment, XmATTACH_WIDGET,
1831                         XmNbottomWidget, t->completed_toggle,
1832                         XmNbottomOffset, 10,
1833                         NULL );
1834
1835         XtVaSetValues(t->dssw.dssw_form_mgr,
1836                 XmNtopAttachment,       XmATTACH_FORM,
1837                 XmNtopOffset,           label_height + 5,
1838                 XmNleftAttachment,      XmATTACH_FORM,
1839                 XmNleftOffset,          5,
1840                 XmNbottomAttachment,    XmATTACH_WIDGET,
1841                 XmNbottomWidget,        t->expand_ui_button,
1842                 XmNbottomOffset,        3,
1843                 NULL);
1844
1845         XtVaGetValues(t->dssw.dssw_form_mgr,
1846                 XmNchildren,            &children,
1847                 XmNnumChildren,         &n,
1848                 NULL);
1849
1850         /* We don't want to manage some of the widgets */
1851         for (i = 0; i < n; i++) {
1852                 if ((children[i] == t->dssw.stop_label) ||
1853                     (children[i] == t->dssw.stop_menu) ||
1854                     (children[i] == t->dssw.stop_ampm_rc_mgr) ||
1855                     (children[i] == t->dssw.stop_text))
1856                         continue;
1857                 widgets[j++] = children[i];
1858         }
1859         XtManageChildren(widgets, n - 4);
1860
1861         /*
1862         **  Build the list and separators
1863         */
1864         CalFontExtents(c->fonts->labelfont, &listfontextents);;
1865
1866         cnt = 0;
1867         XtSetArg(args[cnt], XmNlistSizePolicy, XmCONSTANT);             ++cnt;
1868         XtSetArg(args[cnt], XmNwidth, 15 * 
1869                 listfontextents.max_logical_extent.width);              ++cnt;
1870         XtSetArg(args[cnt], XmNscrollBarDisplayPolicy, XmSTATIC);       ++cnt;
1871         XtSetArg(args[cnt], XmNdoubleClickInterval, 5);                 ++cnt; 
1872         t->todo_list = (Widget)XmCreateScrolledList(t->base_form_mgr,
1873                                                 "todo_list", args, cnt);
1874         t->todo_list_sw = XtParent(t->todo_list);
1875
1876         XtOverrideTranslations(t->todo_list, new_translations);
1877
1878         /* Make btn 2 do dnd of appts */
1879         /* btn1_transfer is a tri-state variable - see 1195846 */ 
1880         if ((Boolean)btn1_transfer != True) {   
1881                 new_translations = XtParseTranslationTable(btn2_translations);
1882                 XtOverrideTranslations(t->todo_list, new_translations);
1883         }
1884
1885         XtVaSetValues(t->todo_list_sw,
1886                 XmNtopAttachment,       XmATTACH_FORM,
1887                 XmNtopOffset,           label_height + 11,
1888                 XmNrightAttachment,     XmATTACH_FORM,
1889                 XmNrightOffset,         5,
1890                 XmNleftAttachment,      XmATTACH_WIDGET,
1891                 XmNleftWidget,          t->dssw.dssw_form_mgr,
1892                 XmNleftOffset,          10,
1893                 XmNbottomAttachment,    XmATTACH_OPPOSITE_WIDGET,
1894                 XmNbottomWidget,        t->dssw.dssw_form_mgr,
1895                 NULL);
1896
1897         XtManageChild(t->todo_list);
1898         XtAddCallback(t->todo_list,
1899                 XmNbrowseSelectionCallback, t_list_select_proc, t); 
1900
1901         XtVaSetValues(t->list_label,
1902                 XmNleftAttachment,      XmATTACH_OPPOSITE_WIDGET,
1903                 XmNleftWidget,          t->todo_list_sw,
1904                 NULL);
1905
1906         /* set default button */
1907         XtVaSetValues(t->base_form_mgr, 
1908                 XmNdefaultButton,       t->insert_button, 
1909                 NULL);
1910
1911         XtVaSetValues(t->base_form_mgr, 
1912                 XmNcancelButton,        t->close_button, 
1913                 NULL);
1914
1915         XmProcessTraversal(t->dssw.what_text, XmTRAVERSE_CURRENT);
1916         XtVaSetValues(t->base_form_mgr, 
1917                 XmNinitialFocus,        t->dssw.what_text, 
1918                 NULL);
1919
1920         ManageChildren(t->base_form_mgr);
1921         XtManageChild(t->base_form_mgr);
1922
1923         rfp_init(&t->rfp, c, t->base_form_mgr);
1924         reminders_init(&t->reminders, c, t->base_form_mgr);
1925
1926         t->todo_count = 0;
1927         t->todo_head = NULL;
1928         t->todo_is_up = False;
1929         t->initialX = -1;
1930         t->initialY = -1;
1931         t->doing_drag = False;
1932 }
1933
1934 /*******************************************************************************
1935 **
1936 **  External functions
1937 **
1938 *******************************************************************************/
1939 extern void
1940 add_to_todo_list(CSA_entry_handle entry, ToDo *t) {
1941         char                    *buf;
1942         Lines                   *lines;
1943         XmString                str;
1944         CSA_return_code         stat;
1945         Dtcm_appointment        *appt;
1946
1947         appt = allocate_appt_struct(appt_read, 
1948                                         t->cal->general->version,
1949                                         CSA_ENTRY_ATTR_SUMMARY_I, 
1950                                         NULL);
1951         stat = query_appt_struct(t->cal->cal_handle, entry, appt);
1952         backend_err_msg(t->frame, t->cal->view->current_calendar, stat,
1953                         ((Props_pu *)t->cal->properties_pu)->xm_error_pixmap);
1954         if (stat != CSA_SUCCESS) {
1955                 free_appt_struct(&appt);
1956                 return;
1957         }
1958
1959         lines = text_to_lines(appt->what->value->item.string_value, 1);
1960         if (lines && lines->s) {
1961                 buf = (char *)ckalloc(cm_strlen(lines->s) + 1);
1962                 strcpy(buf, lines->s);
1963                 destroy_lines(lines);
1964         } else {
1965                 buf = (char *)ckalloc(1);
1966                 buf[0] = '\0';
1967         }
1968
1969         str = XmStringCreateLocalized(buf);
1970         XmListAddItem(t->todo_list, str, 0);
1971         free_appt_struct(&appt);
1972         XmStringFree(str);
1973         free(buf);
1974 }
1975
1976 extern void
1977 add_all_todo(ToDo *t) {
1978         int             i;
1979         CSA_uint32      count;
1980         char            *date, date_str[MAXNAMELEN];
1981         Tick            tick;
1982         CSA_entry_handle        *entry_list;
1983         Props           *p;
1984         OrderingType    o;
1985         SeparatorType   s;
1986
1987         if (!todo_showing(t))
1988                 return;
1989
1990         p = (Props *)t->cal->properties;
1991         o = get_int_prop(p, CP_DATEORDERING);
1992         s = get_int_prop(p, CP_DATESEPARATOR);
1993         date = get_date_from_widget(t->cal->view->date, t->dssw.date_text, o, s);
1994         if (!date)
1995                 return;
1996
1997         sprintf(date_str, "%s", date);
1998         if ((strcasecmp(date, "today") == 0)
1999                 || (strcasecmp(date, "tomorrow") == 0)
2000                 || (strcasecmp(date, "yesterday") == 0))
2001                 sprintf(date_str, "12:00 am");
2002         if ((tick = cm_getdate(date_str, NULL)) <= 0)
2003                 return;
2004         build_todo_list(t, tick, dayGlance, &entry_list, &count, VIEW_ALL);
2005
2006         XmListDeleteAllItems(t->todo_list);
2007
2008         XtSetSensitive(t->delete_button, False);
2009         XtSetSensitive(t->change_button, False);
2010
2011         if (t->todo_head && t->todo_count > 0)
2012                 csa_free((CSA_buffer) t->todo_head);
2013         t->todo_head = entry_list;
2014         t->todo_count = count;
2015         for (i = 0; i < count; i++)
2016                 add_to_todo_list(entry_list[i], t);
2017         if (count <= 0)
2018                 XtSetSensitive(t->todo_list, False);
2019         else
2020                 XtSetSensitive(t->todo_list, True);
2021 }
2022
2023 static void
2024 set_list_title(ToDo *t) {
2025         Calendar        *c = t->cal;
2026         Props           *p = (Props *)c->properties;
2027         char            *header;
2028         char            buffer[BUFSIZ];
2029         char            buffer2[BUFSIZ];
2030         XmString        xmstr;
2031
2032         switch (t->view_list_glance) {
2033                 case yearGlance:
2034                                 header = catgets(c->DT_catd, 1, 806, "Year of %d");
2035                                 sprintf(buffer, header, year(t->view_list_date));
2036                                 break;
2037                 case monthGlance:
2038                                 format_date(t->view_list_date+1, get_int_prop(p, CP_DATEORDERING), buffer2, 0, 0, 0);
2039                                 header = catgets(c->DT_catd, 1, 807, "%s");
2040                                 sprintf(buffer, header, buffer2);
2041                                 break;
2042                 case weekGlance:
2043                                 format_date(t->view_list_date+1, get_int_prop(p, CP_DATEORDERING), buffer2, 1, 0, 0);
2044                                 header = catgets(c->DT_catd, 1, 808, "Week of %s");
2045                                 sprintf(buffer, header, buffer2);
2046                                 break;
2047                 case dayGlance:
2048                                 format_date(t->view_list_date+1, get_int_prop(p, CP_DATEORDERING), buffer2, 1, 0, 0);
2049                                 header = catgets(c->DT_catd, 1, 809, "%s");
2050                                 sprintf(buffer, header, buffer2);
2051                                 break;
2052         }
2053
2054         if (t->view_frame) {
2055                 xmstr = XmStringCreateLocalized(buffer);
2056                 XtVaSetValues(t->view_list_label, XmNlabelString, xmstr,
2057                         NULL);
2058                 XmStringFree(xmstr);
2059         }
2060
2061 }
2062
2063 extern void
2064 build_todo_list(ToDo *t, Tick date, Glance glance, CSA_entry_handle **a, CSA_uint32 *count, todo_view_op vf) {
2065         int             range_count;
2066         CSA_sint32      state;
2067         time_t          start, stop;
2068         boolean_t       use_state = B_FALSE;
2069         CSA_return_code stat;
2070         CSA_enum        *ops;
2071         CSA_attribute   *range_attrs;
2072
2073         switch(glance) {
2074         case yearGlance:
2075                 start = lowerbound(jan1(date));
2076                 stop = nextyear(start) - 1;
2077                 break;
2078         case monthGlance:
2079                 start = first_dom(date);
2080                 stop = nextmonth(start) - 1;
2081                 break;
2082         case weekGlance:
2083                 start = first_dow(date);
2084                 stop = nextweek(start) - 1;
2085                 break;
2086         case dayGlance:
2087         default:
2088                 start = lowerbound(date);
2089                 stop = nextday(start) - 1;
2090                 break;
2091         }
2092
2093         if (vf == VIEW_PENDING) {
2094                 state = CSA_X_DT_STATUS_ACTIVE;
2095                 use_state = B_TRUE;
2096         }
2097         else if (vf == VIEW_COMPLETED) {
2098                 state = CSA_STATUS_COMPLETED;
2099                 use_state = B_TRUE;
2100         }
2101         else
2102                 use_state = B_FALSE;
2103
2104         setup_range(&range_attrs, &ops, &range_count, start, stop,
2105                     CSA_TYPE_TODO, state, use_state, t->cal->general->version);
2106         stat = csa_list_entries(t->cal->cal_handle, range_count, range_attrs, ops, count, a, NULL);
2107
2108         backend_err_msg(t->frame, t->cal->view->current_calendar, stat,
2109                         ((Props_pu *)t->cal->properties_pu)->xm_error_pixmap);
2110         if (stat != CSA_SUCCESS) {
2111                 *a = NULL;
2112                 *count = 0;
2113         }
2114         free_range(&range_attrs, &ops, range_count);
2115 }
2116
2117 extern int
2118 build_todo_view(ToDo *t, Glance glance, Boolean redisplay) {
2119         int                     cnt; 
2120         CSA_uint32              entry_count;
2121         char                    *buf, *what_str, str1[MAXNAMELEN];
2122         char                    str2[MAXNAMELEN];
2123         Lines                   *lines;
2124         Props                   *p = (Props *)t->cal->properties;
2125         XmString                str;
2126         TodoView                *step, *last = NULL;
2127         CSA_entry_handle        *entry_list;
2128         CSA_return_code         stat;
2129         OrderingType            o = get_int_prop(p, CP_DATEORDERING);
2130         SeparatorType           s = get_int_prop(p, CP_DATESEPARATOR);
2131         Dtcm_appointment        *appt;
2132         Tick                    start_tick;
2133
2134         /*
2135         **  First, get the list of to-do appointments
2136         */
2137
2138         if (redisplay == True) {
2139  
2140                 /* On a redisplay, rebuild the list based on the
2141                    parameters of the last query. */
2142  
2143                 build_todo_list(t, t->view_list_date, t->view_list_glance, &entry_list,
2144                                 &entry_count, t->view_filter);
2145         }
2146         else {
2147                 /* If this is a clean display of the appointment list,
2148                    save the context so that a redisplay can be done if
2149                    something changes, like the display format or something
2150                    like that. */
2151  
2152                 build_todo_list(t, t->cal->view->date, glance, &entry_list,
2153                                 &entry_count, t->view_filter);
2154  
2155                 t->view_list_glance = glance;
2156                 t->view_list_date = t->cal->view->date;
2157         }
2158
2159         set_list_title(t);
2160
2161         step = t->view_list;
2162         appt = allocate_appt_struct(appt_read,
2163                                     t->cal->general->version,
2164                                     CSA_ENTRY_ATTR_START_DATE_I,
2165                                     CSA_ENTRY_ATTR_SUMMARY_I,
2166                                     CSA_ENTRY_ATTR_STATUS_I,
2167                                     NULL);
2168
2169         /*
2170         **  We're going to re-use the list of widgets we may have built
2171         **  previously.  This optimization saves the expensive creating
2172         **  and destroying of all the widgets that make up the "list"
2173         */
2174         for (cnt = 1; cnt <= entry_count; cnt++) {
2175                 /*
2176                 **  If there isn't a TodoView object, we've reached the end
2177                 **  of the current list, so build another
2178                 */
2179                 if (!step) {
2180                         step = (TodoView *)ckalloc(sizeof(TodoView));
2181
2182                         sprintf(str1, "%d", cnt);
2183                         sprintf(str2, "%s.", str1);
2184                         str = XmStringCreateLocalized(str2);
2185                         step->view_item_number = XtVaCreateManagedWidget("cnt",
2186                                 xmLabelGadgetClass, t->view_form_mgr,
2187                                 XmNlabelString, str,
2188                                 NULL);
2189                         XmStringFree(str);
2190
2191                         step->view_item_toggle = XtVaCreateManagedWidget(str1,
2192                                 xmToggleButtonGadgetClass, t->view_form_mgr,
2193                                 XmNalignment, XmALIGNMENT_BEGINNING,
2194                                 XmNleftAttachment, XmATTACH_WIDGET,
2195                                 XmNleftWidget, step->view_item_number,
2196                                 XmNleftOffset, 5,
2197                                 XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET,
2198                                 XmNtopWidget, step->view_item_number,
2199                                 XmNtopOffset, -3,
2200                                 NULL);
2201                         XtAddCallback(step->view_item_toggle,
2202                                 XmNvalueChangedCallback, t_view_change_proc, t);
2203
2204                         step->next = NULL;
2205                         step->appt = NULL;
2206                         if (last) {
2207                                 XtVaSetValues(step->view_item_number,
2208                                         XmNtopAttachment, XmATTACH_WIDGET,
2209                                         XmNtopWidget, last->view_item_number,
2210                                         XmNtopOffset, 10,
2211                                         XmNleftAttachment,
2212                                                 XmATTACH_OPPOSITE_WIDGET,
2213                                         XmNleftWidget, last->view_item_number,
2214                                         NULL);
2215                                 last->next = step;
2216                         } else
2217                                 t->view_list = step;
2218                 } else {
2219                         XtManageChild(step->view_item_number);
2220                         XtManageChild(step->view_item_toggle);
2221                 }
2222                 if (step->appt != NULL)
2223                         csa_free((CSA_buffer) step->appt);
2224                 step->appt = entry_list[cnt - 1];
2225                 step->modified = False;
2226
2227                 /*
2228                 **  Create the text string describing the todo and set that
2229                 **  value in the label gadget.
2230                 */
2231                 stat = query_appt_struct(t->cal->cal_handle, entry_list[cnt - 1], appt);
2232                 backend_err_msg(t->frame, t->cal->view->current_calendar, stat,
2233                         ((Props_pu *)t->cal->properties_pu)->xm_error_pixmap);
2234                 if (stat == CSA_SUCCESS) {
2235                         _csa_iso8601_to_tick(appt->time->value->item.date_time_value, &start_tick);
2236                         format_tick(start_tick, o, s, str1);
2237                         lines = text_to_lines(appt->what->value->item.string_value, 1);
2238                         if (lines && lines->s) {
2239                                 buf = (char *)ckalloc(cm_strlen(str1)
2240                                                       + cm_strlen(lines->s) + 3);
2241                                 what_str = lines->s;
2242                         } else {
2243                                 buf = (char *)ckalloc(cm_strlen(str1) + 4);
2244                                 what_str = "\0";
2245                         }
2246                         sprintf(buf, "%s  %s", str1, what_str);
2247                         str = XmStringCreateLocalized(buf);
2248                         XtVaSetValues(step->view_item_toggle,
2249                                 XmNlabelString, str,
2250                                 XmNset, (appt->state->value->item.sint32_value ==
2251                                         CSA_STATUS_COMPLETED) ?
2252                                                 True : False,
2253                                 NULL);
2254
2255                         XmStringFree(str);
2256                         free(buf);
2257                         destroy_lines(lines);
2258 #ifdef API
2259                         if (cnt < entry_count)
2260                                 DtCmFreeAttributeValues(appt->attrs,
2261                                                         appt->count);
2262 #endif
2263                 }
2264
2265                 last = step;
2266                 step = step->next;
2267         }
2268         free_appt_struct(&appt);
2269
2270         /*
2271         **  If step still points to a value, we've got extra items in the list,
2272         **  possibly filled with old stuff -- unmanage these widgets.
2273         */
2274         while (step) {
2275                 if (step->appt != NULL)
2276                         csa_free((CSA_buffer) step->appt);
2277                 XtUnmanageChild(step->view_item_number);
2278                 XtUnmanageChild(step->view_item_toggle);
2279                 step = step->next;
2280         }
2281
2282         if (entry_count > 0) {
2283                 XtManageChild(t->view_form); 
2284                 XtManageChild(t->view_sw_mgr);
2285                 XtManageChild(t->view_form_mgr); 
2286         }
2287
2288         t->view_list_modified = False;
2289
2290         return entry_count;
2291 }
2292
2293 extern void
2294 todo_clean_up(ToDo *t) {
2295         if (t->todo_head && t->todo_count > 0)
2296                 csa_free((CSA_buffer) t->todo_head);
2297         t->todo_head = NULL;
2298         t->todo_count = 0;
2299 }
2300
2301 extern Boolean
2302 todo_showing(ToDo *t) {
2303         if (t)
2304                 return t->todo_is_up;
2305         return False;
2306 }
2307
2308 extern Boolean
2309 todo_view_showing(ToDo *t) {
2310         if (t)
2311                 return t->todo_view_is_up;
2312         return False;
2313 }
2314
2315 /*
2316 **  External function to set todo defaults
2317 */
2318 extern void
2319 set_todo_defaults(ToDo *t) {
2320        /* ToDo structure may not be valid */
2321         if (!t || !t->cal) return;
2322         set_dssw_defaults(&t->dssw, t->cal->view->date, True);
2323
2324         if (t->reminders.bfpm_form_mgr) {
2325                 set_rfp_defaults(&t->rfp);
2326                 set_reminders_defaults(&t->reminders);
2327         }
2328         XmToggleButtonGadgetSetState(t->completed_toggle, False, False);
2329         set_message(t->message_text, " ");
2330
2331         t->rfpFlags = 0;
2332 }
2333 extern void
2334 set_todo_title(ToDo *t, char *name) {
2335         Calendar        *c = t->cal;
2336         char            buf[MAXNAMELEN];
2337
2338         if (t->frame) {
2339                 sprintf(buf, "%s - %s", catgets(c->DT_catd, 1, 591, "Calendar : To Do Editor"), name);
2340                 XtVaSetValues(t->frame, XmNtitle, buf,
2341                         NULL);
2342         }
2343 }
2344
2345 extern void
2346 show_todo(Calendar *c) {
2347         int             dv = get_data_version(c->cal_handle);
2348         ToDo            *t = (ToDo *)c->todo;
2349         Props_pu        *p = (Props_pu *)c->properties_pu;
2350
2351         if (dv <= CMS_VERS_2) {
2352                 backend_err_msg(c->frame, c->view->current_calendar,
2353                         CSA_E_NOT_SUPPORTED, p->xm_error_pixmap);
2354                 return;
2355         }
2356
2357         if (!t->frame)
2358                 t_make_todo(c);
2359         if (!todo_showing(t)) {
2360                 ds_position_popup(c->frame, t->frame, DS_POPUP_LOR);
2361                 /* set default button */
2362                 XmProcessTraversal(t->dssw.what_text, XmTRAVERSE_CURRENT);
2363                 XtVaSetValues(t->base_form_mgr, 
2364                         XmNinitialFocus, t->dssw.what_text, 
2365                         NULL);
2366         }
2367
2368         XtPopup(t->frame, XtGrabNone);
2369         if (! t->todo_is_up)
2370         {
2371             t->todo_is_up = True;
2372             set_todo_defaults(t);
2373         }
2374         add_all_todo(t);
2375 }
2376
2377 extern void
2378 show_todo_view(Calendar *c, todo_view_op view_filter) {
2379         int             dv = get_data_version(c->cal_handle);
2380         ToDo            *t = (ToDo *)c->todo;
2381         Props_pu        *p = (Props_pu *)c->properties_pu;
2382
2383         if (dv <= CMS_VERS_2) {
2384                 backend_err_msg(c->frame, c->view->current_calendar,
2385                         CSA_E_NOT_SUPPORTED, p->xm_error_pixmap);
2386                 return;
2387         }
2388
2389         if (!t->view_frame) {
2390                 t->cal = c;
2391                 t_build_view_popup(t);
2392         }
2393
2394
2395         XtVaSetValues(t->view_form, XmNdefaultButton, t->view_apply_button, NULL);
2396         XtVaSetValues(t->view_form, XmNcancelButton, t->view_cancel_button, NULL);
2397
2398
2399         build_todo_view(t, c->view->glance, False);
2400         if (!todo_view_showing(t))
2401                 ds_position_popup(c->frame, t->view_frame,
2402                                   DS_POPUP_LOR);
2403         XtVaSetValues(t->view_frame, XmNmappedWhenManaged, True,
2404                 NULL);
2405         XtPopup(t->view_frame, XtGrabNone);
2406         XtManageChild(t->view_form);
2407         t->todo_view_is_up = True;
2408 }
2409 /*
2410 **  Function to set todo defaults
2411 */
2412 static void
2413 set_todo_msg_defaults(ToDo *t) {
2414         set_dssw_defaults(&t->dssw, t->cal->view->date, False);
2415         set_message(t->message_text, " ");
2416 }
2417 /*
2418  * This todo_insert does not free the appt struct as
2419  * the t_insert code does.
2420  */
2421 extern Boolean
2422 todo_insert(Dtcm_appointment *appt, CSA_entry_handle *new_a, Calendar *c) {
2423         CSA_return_code stat;
2424         ToDo            *t = (ToDo *)c->todo;
2425         Props_pu        *p = (Props_pu *)c->properties_pu;
2426         CSA_enum                scope;
2427         static int              answer=0;
2428
2429         /* the gui does not support specifying the sequence end date */
2430         if (appt->sequence_end_date && appt->sequence_end_date->name) {
2431                 free(appt->sequence_end_date->name);
2432                 appt->sequence_end_date->name = NULL;
2433         }
2434         if ((appt->repeat_type->value) &&
2435            (appt->repeat_type->value->item.sint32_value != CSA_X_DT_REPEAT_ONETIME))
2436         {
2437                 char *title = XtNewString(catgets(c->DT_catd, 1, 1102,
2438                                         "Insert To Do"));
2439                 char *text = XtNewString(catgets(c->DT_catd, 1, 1103,
2440                                         "This To Do is part of a repeating series.\nDo you want to insert the item ...?"));
2441                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
2442                 char *ident4 = XtNewString(catgets(c->DT_catd, 1, 272, "All"));
2443                         answer = dialog_popup(c->frame,
2444                                 DIALOG_TITLE, title,
2445                                 DIALOG_TEXT, text,
2446                                 BUTTON_IDENT, 1, ident1,
2447                                 BUTTON_IDENT, 4, ident4,
2448                                 DIALOG_IMAGE, p->xm_question_pixmap,
2449                                 NULL);
2450                 XtFree(ident4);
2451                 XtFree(ident4);
2452                 XtFree(text);
2453                 XtFree(title);
2454         }
2455
2456         switch(answer) {
2457         case 1:
2458                 /*
2459                  * Free the CSA_buffer here since before, this routine
2460                  * only returned false when failure to obtain the CSA_structure
2461                  * occurred.
2462                  */
2463                 _DtTurnOffHourGlass(t->frame);
2464                 return;
2465         case 4:
2466         default:
2467                 /*
2468                  * scope is not used at this time.  However, to follow
2469                  * the change/delete style, this is here so in case
2470                  * later the same type of dialog is required.
2471                  */
2472                 scope = CSA_SCOPE_ALL;
2473                 break;
2474         }
2475
2476         stat = csa_add_entry(c->cal_handle, appt->count, appt->attrs, new_a, NULL);
2477         backend_err_msg(c->frame, c->view->current_calendar, stat,
2478                         p->xm_error_pixmap);
2479
2480         if (stat != CSA_SUCCESS) {
2481                 _DtTurnOffHourGlass(t->frame);
2482                 return;
2483         }
2484         csa_free((CSA_buffer) new_a);
2485
2486         set_todo_msg_defaults(t);
2487         add_all_todo(t);
2488
2489         if (todo_view_showing(t))
2490                 build_todo_view(t, dayGlance, False);
2491
2492         reset_alarm(c);
2493         invalidate_cache(c);
2494
2495
2496         return True;
2497 }