dtcm: Resolve CID 87408
[oweals/cde.git] / cde / programs / dtcm / dtcm / editor.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $TOG: editor.c /main/13 1999/07/01 11:44:34 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/RowColumn.h>
43 #include <Xm/ScrolledW.h>
44 #include <Xm/SeparatoG.h>
45 #include <Xm/Text.h>
46 #include <Xm/ToggleBG.h>
47 #include <Xm/LabelG.h>
48 #include <Xm/DragDrop.h>
49 #include <Xm/Screen.h>
50 #include <Dt/HourGlass.h>
51 #include <Dt/Dt.h>
52 #include <Dt/Dnd.h>
53 #include <Dt/Icon.h>
54 #include "editor.h"
55 #include "calendar.h"
56 #include "datefield.h"
57 #include "deskset.h"
58 #include "getdate.h"
59 #include "format.h"
60 #include "timeops.h"
61 #include "props.h"
62 #include "props_pu.h"
63 #include "group_editor.h"
64 #include "browser.h"
65 #include "util.h"
66 #include "dnd.h"
67 #include "help.h"
68 #ifdef SVR4
69 #include <sys/param.h>
70 #endif /* SVR4 */
71
72 static void e_build_expand(Editor *);
73 static void clear_flag_on_modify(Widget, XtPointer, XtPointer);
74
75 /* Absolute value macro */
76 #ifndef ABS
77 #define ABS(x) (((x) > 0) ? (x) : (-(x)))
78 #endif
79
80 static void set_editor_msg_defaults();
81
82 /*******************************************************************************
83 **
84 **  Functions static to editor.c
85 **
86 *******************************************************************************/
87
88 static void
89 clear_flag_on_modify(Widget w, XtPointer uData, XtPointer cbData)
90 {
91   int *flagP = (int *)uData;
92
93   *flagP = 0;
94 }
95
96 /*
97 **  This function will take appointment values and stuff them into a form.
98 */
99 static void
100 appt_to_form(Editor *e, CSA_entry_handle a) {
101         char                    buf[MAXNAMELEN];
102         CSA_return_code         status;
103         Dtcm_appointment        *appt;
104
105         if (!e->reminders.bfpm_form_mgr) {
106                 e_build_expand(e);
107                 set_rfp_defaults(&e->rfp);
108                 set_reminders_defaults(&e->reminders);
109         }
110
111         if (!dssw_appt_to_form(&e->dssw, a))
112                 return;
113         e->dsswFlags = 0;
114         if (!rfp_appt_to_form(&e->rfp, a))
115                 return;
116         e->rfpFlags = 0;
117         if (!reminders_appt_to_form(&e->reminders, a))
118                 return;
119
120         appt = allocate_appt_struct(appt_read, 
121                                         e->cal->general->version,
122                                         CSA_ENTRY_ATTR_ORGANIZER_I, 
123                                         NULL);
124         status = query_appt_struct(e->cal->cal_handle,a, appt);
125         backend_err_msg(e->frame, e->cal->view->current_calendar, status,
126                         ((Props_pu *)e->cal->properties_pu)->xm_error_pixmap);
127         if (status != CSA_SUCCESS) {
128                 free_appt_struct(&appt);
129                 return;
130         }
131         sprintf(buf, "%s:  %s", catgets(e->cal->DT_catd, 1, 251, "Author"),
132                 appt->author->value->item.calendar_user_value->user_name);
133         set_message(e->message_text, buf);
134         free_appt_struct(&appt);
135 }
136
137 /*
138 **  List selection procedure will get the correct appointment, then call
139 **  appt_to_form to load it into the UI.
140 */
141 static void
142 e_list_select_proc(Widget w, XtPointer client_data, XtPointer data) {
143         CSA_entry_handle                a;
144         Editor                  *e = (Editor *)client_data;
145         XmListCallbackStruct    *cbs = (XmListCallbackStruct *) data;
146
147         if (a = editor_nth_appt(e, cbs->item_position - 1))
148                 appt_to_form(e, a);
149
150         XtSetSensitive(e->delete_button, True);
151         XtSetSensitive(e->change_button, True);
152 }
153 /*
154 **  Quit handler for the editor and the editor view popup
155 */
156 static void
157 e_quit_handler(Widget w, XtPointer cdata, XtPointer data) {
158         Editor *e = (Editor *)cdata;
159         Widget popMeDown;
160
161         if (w == e->frame) {
162                 editor_clean_up(e);
163                 e->editor_is_up = False;
164                 popMeDown = e->base_form_mgr;
165         } else if (w == e->view_frame)
166         {
167                 e->editor_view_is_up = False;
168                 popMeDown = e->view_form;
169         }
170
171         XtUnmanageChild(popMeDown);
172 }
173
174
175 static void
176 e_view_cancel_cb(
177         Widget  widget,
178         XtPointer client_data,
179         XmPushButtonCallbackStruct *cbs)
180 {
181         Editor          *e = (Editor *)client_data;
182
183         XtUnmanageChild(e->view_form);
184 }
185
186 /*
187 **  Build the popup to display, in list fashion, the appts for a given period.
188 */
189 static void
190 e_build_view_popup(Editor *e) {
191         int             ac = 0;
192         Arg             args[15];
193         XmString        xmstr;
194         Calendar        *c = e->cal;
195         Widget          separator;
196         char            *title;
197
198         /*
199         **  Dialog shell and stuff
200         */
201         title = XtNewString(catgets(c->DT_catd, 1, 1086, 
202                                     "Calendar : Appointment List"));
203         e->view_frame = XtVaCreatePopupShell("appt_list",
204                 xmDialogShellWidgetClass,       e->cal->frame,
205                 XmNtitle,                       title,
206                 XmNdeleteResponse,              XmDO_NOTHING,
207                 XmNautoUnmanage,                False,
208                 XmNallowShellResize,            True,
209                 NULL);
210         XtFree(title);
211         setup_quit_handler(e->view_frame, e_quit_handler, (caddr_t)e);
212
213         e->view_form = XtVaCreateWidget("apptform",
214                         xmFormWidgetClass,      e->view_frame,
215                         XmNfractionBase,        2,
216                         XmNmarginWidth,         2,
217                         XmNautoUnmanage,        False,
218                         NULL);
219
220         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 680, "Close"));
221         e->view_cancel_button = XtVaCreateWidget("cancel",
222                         xmPushButtonWidgetClass,        e->view_form,
223                         XmNlabelString,                 xmstr,
224                         XmNleftAttachment,              XmATTACH_POSITION,
225                         XmNleftPosition,                0,
226                         XmNrightAttachment,             XmATTACH_POSITION,
227                         XmNrightPosition,               1,
228                         XmNbottomAttachment,            XmATTACH_FORM,
229                         XmNleftOffset,                  10,
230                         NULL);
231         XmStringFree(xmstr);
232
233         XtAddCallback(e->view_cancel_button, XmNactivateCallback, (XtCallbackProc) e_view_cancel_cb, e);
234
235         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 77, "Help"));
236         e->view_help_button = XtVaCreateWidget("help",
237                         xmPushButtonWidgetClass,        e->view_form,
238                         XmNlabelString,                 xmstr,
239                         XmNleftAttachment,              XmATTACH_POSITION,
240                         XmNleftPosition,                1,
241                         XmNrightAttachment,             XmATTACH_POSITION,
242                         XmNrightPosition,               2,
243                         XmNbottomAttachment,            XmATTACH_FORM,
244                         XmNrightOffset,                 10,
245                         NULL);
246         XmStringFree(xmstr);
247
248         separator = XtVaCreateWidget("separator",
249                 xmSeparatorGadgetClass,
250                 e->view_form,
251                 XmNleftAttachment,      XmATTACH_FORM,
252                 XmNrightAttachment,     XmATTACH_FORM,
253                 XmNbottomAttachment,    XmATTACH_WIDGET,
254                 XmNbottomWidget,        e->view_cancel_button,
255                 XmNbottomOffset,        5,
256                 NULL);
257
258         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 703, "context"));
259         e->view_list_label= XtVaCreateWidget("type_label",
260                 xmLabelGadgetClass,     e->view_form,
261                 XmNtopAttachment,       XmATTACH_FORM,
262                 XmNleftAttachment,      XmATTACH_FORM,
263                 XmNleftOffset,          5,
264                 XmNtopOffset,           5,
265                 XmNlabelString,         xmstr,
266                 NULL);
267         XmStringFree(xmstr);
268
269
270         ac = 0;
271         XtSetArg(args[ac], XmNwidth, 300); ac++;
272         XtSetArg(args[ac], XmNheight, 200); ac++;
273         XtSetArg(args[ac], XmNscrolledWindowMarginHeight, 5); ac++;
274         XtSetArg(args[ac], XmNscrolledWindowMarginWidth, 5); ac++;
275         XtSetArg(args[ac], XmNlistSpacing, 5); ac++;
276         XtSetArg(args[ac], XmNlistSizePolicy, XmCONSTANT); ++ac;
277         XtSetArg(args[ac], XmNrightAttachment, XmATTACH_FORM); ++ac;
278         XtSetArg(args[ac], XmNrightOffset, 2); ++ac;
279         XtSetArg(args[ac], XmNleftAttachment, XmATTACH_FORM); ++ac;
280         XtSetArg(args[ac], XmNtopAttachment, XmATTACH_WIDGET); ++ac;
281         XtSetArg(args[ac], XmNtopWidget, e->view_list_label); ++ac;
282         XtSetArg(args[ac], XmNbottomAttachment, XmATTACH_WIDGET); ++ac;
283         XtSetArg(args[ac], XmNbottomWidget, separator); ++ac;
284         XtSetArg(args[ac], XmNbottomOffset, 5); ++ac;
285         XtSetArg(args[ac], XmNdoubleClickInterval, 5); ++ac;
286         e->view_list = XmCreateScrolledList(e->view_form, "view_list",
287                                             args, ac);
288
289         XtAddCallback(e->view_help_button, XmNactivateCallback, 
290                 (XtCallbackProc)help_cb, APPT_LIST_HELP_BUTTON);
291         XtAddCallback(e->view_form, XmNhelpCallback, 
292                 (XtCallbackProc)help_cb, (XtPointer) APPT_LIST_HELP_BUTTON);
293
294         XtManageChild(e->view_list);
295         ManageChildren(e->view_form);
296         XtManageChild(e->view_form);
297         e->editor_view_is_up = False;
298 }
299
300 /*
301 **  This function creates the expando stuff on a form manager.
302 */
303 static void
304 e_build_expand(
305         Editor          *e)
306 {
307         Props           *p = (Props *)e->cal->properties;
308
309         /*
310         **  Build the rfp "widget"
311         */
312         e->rfpFlags = 0;
313         build_rfp(&e->rfp, e->cal, e->base_form_mgr);
314         XtVaSetValues(e->rfp.rfp_form_mgr,
315                 XmNleftAttachment,      XmATTACH_FORM,
316                 XmNleftOffset,          3,
317                 XmNtopAttachment,       XmATTACH_WIDGET,
318                 XmNtopWidget,           e->separator1,
319                 NULL);
320         ManageChildren(e->rfp.rfp_form_mgr);
321
322         XtAddCallback(e->rfp.repeat_menu, XmNselectionCallback,
323                       clear_flag_on_modify, (XtPointer)&e->rfpFlags);
324
325         /*
326         **  Call the build_reminders function to build that widget
327         */
328         build_reminders(&e->reminders, e->cal, e->base_form_mgr);
329         XtVaSetValues(e->reminders.bfpm_form_mgr,
330                 XmNleftAttachment,      XmATTACH_WIDGET,
331                 XmNleftWidget,          e->rfp.rfp_form_mgr,
332                 XmNrightOffset,         3,
333                 XmNtopAttachment,       XmATTACH_WIDGET,
334                 XmNtopWidget,           e->separator1,
335                 NULL);
336         ManageChildren(e->reminders.bfpm_form_mgr);
337 }
338
339 /*
340 **  Button action procedures manage and unmanage the "extra" stuff in the UI to
341 **  make it visible and invisible to the user.
342 */
343 static void
344 e_expand_ui_proc(Widget w, XtPointer client_data, XtPointer data) {
345         Editor          *e = (Editor *)client_data;
346         Props_pu        *p = (Props_pu *)e->cal->properties_pu;
347         XmString        xmstr;
348         Dimension       h, height, width;
349         static Boolean  expand_state_closed = True;
350
351         XtVaGetValues(e->appt_list_sw, 
352                         XmNheight,      &height, 
353                         XmNwidth,       &width, 
354                         NULL);
355
356         if (expand_state_closed) {
357                 Widget  children[2];
358
359                 if (!e->reminders.bfpm_form_mgr) {
360                         e_build_expand(e);
361                         set_rfp_defaults(&e->rfp);
362                         set_reminders_defaults(&e->reminders);
363                 }
364
365                 XtRealizeWidget(e->rfp.rfp_form_mgr);
366                 XtRealizeWidget(e->reminders.bfpm_form_mgr);
367
368                 xmstr = XmStringCreateLocalized(catgets(e->cal->DT_catd, 1, 625,
369                                                         "Less"));
370                 XtVaSetValues(e->expand_ui_button, XmNlabelString, xmstr,
371                               NULL);
372                 XmStringFree(xmstr);
373
374                 XtVaGetValues(e->reminders.bfpm_form_mgr, XmNheight, &h, NULL);
375                 XtVaSetValues(e->separator1, XmNbottomOffset, h + 10, NULL);
376
377                 children[0] = e->rfp.rfp_form_mgr;
378                 children[1] = e->reminders.bfpm_form_mgr;
379
380                 XtManageChildren(children, 2);
381
382                 expand_state_closed = False;
383         } else {
384                 xmstr = XmStringCreateLocalized(catgets(e->cal->DT_catd, 1, 626,
385                                                         "More"));
386                 XtVaSetValues(e->expand_ui_button, XmNlabelString, xmstr,
387                               NULL);
388                 XmStringFree(xmstr);
389                 XtUnmanageChild(e->rfp.rfp_form_mgr);
390                 XtUnmanageChild(e->reminders.bfpm_form_mgr);
391                 XtVaSetValues(e->separator1, XmNbottomOffset, 0, NULL);
392                 expand_state_closed = True;
393         }
394         XtVaSetValues(e->appt_list_sw, 
395                 XmNheight, height, 
396                 XmNwidth, width, 
397                 NULL);
398 }
399
400
401 /*
402 **  This function will consume form values and stuff them into an appointment.
403 */
404 static Dtcm_appointment*
405 form_to_appt(Editor *e) {
406         boolean_t               all_ok;
407         Dtcm_appointment        *a;
408
409         /* This code needs to conditionally decide whether to write out
410            the repeating event specification as an old style set of
411            specifications, or a new style recurrence rule.  In the case
412            of data versions 1-3, it needs to be the old style.  In the
413            case of version 4 it needs to be the new style. */
414
415         a = allocate_appt_struct(appt_write, e->cal->general->version, NULL);
416
417         all_ok = dssw_form_to_appt(&e->dssw, a, e->cal->view->current_calendar,
418                                    e->cal->view->date);
419         if (all_ok)
420                 all_ok = rfp_form_to_appt(&e->rfp, a,
421                                           e->cal->view->current_calendar);
422         if (all_ok)
423                 all_ok = reminders_form_to_appt(&e->reminders, a, e->cal->view->current_calendar);
424
425         if (!all_ok) {
426                 free_appt_struct(&a);
427                 return NULL;
428         }
429         a->type->value->item.sint32_value = CSA_TYPE_EVENT;
430         a->subtype->value->item.string_value = strdup(CSA_SUBTYPE_APPOINTMENT);
431         a->state->value->item.sint32_value = CSA_X_DT_STATUS_ACTIVE;
432
433         return a;
434 }
435
436 /*
437 **  Action procedures
438 */
439 static void
440 e_insert_proc(Widget w, XtPointer client_data, XtPointer data) {
441         Editor                  *e = (Editor *)client_data;
442         CSA_entry_handle        new_a = 0;
443         Dtcm_appointment        *a;
444         Calendar                *c = e->cal;
445
446         if (strcmp(c->calname, c->view->current_calendar) != 0) {
447                 char buf[BUFSIZ], buf2[BUFSIZ];
448                 int answer = 0;
449                 char *title;
450                 char *ident;
451                 /*
452                  * Make sure user really meant to insert appointment
453                  * into somebody elses calendar.
454                  */
455                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 210, "The appointment will be scheduled in the calendar\nyou are currently browsing.  Do you still want to schedule it?"));
456                 sprintf(buf2, "%s %s", catgets(c->DT_catd, 1, 211, "Schedule in"),
457                         c->view->current_calendar);
458                 title = XtNewString(catgets(c->DT_catd, 1, 212,
459                                             "Calendar : Schedule Appointment"));
460                 ident = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
461                 answer = dialog_popup(e->frame,
462                         DIALOG_TITLE, title,
463                         DIALOG_TEXT, buf,
464                         BUTTON_IDENT, 1, ident,
465                         BUTTON_IDENT, 2, buf2,
466                         NULL);
467                 XtFree(ident);
468                 XtFree(title);
469                 if (answer == 1)
470                         return;
471         }
472
473         _DtTurnOnHourGlass(e->frame);
474         if ((a = form_to_appt(e)) != NULL) {
475                 if ((editor_insert(a, &new_a, e->cal)) == True)
476                         csa_free((CSA_buffer)new_a);
477                 free_appt_struct(&a);
478         }
479         _DtTurnOffHourGlass(e->frame);
480 }
481
482 static void
483 e_delete_proc(Widget w, XtPointer client_data, XtPointer data) {
484         int             *item_list = NULL, item_cnt = 0;
485         CSA_entry_handle        a;
486         Editor          *e = (Editor *)client_data;
487         Calendar        *c = e->cal;
488         Props_pu        *p = (Props_pu *)e->cal->properties_pu;
489         static int      answer;
490
491         if (strcmp(c->calname, c->view->current_calendar) != 0) {
492                 char buf[BUFSIZ], buf2[BUFSIZ];
493                 char *title;
494                 char *ident;
495                 /*
496                  * Make sure user really meant to delete appointment
497                  * from somebody elses calendar.
498                  */
499                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 1004, "This appointment is in a calendar owned by someone else.\nDo you want to delete it anyway ?"));
500                 sprintf(buf2, "%s %s", catgets(c->DT_catd, 1, 1005, "Delete from"),
501                         c->view->current_calendar);
502                 title = XtNewString(catgets(c->DT_catd, 1, 252,
503                                 "Calendar : Appointment Editor - Delete"));
504                 ident = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
505                 answer = dialog_popup(e->frame,
506                         DIALOG_TITLE, title,
507                         DIALOG_TEXT, buf,
508                         BUTTON_IDENT, 1, ident,
509                         BUTTON_IDENT, 2, buf2,
510                         NULL);
511                 XtFree(ident);
512                 XtFree(title);
513                 if (answer == 1)
514                         return;
515         }
516
517         _DtTurnOnHourGlass(e->frame);
518         if (!XmListGetSelectedPos(e->appt_list, &item_list, &item_cnt)) {
519                 char *title = XtNewString(catgets(c->DT_catd, 1, 252,
520                                 "Calendar : Appointment Editor - Delete"));
521                 char *text = XtNewString(catgets(c->DT_catd, 1, 253,
522                                 "Select an appointment and DELETE again."));
523                 char *ident = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
524                 answer = dialog_popup(e->frame,
525                         DIALOG_TITLE, title,
526                         DIALOG_TEXT, text,
527                         BUTTON_IDENT, 1, ident,
528                         DIALOG_IMAGE, p->xm_error_pixmap,
529                         NULL);
530                 XtFree(ident);
531                 XtFree(text);
532                 XtFree(title);
533                 _DtTurnOffHourGlass(e->frame);
534                 return;
535         } 
536
537         if (!(a = editor_nth_appt(e, item_list[0] - 1))) {
538                 char *title = XtNewString(catgets(c->DT_catd, 1, 252,
539                                 "Calendar : Appointment Editor - Delete"));
540                 char *text = XtNewString(catgets(c->DT_catd, 1, 256,
541                                 "Internal error selecting appointment.\nAppointment was not deleted."));
542                 char *ident = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
543                 answer = dialog_popup(e->frame,
544                         DIALOG_TITLE, title,
545                         DIALOG_TEXT, text,
546                         BUTTON_IDENT, 1, ident,
547                         BUTTON_HELP, RESELECT_ERROR_HELP,
548                         DIALOG_IMAGE, p->xm_error_pixmap,
549                         NULL);
550                 XtFree(ident);
551                 XtFree(text);
552                 XtFree(title);
553                 XtFree((XtPointer)item_list);
554                 _DtTurnOffHourGlass(e->frame);
555                 return;
556         }
557         XtFree((XtPointer)item_list);
558
559         editor_delete(a, e->cal);
560         _DtTurnOffHourGlass(e->frame);
561 }
562
563 static void
564 e_change_proc(Widget w, XtPointer client_data, XtPointer data) {
565         int                     *item_list = NULL, item_cnt = 0;
566         Editor                  *e = (Editor *)client_data;
567         Calendar                *c = e->cal;
568         CSA_entry_handle        old_a, updated_a;
569         Props_pu                *p = (Props_pu *)e->cal->properties_pu;
570         static int              answer;
571         Dtcm_appointment        *new_a;
572
573         if (strcmp(c->calname, c->view->current_calendar) != 0) {
574                 char buf[BUFSIZ], buf2[BUFSIZ];
575                 char *title = XtNewString(catgets(c->DT_catd, 1, 258,
576                                 "Calendar : Appointment Editor - Change"));
577                 char *ident = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
578                 /*
579                  * Make sure user really meant to insert appointment
580                  * into somebody elses calendar.
581                  */
582                 sprintf(buf, "%s", catgets(c->DT_catd, 1, 1003, "This appointment is in a calendar owned by someone else.\nDo you want to change it anyway ?"));
583                 sprintf(buf2, "%s %s", catgets(c->DT_catd, 1, 1006, "Change in"),
584                         c->view->current_calendar);
585                 answer = dialog_popup(e->frame,
586                         DIALOG_TITLE, title,
587                         DIALOG_TEXT, buf,
588                         BUTTON_IDENT, 1, ident,
589                         BUTTON_IDENT, 2, buf2,
590                         NULL);
591                 XtFree(ident);
592                 XtFree(title);
593                 if (answer == 1)
594                         return;
595         }
596
597         _DtTurnOnHourGlass(e->frame);
598         if (!XmListGetSelectedPos(e->appt_list, &item_list, &item_cnt)) {
599                 char *title = XtNewString(catgets(c->DT_catd, 1, 258,
600                                 "Calendar : Appointment Editor - Change"));
601                 char *text = XtNewString(catgets(c->DT_catd, 1, 259,
602                                 "Select an appointment and CHANGE again."));
603                 char *ident = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
604                 answer = dialog_popup(e->frame,
605                         DIALOG_TITLE, title,
606                         DIALOG_TEXT, text,
607                         BUTTON_IDENT, 1, ident,
608                         DIALOG_IMAGE, p->xm_error_pixmap,
609                         NULL);
610                 XtFree(ident);
611                 XtFree(text);
612                 XtFree(title);
613                 _DtTurnOffHourGlass(e->frame);
614                 return;
615         } 
616
617         if (!(old_a = editor_nth_appt(e, item_list[0] - 1))) {
618                 char *title = XtNewString(catgets(c->DT_catd, 1, 1075,
619                                 "Calendar : Error - Change Appointment"));
620                 char *text = XtNewString(catgets(c->DT_catd, 1, 1007,
621                                 "Internal error selecting appointment.\nAppointment was not changed."));
622                 char *ident = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
623                 answer = dialog_popup(e->frame,
624                         DIALOG_TITLE, title,
625                         DIALOG_TEXT, text,
626                         BUTTON_IDENT, 1, ident,
627                         DIALOG_IMAGE, p->xm_error_pixmap,
628                         NULL);
629                 XtFree(ident);
630                 XtFree(text);
631                 XtFree(title);
632                 XtFree((XtPointer)item_list);
633                 _DtTurnOffHourGlass(e->frame);
634                 return;
635         }
636         XtFree((XtPointer)item_list);
637
638         if ((new_a = form_to_appt(e)) == NULL) {
639                 _DtTurnOffHourGlass(e->frame);
640                 return;
641         }
642
643         if (editor_change(new_a, old_a, &updated_a, e->cal))
644                 csa_free((CSA_buffer)updated_a);
645
646         free_appt_struct(&new_a);
647         _DtTurnOffHourGlass(e->frame);
648 }
649
650 static void
651 e_clear_proc(Widget w, XtPointer client_data, XtPointer data) {
652         Editor *e = (Editor *)client_data;
653
654         set_editor_defaults(e, 0, 0, False);
655         add_all_appt(e);
656 }
657
658 static void
659 e_close_proc(Widget w, XtPointer client_data, XtPointer data) {
660         Editor *e = (Editor *)client_data;
661
662         XtUnmanageChild(e->base_form_mgr);
663         e->editor_is_up = False;
664 }
665
666 /*
667  * dragMotionHandler
668  *
669  * Determine if the pointer has moved beyond the drag threshold while button 1
670  * was being held down.
671  */
672 void
673 FormApptDragMotionHandler(
674         Widget          dragInitiator,
675         XtPointer       clientData,
676         XEvent         *event)
677 {
678         int             diffX, diffY;
679         Calendar        *c = (Calendar *) clientData;
680         Editor          *e = (Editor *) c->editor;
681         Dimension       source_height, source_width;
682         Position        source_x, source_y;
683  
684         if (!e->doing_drag) {
685
686                 /* check to see if the iniital value was within the 
687                    bounds for the drag source icon. */
688
689                 XtVaGetValues(e->drag_source, 
690                                 XmNx, &source_x,
691                                 XmNy, &source_y,
692                                 XmNheight, &source_height,
693                                 XmNwidth, &source_width,
694                                 NULL);
695
696                 if ((event->xmotion.x < source_x) ||
697                     (event->xmotion.y < source_y) ||
698                     (event->xmotion.x > (int) (source_x + source_width)) ||
699                     (event->xmotion.y > (int) (source_y + source_height)))
700                         return;
701
702                 /*
703                  * If the drag is just starting, set initial button down coords
704                  */
705                 if (e->initialX == -1 && e->initialY == -1) {
706                         e->initialX = event->xmotion.x;
707                         e->initialY = event->xmotion.y;
708                 }
709                 /*
710                  * Find out how far pointer has moved since button press
711                  */
712                 diffX = e->initialX - event->xmotion.x;
713                 diffY = e->initialY - event->xmotion.y;
714  
715                 if ((ABS(diffX) >= DRAG_THRESHOLD) ||
716                     (ABS(diffY) >= DRAG_THRESHOLD)) {
717                         e->doing_drag = True;
718                         ApptDragStart(dragInitiator, event, c, SingleEditorIcon);
719                         e->initialX = -1;
720                         e->initialY = -1;
721                 }
722         }
723 }
724
725 extern void
726 e_make_editor(Calendar *c)
727 {
728         int             cnt = 0;
729         Arg             args[15];
730         Editor          *e = (Editor *)c->editor;
731         Props_pu        *p = (Props_pu *)c->properties_pu;
732         XmString        xmstr;
733         Dimension       label_height;
734         XtTranslations  new_translations;
735         XFontSetExtents listfontextents;
736         static char     translations[] = "\
737                 ~c ~s ~m ~a <Btn1Down>:\
738                  dtcm-process-press(ListBeginSelect,TranslationDragStart)\n\
739                 c ~s ~m ~a <Btn1Down>:\
740                  dtcm-process-press(ListBeginToggle,TranslationDragStart)";
741         static char     btn2_translations[] = "\
742                 ~c ~s ~m ~a <Btn2Down>:\
743                  dtcm-process-press(ListBeginSelect,TranslationDragStart)\n\
744                 c ~s ~m ~a <Btn2Down>:\
745                  dtcm-process-press(ListBeginToggle,TranslationDragStart)\n\
746                 <Btn2Motion>:ListButtonMotion()\n\
747                 ~c ~s ~m ~a <Btn2Up>:ListEndSelect()\n\
748                 c ~s ~m ~a <Btn2Up>:ListEndToggle()";
749         Boolean         btn1_transfer; 
750
751         new_translations = XtParseTranslationTable(translations);
752                          
753         e->cal = c;
754
755         /*
756         **  Dialog shell and the base form
757         */
758         e->frame = XtVaCreatePopupShell("frame",
759                 xmDialogShellWidgetClass, e->cal->frame,
760                 XmNdeleteResponse,      XmDO_NOTHING,
761                 XmNallowShellResize,    True,
762                 NULL);
763         set_editor_title(e, c->view->current_calendar);
764         setup_quit_handler(e->frame, e_quit_handler, (caddr_t)e);
765
766         e->base_form_mgr = XtVaCreateWidget("base_form_mgr",
767                 xmFormWidgetClass,      e->frame,
768                 XmNautoUnmanage,        False,
769                 XmNfractionBase,        8,
770                 NULL);
771
772         /*
773         **  Build the stuff in the upper portion of the form - the dssw widget,
774         **  the scrolling appointment list, the expand/contract button, and the
775         **  first separator.
776         */
777         xmstr = XmStringCreateLocalized(
778                                 catgets(c->DT_catd, 1, 628, "Time  What"));
779         e->list_label = XtVaCreateWidget("label",
780                 xmLabelGadgetClass,     e->base_form_mgr,
781                 XmNlabelString,         xmstr,
782                 XmNtopAttachment,       XmATTACH_FORM,
783                 XmNtopOffset,           5,
784                 NULL);
785         XmStringFree(xmstr);
786
787         XtVaGetValues(e->list_label, XmNheight, &label_height, NULL);
788
789         e->message_text = XtVaCreateWidget("message",
790                 xmLabelGadgetClass,     e->base_form_mgr,
791                 XmNalignment,           XmALIGNMENT_BEGINNING,
792                 XmNbottomAttachment,    XmATTACH_FORM,
793                 XmNbottomOffset,        2,
794                 XmNleftAttachment,      XmATTACH_FORM,
795                 XmNleftOffset,          2,
796                 XmNrightAttachment,     XmATTACH_FORM,
797                 XmNrightOffset,         2,
798                 NULL);
799
800         /*
801         **  Create insert, delete, change, and clear buttons
802         */
803         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 342, "Insert"));
804         e->insert_button = XtVaCreateWidget("Insert",
805                 xmPushButtonWidgetClass, e->base_form_mgr,
806                 XmNlabelString,         xmstr,
807                 XmNbottomAttachment,    XmATTACH_WIDGET,
808                 XmNbottomWidget,        e->message_text,
809                 XmNleftAttachment,      XmATTACH_POSITION,
810                 XmNleftPosition,        1,
811                 XmNrightAttachment,     XmATTACH_POSITION,
812                 XmNrightPosition,       2,
813                 NULL);
814         XtAddCallback(e->insert_button, XmNactivateCallback, e_insert_proc, e);
815         XmStringFree(xmstr);
816
817         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 343, "Change"));
818         e->change_button = XtVaCreateWidget("Change",
819                 xmPushButtonWidgetClass, e->base_form_mgr,
820                 XmNlabelString,         xmstr,
821                 XmNbottomAttachment,    XmATTACH_WIDGET,
822                 XmNbottomWidget,        e->message_text,
823                 XmNleftAttachment,      XmATTACH_POSITION,
824                 XmNleftPosition,        2,
825                 XmNrightAttachment,     XmATTACH_POSITION,
826                 XmNrightPosition,       3,
827                 XmNsensitive,           False,
828                 NULL);
829         XtAddCallback(e->change_button, XmNactivateCallback, e_change_proc, e);
830         XmStringFree(xmstr);
831  
832         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 419, "Delete"));
833         e->delete_button = XtVaCreateWidget("Delete",
834                 xmPushButtonWidgetClass, e->base_form_mgr,
835                 XmNlabelString,         xmstr,
836                 XmNbottomAttachment,    XmATTACH_WIDGET,
837                 XmNbottomWidget,        e->message_text,
838                 XmNleftAttachment,      XmATTACH_POSITION,
839                 XmNleftPosition,        3,
840                 XmNrightAttachment,     XmATTACH_POSITION,
841                 XmNrightPosition,       4,
842                 XmNsensitive,           False,
843                 NULL);
844         XtAddCallback(e->delete_button, XmNactivateCallback, e_delete_proc, e);
845         XmStringFree(xmstr);
846
847         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 803, "Clear"));
848         e->clear_button = XtVaCreateWidget("Clear",
849                 xmPushButtonWidgetClass, e->base_form_mgr,
850                 XmNlabelString,         xmstr,
851                 XmNbottomAttachment,    XmATTACH_WIDGET,
852                 XmNbottomWidget,        e->message_text,
853                 XmNleftAttachment,      XmATTACH_POSITION,
854                 XmNleftPosition,        4,
855                 XmNrightAttachment,     XmATTACH_POSITION,
856                 XmNrightPosition,       5,
857                 NULL);
858         XtAddCallback(e->clear_button, XmNactivateCallback, e_clear_proc, e);
859         XmStringFree(xmstr);
860
861         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 923, "Cancel"));
862         e->close_button = XtVaCreateWidget("Cancel",
863                 xmPushButtonWidgetClass, e->base_form_mgr,
864                 XmNlabelString,         xmstr,
865                 XmNbottomAttachment,    XmATTACH_WIDGET,
866                 XmNbottomWidget,        e->message_text,
867                 XmNleftAttachment,      XmATTACH_POSITION,
868                 XmNleftPosition,        5,
869                 XmNrightAttachment,     XmATTACH_POSITION,
870                 XmNrightPosition,       6,
871                 NULL);
872         XtAddCallback(e->close_button, XmNactivateCallback, e_close_proc, e);
873         XmStringFree(xmstr);
874
875         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 77, "Help"));
876         e->help_button = XtVaCreateWidget("Help",
877                 xmPushButtonWidgetClass, e->base_form_mgr,
878                 XmNlabelString,         xmstr,
879                 XmNbottomAttachment,    XmATTACH_WIDGET,
880                 XmNbottomWidget,        e->message_text,
881                 XmNleftAttachment,      XmATTACH_POSITION,
882                 XmNleftPosition,        6,
883                 XmNrightAttachment,     XmATTACH_POSITION,
884                 XmNrightPosition,       7,
885                 NULL);
886         XmStringFree(xmstr);
887
888         e->separator2 = XtVaCreateWidget("separator2",
889                 xmSeparatorGadgetClass, e->base_form_mgr,
890                 XmNbottomAttachment,    XmATTACH_WIDGET,
891                 XmNbottomWidget,        e->insert_button,
892                 XmNbottomOffset,        5,
893                 XmNleftAttachment,      XmATTACH_FORM,
894                 XmNleftOffset,          5,
895                 XmNrightAttachment,     XmATTACH_FORM,
896                 XmNrightOffset,         5,
897                 NULL);
898
899         e->separator1 = XtVaCreateWidget("separator1",
900                 xmSeparatorGadgetClass, e->base_form_mgr,
901                 XmNleftAttachment,      XmATTACH_FORM,
902                 XmNleftOffset,          5,
903                 XmNrightAttachment,     XmATTACH_FORM,
904                 XmNrightOffset,         5,
905                 XmNbottomAttachment,    XmATTACH_WIDGET,
906                 XmNbottomWidget,        e->separator2,
907                 NULL);
908
909         xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 626, "More"));
910         e->expand_ui_button = XtVaCreateWidget("expand_ui_button",
911                 xmPushButtonWidgetClass, e->base_form_mgr,
912                 XmNlabelString,         xmstr,
913                 XmNbottomAttachment,    XmATTACH_WIDGET,
914                 XmNbottomWidget,        e->separator1,
915                 XmNbottomOffset,        3,
916                 XmNleftAttachment,      XmATTACH_FORM,
917                 XmNleftOffset,          5,
918                 XmNnavigationType,      XmTAB_GROUP,
919                 NULL);
920         XtAddCallback(e->expand_ui_button, XmNactivateCallback,
921                 e_expand_ui_proc, e);
922         XmStringFree(xmstr);
923
924         e->dsswFlags = 0;
925         build_dssw(&e->dssw, c, e->base_form_mgr, True, True);
926         XtVaSetValues(e->dssw.dssw_form_mgr,
927                 XmNtopAttachment,       XmATTACH_FORM,
928                 XmNtopOffset,           label_height + 5,
929                 XmNbottomAttachment,    XmATTACH_WIDGET,
930                 XmNbottomWidget,        e->expand_ui_button,
931                 XmNbottomOffset,        3,
932                 XmNleftAttachment,      XmATTACH_FORM,
933                 XmNleftOffset,          5,
934                 NULL);
935
936         XtAddCallback(e->dssw.start_text, XmNvalueChangedCallback,
937                       clear_flag_on_modify, (XtPointer)&e->dsswFlags);
938         XtAddCallback(e->dssw.start_am, XmNvalueChangedCallback,
939                       clear_flag_on_modify, (XtPointer)&e->dsswFlags);
940         XtAddCallback(e->dssw.start_pm, XmNvalueChangedCallback,
941                       clear_flag_on_modify, (XtPointer)&e->dsswFlags);
942         XtAddCallback(e->dssw.stop_text, XmNvalueChangedCallback,
943                       clear_flag_on_modify, (XtPointer)&e->dsswFlags);
944         XtAddCallback(e->dssw.stop_am, XmNvalueChangedCallback,
945                       clear_flag_on_modify, (XtPointer)&e->dsswFlags);
946         XtAddCallback(e->dssw.stop_pm, XmNvalueChangedCallback,
947                       clear_flag_on_modify, (XtPointer)&e->dsswFlags);
948
949         /*
950          * Add a drag source icon inside the dssw, lower right
951          */
952         xmstr = XmStringCreateLocalized(
953                                 catgets(c->DT_catd, 1, 627, "Drag Appt"));
954         e->drag_source = XtVaCreateWidget("drag_source",
955                 dtIconGadgetClass,      e->dssw.dssw_form_mgr,
956                 XmNpixmapPosition,      XmPIXMAP_TOP,
957                 XmNstringPosition,      XmSTRING_BOTTOM,
958                 XmNalignment,           XmALIGNMENT_CENTER,
959                 XmNstring,              xmstr,
960                 XmNbottomAttachment,    XmATTACH_FORM,
961                 XmNrightAttachment,     XmATTACH_FORM,
962                 XmNtraversalOn,         False,
963                 XmNbehavior,            XmICON_DRAG,
964                 NULL);
965         XmStringFree(xmstr);
966
967         XtAddEventHandler(XtParent(e->drag_source), Button1MotionMask, False,
968                 (XtEventHandler)FormApptDragMotionHandler, (XtPointer) c);
969
970         XtVaGetValues((Widget)XmGetXmDisplay(XtDisplay(c->frame)), 
971                 "enableBtn1Transfer",   &btn1_transfer, 
972                 NULL); 
973
974         /* btn1_transfer is a tri-state variable - see 1195846 */
975         if ((Boolean)btn1_transfer != True) {
976                 XtAddEventHandler(XtParent(e->drag_source), 
977                                 Button2MotionMask, False, 
978                                 (XtEventHandler)FormApptDragMotionHandler, 
979                                 (XtPointer) c);
980         }
981
982         if (p->drag_icon_xbm)
983                 XtVaSetValues(e->drag_source, 
984                                 XmNpixmap, p->drag_icon_xbm, 
985                                 NULL);
986
987         XtVaSetValues(e->dssw.what_scrollwindow, 
988                 XmNrightAttachment,     XmATTACH_WIDGET,
989                 XmNrightWidget,         e->drag_source, 
990                 NULL);
991
992         ManageChildren(e->dssw.dssw_form_mgr);
993
994         CalFontExtents(c->fonts->labelfont, &listfontextents);
995
996         cnt = 0;
997         XtSetArg(args[cnt], XmNlistSizePolicy, XmCONSTANT);             ++cnt;
998         XtSetArg(args[cnt], XmNwidth, 15 * 
999                 listfontextents.max_logical_extent.width);              ++cnt;
1000         XtSetArg(args[cnt], XmNscrollBarDisplayPolicy, XmSTATIC);       ++cnt;
1001         XtSetArg(args[cnt], XmNdoubleClickInterval, 5);                 ++cnt;
1002         e->appt_list = XmCreateScrolledList(e->base_form_mgr, "appt_list",
1003                                             args, cnt);
1004         e->appt_list_sw = XtParent(e->appt_list);
1005
1006         XtOverrideTranslations(e->appt_list, new_translations);
1007
1008         /* Make btn 2 do dnd of appts */
1009         /* btn1_transfer is a tri-state variable - see 1195846 */
1010         if ((Boolean)btn1_transfer != True) {
1011                 new_translations = XtParseTranslationTable(btn2_translations);
1012                 XtOverrideTranslations(e->appt_list, new_translations);
1013         }
1014
1015         XtVaSetValues(e->appt_list_sw,
1016                 XmNtopAttachment,       XmATTACH_FORM,
1017                 XmNtopOffset,           label_height + 11,
1018                 XmNleftAttachment,      XmATTACH_WIDGET,
1019                 XmNleftWidget,          e->dssw.dssw_form_mgr,
1020                 XmNleftOffset,          10,
1021                 XmNrightAttachment,     XmATTACH_FORM,
1022                 XmNrightOffset,         5,
1023                 XmNbottomAttachment,    XmATTACH_WIDGET,
1024                 XmNbottomWidget,        e->expand_ui_button,
1025                 XmNbottomOffset,        3,
1026                 NULL);
1027
1028         XtManageChild(e->appt_list);
1029         XtAddCallback(e->appt_list,
1030                 XmNbrowseSelectionCallback, e_list_select_proc, e); 
1031
1032         XtVaSetValues(e->list_label,
1033                 XmNleftAttachment,      XmATTACH_OPPOSITE_WIDGET,
1034                 XmNleftWidget,          e->appt_list_sw,
1035                 NULL);
1036
1037         XtAddCallback(e->help_button, XmNactivateCallback,
1038                 (XtCallbackProc)help_cb, APPT_EDITOR_HELP_BUTTON);
1039         XtAddCallback(e->base_form_mgr, XmNhelpCallback,
1040                 (XtCallbackProc)help_cb, (XtPointer) APPT_EDITOR_HELP_BUTTON);
1041
1042         XtVaSetValues(e->base_form_mgr, 
1043                 XmNdefaultButton,       e->insert_button, 
1044                 NULL);
1045
1046         XtVaSetValues(e->base_form_mgr, 
1047                 XmNcancelButton,        e->close_button, 
1048                 NULL);
1049
1050         XmProcessTraversal(e->dssw.what_text, XmTRAVERSE_CURRENT);
1051         XtVaSetValues(e->base_form_mgr, 
1052                 XmNinitialFocus,        e->dssw.what_text, 
1053                 NULL);
1054
1055         ManageChildren(e->base_form_mgr);
1056         XtManageChild(e->base_form_mgr);
1057
1058         /*
1059         **  Set up editor variables.  The drag threshold variables are set to
1060         **  -1, so we are ready for first dnd operation.
1061         */
1062         rfp_init(&e->rfp, c, e->base_form_mgr);
1063         reminders_init(&e->reminders, c, e->base_form_mgr);
1064         e->appt_count = 0;
1065         e->appt_head = NULL;
1066         e->initialX = -1;
1067         e->initialY = -1;
1068         e->doing_drag = False;
1069 }
1070
1071 /*******************************************************************************
1072 **
1073 **  External functions
1074 **
1075 *******************************************************************************/
1076 extern void
1077 add_to_appt_list(CSA_entry_handle entry, Editor *e) {
1078         char                    buf[DEFAULT_APPT_LEN];
1079         Props                   *p = (Props *)e->cal->properties;
1080         XmString                str;
1081         CSA_return_code         status;
1082         DisplayType             dt = get_int_prop(p, CP_DEFAULTDISP);
1083         Dtcm_appointment        *appt;
1084
1085         appt = allocate_appt_struct(appt_read,
1086                                     e->cal->general->version,
1087                                     CSA_ENTRY_ATTR_START_DATE_I,
1088                                     CSA_ENTRY_ATTR_SUMMARY_I,
1089                                     CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,
1090                                     NULL);
1091         status = query_appt_struct(e->cal->cal_handle, entry, appt);
1092         backend_err_msg(e->frame, e->cal->view->current_calendar, status,
1093                         ((Props_pu *)e->cal->properties_pu)->xm_error_pixmap);
1094         if (status != CSA_SUCCESS) {
1095                 free_appt_struct(&appt);
1096                 return;
1097         }
1098
1099         format_appt(appt, buf, dt, DEFAULT_APPT_LEN);
1100         str = XmStringCreateLocalized(buf);
1101         XmListAddItem(e->appt_list, str, 0);
1102         XmStringFree(str);
1103         free_appt_struct(&appt);
1104 }
1105
1106 extern void
1107 add_all_appt(Editor *e) {
1108         int             i;
1109         CSA_uint32      j;
1110         char            *date;
1111         Tick            tick;
1112         Props           *p;
1113         Calendar        *c = e->cal;
1114         CSA_entry_handle        *entry_list;
1115         OrderingType    o;
1116         SeparatorType   s;
1117
1118         if (!editor_showing(e))
1119                 return;
1120
1121         p = (Props *)e->cal->properties;
1122         o = get_int_prop(p, CP_DATEORDERING);
1123         s = get_int_prop(p, CP_DATESEPARATOR);
1124
1125         date = get_date_from_widget(e->cal->view->date, e->dssw.date_text, o, s);
1126         if (!date || (tick = cm_getdate(date, NULL)) <= 0)
1127                 return;
1128         build_editor_list(e, tick, dayGlance, &entry_list, &j);
1129
1130         XmListDeleteAllItems(e->appt_list);
1131         XtSetSensitive(e->delete_button, False);
1132         XtSetSensitive(e->change_button, False);
1133         if (e->appt_head && e->appt_count >= 0)
1134                 csa_free(e->appt_head); 
1135         e->appt_head = entry_list;
1136         e->appt_count = j;
1137         for (i = 0; i < j; i++)
1138                 add_to_appt_list(entry_list[i], e);
1139         if (j <= 0)
1140                 XtSetSensitive(e->appt_list, False);
1141         else
1142                 XtSetSensitive(e->appt_list, True);
1143 }
1144
1145
1146 static void
1147 set_list_title(Editor *e) {
1148         Calendar        *c = e->cal;
1149         Props           *p = (Props *)c->properties;
1150         char            *header;
1151         char            buffer[BUFSIZ];
1152         char            buffer2[BUFSIZ];
1153         XmString        xmstr;
1154
1155         switch (e->view_list_glance) {
1156                 case yearGlance:
1157                                 header = catgets(c->DT_catd, 1, 704, "Year of %d");
1158                                 sprintf(buffer, header, year(e->view_list_date));
1159                                 break;
1160                 case monthGlance:
1161                                 header = catgets(c->DT_catd, 1, 705, "%s");
1162                                 format_date(e->view_list_date+1, get_int_prop(p, CP_DATEORDERING), buffer2, 0, 0, 0);
1163                                 sprintf(buffer, header, buffer2);
1164                                 break;
1165                 case weekGlance:
1166                                 header = catgets(c->DT_catd, 1, 706, "Week of %s");
1167                                 format_date(e->view_list_date+1, get_int_prop(p, CP_DATEORDERING), buffer2, 1, 0, 0);
1168                                 sprintf(buffer, header, buffer2);
1169                                 break;
1170                 case dayGlance:
1171                                 header = catgets(c->DT_catd, 1, 707, "%s");
1172                                 format_date(e->view_list_date+1, get_int_prop(p, CP_DATEORDERING), buffer2, 1, 0, 0);
1173                                 sprintf(buffer, header, buffer2);
1174                                 break;
1175         }
1176         if (e->view_frame) {
1177                 xmstr = XmStringCreateLocalized(buffer);
1178                 XtVaSetValues(e->view_list_label, XmNlabelString, xmstr,
1179                         NULL);
1180                 XmStringFree(xmstr);
1181         }
1182 }
1183 extern void
1184 build_editor_list(Editor *e, Tick date, Glance glance,
1185                   CSA_entry_handle **entry_list, CSA_uint32 *count) {
1186         int                     range_count;
1187         time_t                  start, stop;
1188         CSA_return_code         status;
1189         CSA_enum                *ops;
1190         CSA_attribute           *range_attr;
1191
1192         switch(glance) {
1193         case yearGlance:
1194                 start = lowerbound(jan1(date));
1195                 stop = nextyear(start) - 1;
1196                 break;
1197         case monthGlance:
1198                 start = first_dom(date);
1199                 stop = nextmonth(start) - 1;
1200                 break;
1201         case weekGlance:
1202                 start = first_dow(date);
1203                 stop = nextweek(start) - 1;
1204                 break;
1205         case dayGlance:
1206         default:
1207                 start = lowerbound(date);
1208                 stop = nextday(start) - 1;
1209                 break;
1210         }
1211
1212         setup_range(&range_attr, &ops, &range_count, start, stop,
1213                     CSA_TYPE_EVENT, 0, B_FALSE, e->cal->general->version);
1214
1215         status = csa_list_entries(e->cal->cal_handle, range_count, range_attr, ops, count, entry_list, NULL);
1216         backend_err_msg(e->frame, e->cal->view->current_calendar, status,
1217                         ((Props_pu *)e->cal->properties_pu)->xm_error_pixmap);
1218         if (status != CSA_SUCCESS) {
1219                 *entry_list = NULL;
1220                 *count = 0;
1221         }
1222         free_range(&range_attr, &ops, range_count);
1223 }
1224
1225 extern int
1226 build_editor_view(Editor *e, Glance glance, Boolean redisplay) {
1227         int                     cnt;
1228         CSA_uint32              entry_count;
1229         char                    *buf, *what_str, str1[MAXNAMELEN],
1230                                 str2[MAXNAMELEN];
1231         CSA_entry_handle        *entry_list;
1232         Lines                   *lines;
1233         Props                   *p = (Props *)e->cal->properties;
1234         XmString                str;
1235         CSA_return_code         status;
1236         OrderingType            o = get_int_prop(p, CP_DATEORDERING);
1237         SeparatorType           s = get_int_prop(p, CP_DATESEPARATOR);
1238         DisplayType             dt = get_int_prop(p, CP_DEFAULTDISP);
1239         Dtcm_appointment        *appt;
1240         Tick                    start_time;
1241
1242         /*
1243         **  First, get the list of appointments and delete all items from the
1244         **  list
1245         */
1246
1247         if (redisplay == True) {
1248  
1249                 /* On a redisplay, rebuild the list based on the
1250                    parameters of the last query. */
1251  
1252                 build_editor_list(e, e->view_list_date, e->view_list_glance, &entry_list,
1253                                 &entry_count);
1254         }
1255         else {
1256                 /* If this is a clean display of the appointment list,
1257                    save the context so that a redisplay can be done if
1258                    something changes, like the display format or something
1259                    like that. */
1260  
1261                 build_editor_list(e, e->cal->view->date, glance, &entry_list,
1262                                 &entry_count);
1263  
1264                 e->view_list_glance = glance;
1265                 e->view_list_date = e->cal->view->date;
1266         }
1267
1268         set_list_title(e);
1269
1270         XmListDeleteAllItems(e->view_list);
1271
1272         /*
1273         **  Now loop through and add each appt to the list
1274         */
1275         appt = allocate_appt_struct(appt_read,
1276                                     e->cal->general->version,
1277                                     CSA_ENTRY_ATTR_START_DATE_I,
1278                                     CSA_ENTRY_ATTR_SUMMARY_I,
1279                                     NULL);
1280         for (cnt = 0; cnt < entry_count; cnt++) {
1281                 /*
1282                 **  Create the text string describing the editor and set that
1283                 **  value in the scrolling list
1284                 */
1285                 status = query_appt_struct(e->cal->cal_handle, entry_list[cnt], appt);
1286                 backend_err_msg(e->frame, e->cal->view->current_calendar, status,
1287                         ((Props_pu *)e->cal->properties_pu)->xm_error_pixmap);
1288                 if (status != CSA_SUCCESS) {
1289                         csa_free(entry_list);
1290                         free_appt_struct(&appt);
1291                         entry_count = cnt = 0;
1292                         continue;
1293                 }
1294
1295                 _csa_iso8601_to_tick(appt->time->value->item.date_time_value, &start_time);
1296                 format_tick(start_time, o, s, str1);
1297                 format_time(start_time, dt, str2);
1298                 lines = text_to_lines(appt->what->value->item.string_value, 1);
1299                 if (lines && lines->s) {
1300                         buf = (char *)ckalloc(cm_strlen(str1) + cm_strlen(str2)
1301                                               + cm_strlen(lines->s) + 5);
1302                         what_str = lines->s;
1303                 } else {
1304                         buf = (char *)ckalloc(cm_strlen(str1)
1305                                               + cm_strlen(str2) + 6);
1306                         what_str = "\0";
1307                 }
1308
1309                 sprintf(buf, "%s  %s  %s", str1, str2, what_str);
1310                 str = XmStringCreateLocalized(buf);
1311                 XmListAddItem(e->view_list, str, 0);
1312
1313                 XmStringFree(str);
1314                 free(buf);
1315                 destroy_lines(lines);
1316         }
1317         if (entry_list && entry_count > 0)
1318                 csa_free(entry_list);
1319         free_appt_struct(&appt);
1320
1321         if (entry_count <= 0)
1322                 XtSetSensitive(e->view_list, False);
1323         else
1324                 XtSetSensitive(e->view_list, True);
1325
1326         return (cnt);
1327 }
1328
1329 boolean_t
1330 compare_repeat_info(
1331         Dtcm_appointment        *old_a,
1332         RFP                     *rfp,
1333         CSA_session_handle      cal_handle,
1334         int                     cal_version)
1335 {
1336         Dtcm_appointment        *appt;
1337         CSA_return_code          status;
1338         CSA_enum                 ops[1];
1339         CSA_entry_handle        *entries;
1340         CSA_uint32               num_entries;
1341
1342         /* Find the start date of the appointment.  If it matches the
1343          * current appt then we don't care if the rules match because we
1344          * allow changes to the rules when you start from the first
1345          * appt.
1346          */
1347         ops[0] = CSA_MATCH_EQUAL_TO;
1348
1349         status = csa_list_entries(cal_handle, 1, old_a->identifier, ops,
1350                         &num_entries, &entries, NULL);
1351
1352         if (status != CSA_SUCCESS || num_entries == 0) {
1353                 return FALSE;
1354         }
1355
1356         appt = allocate_appt_struct(appt_read,
1357                                     cal_version,
1358                                     CSA_ENTRY_ATTR_START_DATE_I,
1359                                     NULL);
1360         status = query_appt_struct(cal_handle, entries[0], appt);
1361         if (status != CSA_SUCCESS) {
1362                 free_appt_struct(&appt);
1363                 return FALSE;
1364         }
1365
1366         csa_free(entries);
1367
1368         if (!strcmp(old_a->time->value->item.date_time_value,
1369                     appt->time->value->item.date_time_value)) {
1370                 free_appt_struct(&appt);
1371                 return TRUE;
1372         }
1373  
1374         free_appt_struct(&appt);
1375  
1376         /* We're not at the first event so we check to see if the rule
1377          * has changed.
1378          */
1379         if (!old_a->repeat_type->value)
1380                 return FALSE;
1381  
1382         if (old_a->repeat_type->value->item.sint32_value !=
1383             rfp->repeat_type)
1384                 return FALSE;
1385
1386         if (!old_a->repeat_interval || !old_a->repeat_interval->value)
1387                 return TRUE;
1388
1389         if (rfp->repeat_type == CSA_X_DT_REPEAT_EVERY_NDAY ||
1390             rfp->repeat_type == CSA_X_DT_REPEAT_EVERY_NWEEK ||
1391             rfp->repeat_type == CSA_X_DT_REPEAT_EVERY_NMONTH)
1392                 if (old_a->repeat_interval->value->item.sint32_value !=
1393                     rfp->repeat_nth)
1394                         return FALSE;
1395
1396         return TRUE;                  
1397 }
1398
1399 void
1400 trim_end_date_from_rule(char *rule, char *newrule)
1401 {
1402         char    *ptr;
1403
1404         /* this is done with the assumption that 'Z' only appears
1405          * in the end date of the rule and that there is at most
1406          * one end date in the rule and that the end date is
1407          * is always at the end of the rule
1408          */
1409         if (ptr = strchr(rule, 'Z')) {
1410                 while (*ptr != ' ')
1411                         ptr--;
1412                 *ptr = '\0';
1413         }
1414         strcpy(newrule, rule);
1415
1416         if (ptr)
1417                 *ptr = ' ';
1418 }
1419
1420 /*
1421  * A single event in a repeating appt is beinging changed.  If the rule is
1422  * not being changed then we need to change it to D1 #1 since the change
1423  * is suppose to effect this appt only.
1424  */
1425 void
1426 change_rule_for_this_one_only(
1427         Calendar         *c,
1428         Dtcm_appointment *new, 
1429         Dtcm_appointment *old)
1430 {
1431         char    buf[BUFSIZ];
1432
1433         if (c->general->version < DATAVER4) {
1434                 if ((new->repeat_type->value->item.sint32_value ==
1435                      old->repeat_type->value->item.sint32_value) &&
1436                     (new->repeat_times->value->item.uint32_value ==
1437                      old->repeat_times->value->item.uint32_value)) {
1438                         new->repeat_type->value->item.sint32_value =
1439                                                 CSA_X_DT_REPEAT_ONETIME;
1440                         new->repeat_times->value->item.uint32_value = 0;
1441                 }
1442         } else {
1443                 /* an end date might be added to the rule if the user
1444                  * has done a delete/change forward operation on this
1445                  * appointment before.  We need to get rid of the
1446                  * end date from the rule otherwise the 2 rules
1447                  * won't match
1448                  */
1449                 trim_end_date_from_rule(old->recurrence_rule->value->\
1450                         item.string_value, buf); 
1451                 if (!strcmp(new->recurrence_rule->value->item.string_value,
1452                             buf)) {
1453                         free (new->recurrence_rule->value->item.string_value);
1454                         new->recurrence_rule->value->item.string_value =
1455                                                 cm_strdup("D1 #1");
1456                 }
1457         }
1458 }
1459
1460 extern Boolean
1461 editor_change(Dtcm_appointment *new_a, CSA_entry_handle old_a, CSA_entry_handle *updated_a,
1462               Calendar *c) {
1463         Editor                  *e = (Editor *)c->editor;
1464         Props_pu                *p = (Props_pu *)c->properties_pu;
1465         CSA_return_code         stat;
1466         CSA_enum                scope;
1467         Dtcm_appointment        *appt;
1468         static int              answer;
1469
1470         answer = 0;
1471         appt = allocate_appt_struct(appt_read,
1472                                     c->general->version,
1473                                     CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I,
1474                                     CSA_X_DT_ENTRY_ATTR_REPEAT_TIMES_I,
1475                                     CSA_X_DT_ENTRY_ATTR_REPEAT_INTERVAL_I,
1476                                     CSA_X_DT_ENTRY_ATTR_REPEAT_OCCURRENCE_NUM_I,
1477                                     CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER_I,
1478                                     CSA_ENTRY_ATTR_START_DATE_I,
1479                                     CSA_ENTRY_ATTR_RECURRENCE_RULE_I,
1480                                     NULL);
1481         stat = query_appt_struct(c->cal_handle, old_a, appt);
1482         backend_err_msg(e->frame, c->view->current_calendar, stat,
1483                         p->xm_error_pixmap);
1484         if (stat != CSA_SUCCESS) {
1485                 free_appt_struct(&appt);
1486                 return FALSE;
1487         }
1488
1489         if ((appt->repeat_type->value->item.sint32_value == CSA_X_DT_REPEAT_OTHER) ||
1490             (appt->repeat_type->value->item.sint32_value == CSA_X_DT_REPEAT_OTHER_WEEKLY) ||
1491             (appt->repeat_type->value->item.sint32_value == CSA_X_DT_REPEAT_OTHER_MONTHLY) ||
1492             (appt->repeat_type->value->item.sint32_value == CSA_X_DT_REPEAT_OTHER_YEARLY)) {
1493                 char *title = XtNewString(catgets(c->DT_catd, 1, 258,
1494                                       "Calendar : Appointment Editor - Change"));
1495                 char *text = XtNewString(catgets(c->DT_catd, 1, 708,
1496                                         "This appointment repeats in an unknown fashion.  All occurrences will be changed\nDo you still wish to change it?"));
1497                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
1498                 char *ident4 = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
1499                 answer = dialog_popup(e->frame,
1500                                 DIALOG_TITLE, title,
1501                                 DIALOG_TEXT, text,
1502                                 BUTTON_IDENT, 1, ident1,
1503                                 BUTTON_IDENT, 4, ident4,
1504                                 DIALOG_IMAGE, p->xm_question_pixmap,
1505                                 NULL);
1506                 XtFree(ident4);
1507                 XtFree(ident1);
1508                 XtFree(text);
1509                 XtFree(title);
1510         }
1511         else if (appt->repeat_type->value->item.sint32_value != 
1512                 CSA_X_DT_REPEAT_ONETIME) {
1513                 char *title = XtNewString(catgets(c->DT_catd, 1, 258,
1514                                 "Calendar : Appointment Editor - Change"));
1515                 char *text = XtNewString(catgets(c->DT_catd, 1, 268,
1516                                 "This appointment is part of a repeating series.\nDo you want to change ...?"));
1517                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
1518                 char *ident2 = XtNewString(catgets(c->DT_catd, 1, 270,
1519                                 "This One Only"));
1520                 char *ident3 = XtNewString(catgets(c->DT_catd, 1, 271, "Forward"));
1521                 char *ident4 = XtNewString(catgets(c->DT_catd, 1, 272, "All"));
1522                 answer = dialog_popup(e->frame,
1523                         DIALOG_TITLE, title,
1524                         DIALOG_TEXT, text,
1525                         BUTTON_IDENT, 1, ident1,
1526                         BUTTON_IDENT, 2, ident2,
1527                         BUTTON_IDENT, 3, ident3,
1528                         (compare_repeat_info(appt, &(e->rfp), c->cal_handle, c->general->version) ?
1529                                 BUTTON_IDENT : BUTTON_INSENSITIVE), 
1530                                         4, ident4,
1531                         DIALOG_IMAGE, p->xm_question_pixmap,
1532                         NULL);
1533                 XtFree(ident4);
1534                 XtFree(ident3);
1535                 XtFree(ident2);
1536                 XtFree(ident1);
1537                 XtFree(text);
1538                 XtFree(title);
1539                 if (answer == 2)
1540                         change_rule_for_this_one_only(c, new_a, appt);
1541         }
1542
1543         switch(answer) {
1544         case 1:
1545                 free_appt_struct(&appt);
1546                 return False;
1547         case 2:
1548                 scope = CSA_SCOPE_ONE;
1549                 break;
1550         case 3:
1551                 scope = CSA_SCOPE_FORWARD;
1552                 break;
1553         case 4:
1554         default:
1555                 scope = CSA_SCOPE_ALL;
1556                 break;
1557         }
1558
1559         /* We are not allowed to change the type of the entry, so we will 
1560            remove that particular entry from the list for writing. */
1561
1562         if (new_a->type) {
1563                 if (new_a->type->name){
1564                         free(new_a->type->name);
1565                         new_a->type->name = NULL;
1566                 }
1567         }
1568
1569         /* if the repeat type/times is changed, reset the sequence end date */
1570         if (c->general->version == DATAVER3 &&
1571             appt->repeat_type->value->item.sint32_value !=
1572             CSA_X_DT_REPEAT_ONETIME &&
1573             (appt->repeat_type->value->item.sint32_value !=
1574              new_a->repeat_type->value->item.sint32_value ||
1575              appt->repeat_times->value->item.uint32_value !=
1576              new_a->repeat_times->value->item.uint32_value))
1577         {
1578                 if (new_a->sequence_end_date && new_a->sequence_end_date->value)
1579                 {
1580                         if (new_a->sequence_end_date->value->item.date_time_value)
1581                                 free(new_a->sequence_end_date->value->\
1582                                         item.date_time_value);
1583                         free(new_a->sequence_end_date->value);
1584                         new_a->sequence_end_date->value = NULL;
1585                 }
1586         } else {
1587                 if (new_a->sequence_end_date && new_a->sequence_end_date->name)
1588                 {
1589                         free (new_a->sequence_end_date->name);
1590                         new_a->sequence_end_date->name = NULL;
1591                 }
1592         }
1593
1594         free_appt_struct(&appt);
1595
1596         stat = csa_update_entry_attributes(c->cal_handle, old_a, scope, CSA_FALSE, new_a->count, new_a->attrs, updated_a, NULL);
1597         backend_err_msg(e->frame, c->view->current_calendar, stat,
1598                         p->xm_error_pixmap);
1599         if (stat != CSA_SUCCESS)
1600                 return FALSE;
1601
1602         set_editor_msg_defaults(e);
1603         add_all_appt(e);
1604         if (editor_view_showing(e))
1605                 build_editor_view(e, dayGlance, False);
1606
1607         if (geditor_showing((GEditor *)calendar->geditor))
1608                 add_all_gappt((GEditor *)calendar->geditor);
1609
1610         reset_alarm(c);
1611         invalidate_cache(c);
1612         paint_canvas(c, NULL, RENDER_CLEAR_FIRST);
1613
1614         if (c->browser)
1615                 br_display(c);
1616
1617         if (geditor_showing((GEditor *)c->geditor))
1618                 add_all_gappt((GEditor *)c->geditor);
1619
1620         return True;
1621 }
1622
1623 extern void
1624 editor_clean_up(Editor *e) {
1625         if (e->appt_head && e->appt_count >= 0)
1626                 csa_free(e->appt_head); 
1627         e->appt_head = NULL;
1628         e->appt_count = 0;
1629 }
1630
1631 extern Boolean
1632 editor_delete(CSA_entry_handle entry, Calendar *c) {
1633         Editor                  *e = (Editor *)c->editor;
1634         Props_pu                *p = (Props_pu *)c->properties_pu;
1635         CSA_return_code         stat;
1636         CSA_enum                scope;
1637         Dtcm_appointment        *appt;
1638         static int      answer;
1639
1640         answer = 0;
1641         appt = allocate_appt_struct(appt_read, 
1642                                 c->general->version,
1643                                 CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I, 
1644                                 NULL);
1645         stat = query_appt_struct(c->cal_handle, entry, appt);
1646         backend_err_msg(e->frame, c->view->current_calendar, stat,
1647                         p->xm_error_pixmap);
1648         if (stat != CSA_SUCCESS) {
1649                 free_appt_struct(&appt);
1650                 return False;
1651         }
1652
1653         if (appt->repeat_type->value) {
1654                 if (appt->repeat_type->value->item.sint32_value != CSA_X_DT_REPEAT_ONETIME) {
1655                         char *title = XtNewString(catgets(c->DT_catd, 1, 252,
1656                                       "Calendar : Appointment Editor - Delete"));
1657                         char *text = XtNewString(catgets(c->DT_catd, 1, 274,
1658                                         "This appointment is part of a repeating series.\nDo you want to delete ...?"));
1659                         char *ident1 = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
1660                         char *ident2 = XtNewString(catgets(c->DT_catd, 1, 270,
1661                                         "This One Only"));
1662                         char *ident3 = XtNewString(catgets(c->DT_catd, 1, 271, "Forward"));
1663                         char *ident4 = XtNewString(catgets(c->DT_catd, 1, 272, "All"));
1664                         answer = dialog_popup(e->frame,
1665                                 DIALOG_TITLE, title,
1666                                 DIALOG_TEXT, text,
1667                                 BUTTON_IDENT, 1, ident1,
1668                                 BUTTON_IDENT, 2, ident2,
1669                                 BUTTON_IDENT, 3, ident3,
1670                                 BUTTON_IDENT, 4, ident4,
1671                                 DIALOG_IMAGE, p->xm_question_pixmap,
1672                                 NULL);
1673                         XtFree(ident4);
1674                         XtFree(ident3);
1675                         XtFree(ident2);
1676                         XtFree(ident1);
1677                         XtFree(text);
1678                         XtFree(title);
1679                 }
1680         }
1681         else if (appt->recurrence_rule->value) {
1682                 char *title = XtNewString(catgets(c->DT_catd, 1, 252,
1683                                       "Calendar : Appointment Editor - Delete"));
1684                 char *text = XtNewString(catgets(c->DT_catd, 1, 711,
1685                                         "This appointment repeats in an unknown fashion.  All occurrences will be deleted\nDo you still wish to delete it?"));
1686                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
1687                 char *ident4 = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
1688                 answer = dialog_popup(e->frame,
1689                                 DIALOG_TITLE, title,
1690                                 DIALOG_TEXT, text,
1691                                 BUTTON_IDENT, 1, ident1,
1692                                 BUTTON_IDENT, 4, ident4,
1693                                 DIALOG_IMAGE, p->xm_question_pixmap,
1694                                 NULL);
1695                 XtFree(ident4);
1696                 XtFree(ident1);
1697                 XtFree(text);
1698                 XtFree(title);
1699         }
1700         free_appt_struct(&appt);
1701
1702         switch(answer) {
1703         case 1:
1704                 return False;
1705         case 2:
1706                 scope = CSA_SCOPE_ONE;
1707                 break;
1708         case 3:
1709                 scope = CSA_SCOPE_FORWARD;
1710                 break;
1711         case 4:
1712         default:
1713                 scope = CSA_SCOPE_ALL;
1714                 break;
1715         }
1716
1717         stat = csa_delete_entry(c->cal_handle, entry, scope, NULL);
1718         backend_err_msg(e->frame, c->view->current_calendar, stat,
1719                         p->xm_error_pixmap);
1720         if (stat != CSA_SUCCESS)
1721                 return FALSE;
1722
1723         set_editor_msg_defaults(e);
1724         add_all_appt(e);
1725         if (editor_view_showing(e))
1726                 build_editor_view(e, dayGlance, False);
1727         reset_alarm(c);
1728         invalidate_cache(c);
1729         paint_canvas(c, NULL, RENDER_CLEAR_FIRST);
1730
1731         if (c->browser)
1732                 br_display(c);
1733
1734         return True;
1735 }
1736
1737 extern Boolean
1738 editor_insert(Dtcm_appointment *appt, CSA_entry_handle *new_a, Calendar *c) {
1739         CSA_return_code stat;
1740         Editor          *e = (Editor *)c->editor;
1741         Props_pu        *p = (Props_pu *)c->properties_pu;
1742         CSA_enum                scope;
1743         static int              answer=0;
1744
1745         /* the gui does not support specifying the sequence end date */
1746         if (appt->sequence_end_date && appt->sequence_end_date->name) {
1747                 free(appt->sequence_end_date->name);
1748                 appt->sequence_end_date->name = NULL;
1749         }
1750
1751         if ((appt->repeat_type) && (appt->repeat_type->value) &&
1752            (appt->repeat_type->value->item.sint32_value != CSA_X_DT_REPEAT_ONETIME))
1753         {
1754                 char *title = XtNewString(catgets(c->DT_catd, 1, 1101,
1755                                         "Insert Appointment"));
1756                 char *text = XtNewString(catgets(c->DT_catd, 1, 984,
1757                                         "This appointment is part of a repeating series.\nDo you want to insert appointment ...?"));
1758                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
1759                 char *ident4 = XtNewString(catgets(c->DT_catd, 1, 272, "All"));
1760                         answer = dialog_popup(e->frame,
1761                                 DIALOG_TITLE, title,
1762                                 DIALOG_TEXT, text,
1763                                 BUTTON_IDENT, 1, ident1,
1764                                 BUTTON_IDENT, 4, ident4,
1765                                 DIALOG_IMAGE, p->xm_question_pixmap,
1766                                 NULL);
1767                 XtFree(ident4);
1768                 XtFree(ident1);
1769                 XtFree(text);
1770                 XtFree(title);
1771         }
1772
1773         switch(answer) {
1774         case 1:
1775                 /*
1776                  * Free the CSA_buffer here since before, this routine
1777                  * only returned false when failure to obtain the CSA_structure
1778                  * occurred.
1779                  */
1780                 csa_free((CSA_buffer)new_a);
1781                 return 2;
1782         case 4:
1783         default:
1784                 /*
1785                  * scope is not used at this time.  However, to follow
1786                  * the change/delete style, this is here so in case
1787                  * later the same type of dialog is required.
1788                  */
1789                 scope = CSA_SCOPE_ALL;
1790                 break;
1791         }
1792
1793         stat = csa_add_entry(c->cal_handle, appt->count, appt->attrs, new_a, NULL);
1794         backend_err_msg(c->frame, c->view->current_calendar, stat,
1795                         p->xm_error_pixmap);
1796         if (stat != CSA_SUCCESS)
1797                 return FALSE;
1798
1799         set_editor_msg_defaults(e);
1800         add_all_appt(e);
1801         if (editor_view_showing(e))
1802                 build_editor_view(e, dayGlance, False);
1803
1804         if (geditor_showing((GEditor *)calendar->geditor))
1805                 add_all_gappt((GEditor *)calendar->geditor);
1806
1807         reset_alarm(c);
1808         invalidate_cache(c);
1809         paint_canvas(c, NULL, RENDER_CLEAR_FIRST);
1810
1811         if (c->browser)
1812                 br_display(c);
1813         return True;
1814 }
1815
1816 extern Boolean
1817 editor_created(Editor *e) {
1818         if (!e || !e->base_form_mgr)
1819                 return False;
1820         return True;
1821 }
1822
1823 /*
1824 **  Return the nth appointment from the array
1825 */
1826 extern CSA_entry_handle
1827 editor_nth_appt(Editor *e, int idx) {
1828         if (idx >= 0 && idx < e->appt_count)
1829                 return e->appt_head[idx];
1830         return 0;
1831 }
1832
1833 extern Boolean
1834 editor_showing(Editor *e) {
1835         if (e)
1836                 return e->editor_is_up;
1837         return False;
1838 }
1839
1840 extern Boolean
1841 editor_view_showing(Editor *e) {
1842         if (e)
1843                 return e->editor_view_is_up;
1844         return False;
1845 }
1846
1847 /*
1848 **  External function to set editor defaults
1849 */
1850 extern void
1851 set_editor_defaults(Editor *e, Tick start, Tick stop, Boolean show_notime) {
1852         if (start > 0 || stop > 0) {
1853                 load_dssw_times(&e->dssw, start, stop, show_notime);
1854                 set_dssw_defaults(&e->dssw, e->cal->view->date, False);
1855         } else
1856                 set_dssw_defaults(&e->dssw, e->cal->view->date, True);
1857         if (e->reminders.bfpm_form_mgr) {
1858                 set_rfp_defaults(&e->rfp);
1859                 set_reminders_defaults(&e->reminders);
1860         }
1861         set_message(e->message_text, " ");
1862
1863         e->dsswFlags = 0;
1864         e->rfpFlags = 0;
1865 }
1866
1867 extern void
1868 set_editor_title(Editor *e, char *name) {
1869         char            buf[MAXNAMELEN];
1870         Calendar        *c = e->cal;
1871
1872         if (e->frame) {
1873                 sprintf(buf, "%s - %s", catgets(c->DT_catd, 1, 279,
1874                         "Calendar : Appointment Editor"), name);
1875                 XtVaSetValues(e->frame, XmNtitle, buf,
1876                         NULL);
1877         }
1878 }
1879
1880 extern void
1881 set_editor_vals(Editor *e, Tick start, Tick stop) {
1882         if (start > 0 || stop > 0)
1883                 load_dssw_times(&e->dssw, start, stop, False);
1884         set_dssw_vals(&e->dssw, e->cal->view->date);
1885         set_rfp_vals(&e->rfp);
1886         set_reminders_vals(&e->reminders, True);
1887 }
1888
1889 extern void
1890 show_editor(Calendar *c, time_t start, time_t stop, Boolean show_notime) {
1891         Editor  *e = (Editor *)c->editor;
1892
1893         if (!editor_created(e))
1894                 e_make_editor(c);
1895         else if (!XtIsManaged(e->base_form_mgr))
1896                 XtManageChild(e->base_form_mgr);
1897         else
1898                 XRaiseWindow(XtDisplay(e->base_form_mgr),
1899                              XtWindow(XtParent(e->base_form_mgr)));
1900         if (!editor_showing(e)) {
1901                 ds_position_popup(c->frame, e->frame, DS_POPUP_LOR);
1902                 XmProcessTraversal(e->dssw.what_text, XmTRAVERSE_CURRENT);
1903                 XtVaSetValues(e->base_form_mgr, 
1904                                 XmNinitialFocus, e->dssw.what_text, 
1905                                 NULL);
1906         }
1907
1908         if (! e->editor_is_up)
1909             {
1910             e->editor_is_up = True;
1911             set_editor_defaults(e, start, stop, show_notime);
1912         }
1913         add_all_appt(e);
1914         if (e->frame) XtPopup(e->frame, XtGrabNone);
1915         /* if (e->view_frame) XtPopup(e->view_frame, XtGrabNone); */
1916 }
1917
1918 extern void
1919 show_editor_view(Calendar *c, Glance glance) {
1920         Editor          *e = (Editor *)c->editor;
1921         Props_pu        *p = (Props_pu *)c->properties_pu;
1922
1923         if (!e->view_frame) {
1924                 e->cal = c;
1925                 e_build_view_popup(e);
1926         }
1927
1928         XtVaSetValues(e->view_form, XmNdefaultButton, e->view_cancel_button, NULL);
1929         XtVaSetValues(e->view_form, XmNcancelButton, e->view_cancel_button, NULL);
1930
1931
1932         if (build_editor_view(e, glance, False) <= 0) {
1933                 char *title = XtNewString(catgets(c->DT_catd, 1, 280,
1934                                 "Calendar : Error - Appointment List"));
1935                 char *text = XtNewString(catgets(c->DT_catd, 1, 281,
1936                                 "Sorry, no appointments to list.     "));
1937                 char *ident1 = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
1938                 dialog_popup(e->cal->frame,
1939                         DIALOG_TITLE, title,
1940                         DIALOG_TEXT, text,
1941                         BUTTON_IDENT, 1, ident1,
1942                         DIALOG_IMAGE, p->xm_error_pixmap,
1943                         NULL);
1944                 XtFree(ident1);
1945                 XtFree(text);
1946                 XtFree(title);
1947                 XtUnmanageChild(e->view_form);
1948                 e->editor_view_is_up = False;
1949         } else {
1950                 if (!editor_view_showing(e))
1951                         ds_position_popup(c->frame, e->view_frame,
1952                                           DS_POPUP_LOR);
1953                 XtManageChild(e->view_form);
1954                 e->editor_view_is_up = True;
1955         }
1956         /* if (e->frame) XtPopup(e->frame, XtGrabNone); */
1957         if (e->view_frame) XtPopup(e->view_frame, XtGrabNone);
1958 }
1959 /*
1960 **  Function to set some editor defaults
1961 */
1962 static void
1963 set_editor_msg_defaults(Editor *e) {
1964         set_dssw_defaults(&e->dssw, e->cal->view->date, False);
1965         set_message(e->message_text, " ");
1966 }