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