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