Files
cdesktop/cde/programs/dtcm/dtcm/editor.c
2018-07-13 19:02:57 +01:00

1969 lines
58 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $TOG: editor.c /main/13 1999/07/01 11:44:34 mgreess $ */
/*
* (c) Copyright 1993, 1994 Hewlett-Packard Company
* (c) Copyright 1993, 1994 International Business Machines Corp.
* (c) Copyright 1993, 1994 Novell, Inc.
* (c) Copyright 1993, 1994 Sun Microsystems, Inc.
*/
#include <EUSCompat.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <Xm/Xm.h>
#include <Xm/DialogS.h>
#include <Xm/Form.h>
#include <Xm/List.h>
#include <Xm/Frame.h>
#include <Xm/PushB.h>
#include <Xm/RowColumn.h>
#include <Xm/ScrolledW.h>
#include <Xm/SeparatoG.h>
#include <Xm/Text.h>
#include <Xm/ToggleBG.h>
#include <Xm/LabelG.h>
#include <Xm/DragDrop.h>
#include <Xm/Screen.h>
#include <Dt/HourGlass.h>
#include <Dt/Dt.h>
#include <Dt/Dnd.h>
#include <Dt/Icon.h>
#include "editor.h"
#include "calendar.h"
#include "datefield.h"
#include "deskset.h"
#include "getdate.h"
#include "format.h"
#include "timeops.h"
#include "props.h"
#include "props_pu.h"
#include "group_editor.h"
#include "browser.h"
#include "util.h"
#include "dnd.h"
#include "help.h"
#ifdef SVR4
#include <sys/param.h>
#endif /* SVR4 */
static void e_build_expand(Editor *);
static void clear_flag_on_modify(Widget, XtPointer, XtPointer);
/* Absolute value macro */
#ifndef ABS
#define ABS(x) (((x) > 0) ? (x) : (-(x)))
#endif
static void set_editor_msg_defaults();
/*******************************************************************************
**
** Functions static to editor.c
**
*******************************************************************************/
static void
clear_flag_on_modify(Widget w, XtPointer uData, XtPointer cbData)
{
int *flagP = (int *)uData;
*flagP = 0;
}
/*
** This function will take appointment values and stuff them into a form.
*/
static void
appt_to_form(Editor *e, CSA_entry_handle a) {
char buf[MAXNAMELEN];
CSA_return_code status;
Dtcm_appointment *appt;
if (!e->reminders.bfpm_form_mgr) {
e_build_expand(e);
set_rfp_defaults(&e->rfp);
set_reminders_defaults(&e->reminders);
}
if (!dssw_appt_to_form(&e->dssw, a))
return;
e->dsswFlags = 0;
if (!rfp_appt_to_form(&e->rfp, a))
return;
e->rfpFlags = 0;
if (!reminders_appt_to_form(&e->reminders, a))
return;
appt = allocate_appt_struct(appt_read,
e->cal->general->version,
CSA_ENTRY_ATTR_ORGANIZER_I,
NULL);
status = query_appt_struct(e->cal->cal_handle,a, appt);
backend_err_msg(e->frame, e->cal->view->current_calendar, status,
((Props_pu *)e->cal->properties_pu)->xm_error_pixmap);
if (status != CSA_SUCCESS) {
free_appt_struct(&appt);
return;
}
sprintf(buf, "%s: %s", catgets(e->cal->DT_catd, 1, 251, "Author"),
appt->author->value->item.calendar_user_value->user_name);
set_message(e->message_text, buf);
free_appt_struct(&appt);
}
/*
** List selection procedure will get the correct appointment, then call
** appt_to_form to load it into the UI.
*/
static void
e_list_select_proc(Widget w, XtPointer client_data, XtPointer data) {
CSA_entry_handle a;
Editor *e = (Editor *)client_data;
XmListCallbackStruct *cbs = (XmListCallbackStruct *) data;
if (a = editor_nth_appt(e, cbs->item_position - 1))
appt_to_form(e, a);
XtSetSensitive(e->delete_button, True);
XtSetSensitive(e->change_button, True);
}
/*
** Quit handler for the editor and the editor view popup
*/
static void
e_quit_handler(Widget w, XtPointer cdata, XtPointer data) {
Editor *e = (Editor *)cdata;
Widget popMeDown = NULL;
if (w == e->frame) {
editor_clean_up(e);
e->editor_is_up = False;
popMeDown = e->base_form_mgr;
} else if (w == e->view_frame)
{
e->editor_view_is_up = False;
popMeDown = e->view_form;
}
if(popMeDown) {
XtUnmanageChild(popMeDown);
}
}
static void
e_view_cancel_cb(
Widget widget,
XtPointer client_data,
XmPushButtonCallbackStruct *cbs)
{
Editor *e = (Editor *)client_data;
XtUnmanageChild(e->view_form);
}
/*
** Build the popup to display, in list fashion, the appts for a given period.
*/
static void
e_build_view_popup(Editor *e) {
int ac = 0;
Arg args[15];
XmString xmstr;
Calendar *c = e->cal;
Widget separator;
char *title;
/*
** Dialog shell and stuff
*/
title = XtNewString(catgets(c->DT_catd, 1, 1086,
"Calendar : Appointment List"));
e->view_frame = XtVaCreatePopupShell("appt_list",
xmDialogShellWidgetClass, e->cal->frame,
XmNtitle, title,
XmNdeleteResponse, XmDO_NOTHING,
XmNautoUnmanage, False,
XmNallowShellResize, True,
NULL);
XtFree(title);
setup_quit_handler(e->view_frame, e_quit_handler, (caddr_t)e);
e->view_form = XtVaCreateWidget("apptform",
xmFormWidgetClass, e->view_frame,
XmNfractionBase, 2,
XmNmarginWidth, 2,
XmNautoUnmanage, False,
NULL);
xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 680, "Close"));
e->view_cancel_button = XtVaCreateWidget("cancel",
xmPushButtonWidgetClass, e->view_form,
XmNlabelString, xmstr,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, 0,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, 1,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftOffset, 10,
NULL);
XmStringFree(xmstr);
XtAddCallback(e->view_cancel_button, XmNactivateCallback, (XtCallbackProc) e_view_cancel_cb, e);
xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 77, "Help"));
e->view_help_button = XtVaCreateWidget("help",
xmPushButtonWidgetClass, e->view_form,
XmNlabelString, xmstr,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, 1,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, 2,
XmNbottomAttachment, XmATTACH_FORM,
XmNrightOffset, 10,
NULL);
XmStringFree(xmstr);
separator = XtVaCreateWidget("separator",
xmSeparatorGadgetClass,
e->view_form,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, e->view_cancel_button,
XmNbottomOffset, 5,
NULL);
xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 703, "context"));
e->view_list_label= XtVaCreateWidget("type_label",
xmLabelGadgetClass, e->view_form,
XmNtopAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
XmNleftOffset, 5,
XmNtopOffset, 5,
XmNlabelString, xmstr,
NULL);
XmStringFree(xmstr);
ac = 0;
XtSetArg(args[ac], XmNwidth, 300); ac++;
XtSetArg(args[ac], XmNheight, 200); ac++;
XtSetArg(args[ac], XmNscrolledWindowMarginHeight, 5); ac++;
XtSetArg(args[ac], XmNscrolledWindowMarginWidth, 5); ac++;
XtSetArg(args[ac], XmNlistSpacing, 5); ac++;
XtSetArg(args[ac], XmNlistSizePolicy, XmCONSTANT); ++ac;
XtSetArg(args[ac], XmNrightAttachment, XmATTACH_FORM); ++ac;
XtSetArg(args[ac], XmNrightOffset, 2); ++ac;
XtSetArg(args[ac], XmNleftAttachment, XmATTACH_FORM); ++ac;
XtSetArg(args[ac], XmNtopAttachment, XmATTACH_WIDGET); ++ac;
XtSetArg(args[ac], XmNtopWidget, e->view_list_label); ++ac;
XtSetArg(args[ac], XmNbottomAttachment, XmATTACH_WIDGET); ++ac;
XtSetArg(args[ac], XmNbottomWidget, separator); ++ac;
XtSetArg(args[ac], XmNbottomOffset, 5); ++ac;
XtSetArg(args[ac], XmNdoubleClickInterval, 5); ++ac;
e->view_list = XmCreateScrolledList(e->view_form, "view_list",
args, ac);
XtAddCallback(e->view_help_button, XmNactivateCallback,
(XtCallbackProc)help_cb, APPT_LIST_HELP_BUTTON);
XtAddCallback(e->view_form, XmNhelpCallback,
(XtCallbackProc)help_cb, (XtPointer) APPT_LIST_HELP_BUTTON);
XtManageChild(e->view_list);
ManageChildren(e->view_form);
XtManageChild(e->view_form);
e->editor_view_is_up = False;
}
/*
** This function creates the expando stuff on a form manager.
*/
static void
e_build_expand(
Editor *e)
{
Props *p = (Props *)e->cal->properties;
/*
** Build the rfp "widget"
*/
e->rfpFlags = 0;
build_rfp(&e->rfp, e->cal, e->base_form_mgr);
XtVaSetValues(e->rfp.rfp_form_mgr,
XmNleftAttachment, XmATTACH_FORM,
XmNleftOffset, 3,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, e->separator1,
NULL);
ManageChildren(e->rfp.rfp_form_mgr);
XtAddCallback(e->rfp.repeat_menu, XmNselectionCallback,
clear_flag_on_modify, (XtPointer)&e->rfpFlags);
/*
** Call the build_reminders function to build that widget
*/
build_reminders(&e->reminders, e->cal, e->base_form_mgr);
XtVaSetValues(e->reminders.bfpm_form_mgr,
XmNleftAttachment, XmATTACH_WIDGET,
XmNleftWidget, e->rfp.rfp_form_mgr,
XmNrightOffset, 3,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, e->separator1,
NULL);
ManageChildren(e->reminders.bfpm_form_mgr);
}
/*
** Button action procedures manage and unmanage the "extra" stuff in the UI to
** make it visible and invisible to the user.
*/
static void
e_expand_ui_proc(Widget w, XtPointer client_data, XtPointer data) {
Editor *e = (Editor *)client_data;
Props_pu *p = (Props_pu *)e->cal->properties_pu;
XmString xmstr;
Dimension h, height, width;
static Boolean expand_state_closed = True;
XtVaGetValues(e->appt_list_sw,
XmNheight, &height,
XmNwidth, &width,
NULL);
if (expand_state_closed) {
Widget children[2];
if (!e->reminders.bfpm_form_mgr) {
e_build_expand(e);
set_rfp_defaults(&e->rfp);
set_reminders_defaults(&e->reminders);
}
XtRealizeWidget(e->rfp.rfp_form_mgr);
XtRealizeWidget(e->reminders.bfpm_form_mgr);
xmstr = XmStringCreateLocalized(catgets(e->cal->DT_catd, 1, 625,
"Less"));
XtVaSetValues(e->expand_ui_button, XmNlabelString, xmstr,
NULL);
XmStringFree(xmstr);
XtVaGetValues(e->reminders.bfpm_form_mgr, XmNheight, &h, NULL);
XtVaSetValues(e->separator1, XmNbottomOffset, h + 10, NULL);
children[0] = e->rfp.rfp_form_mgr;
children[1] = e->reminders.bfpm_form_mgr;
XtManageChildren(children, 2);
expand_state_closed = False;
} else {
xmstr = XmStringCreateLocalized(catgets(e->cal->DT_catd, 1, 626,
"More"));
XtVaSetValues(e->expand_ui_button, XmNlabelString, xmstr,
NULL);
XmStringFree(xmstr);
XtUnmanageChild(e->rfp.rfp_form_mgr);
XtUnmanageChild(e->reminders.bfpm_form_mgr);
XtVaSetValues(e->separator1, XmNbottomOffset, 0, NULL);
expand_state_closed = True;
}
XtVaSetValues(e->appt_list_sw,
XmNheight, height,
XmNwidth, width,
NULL);
}
/*
** This function will consume form values and stuff them into an appointment.
*/
static Dtcm_appointment*
form_to_appt(Editor *e) {
boolean_t all_ok;
Dtcm_appointment *a;
/* This code needs to conditionally decide whether to write out
the repeating event specification as an old style set of
specifications, or a new style recurrence rule. In the case
of data versions 1-3, it needs to be the old style. In the
case of version 4 it needs to be the new style. */
a = allocate_appt_struct(appt_write, e->cal->general->version, NULL);
all_ok = dssw_form_to_appt(&e->dssw, a, e->cal->view->current_calendar,
e->cal->view->date);
if (all_ok)
all_ok = rfp_form_to_appt(&e->rfp, a,
e->cal->view->current_calendar);
if (all_ok)
all_ok = reminders_form_to_appt(&e->reminders, a, e->cal->view->current_calendar);
if (!all_ok) {
free_appt_struct(&a);
return NULL;
}
a->type->value->item.sint32_value = CSA_TYPE_EVENT;
a->subtype->value->item.string_value = strdup(CSA_SUBTYPE_APPOINTMENT);
a->state->value->item.sint32_value = CSA_X_DT_STATUS_ACTIVE;
return a;
}
/*
** Action procedures
*/
static void
e_insert_proc(Widget w, XtPointer client_data, XtPointer data) {
Editor *e = (Editor *)client_data;
CSA_entry_handle new_a = 0;
Dtcm_appointment *a;
Calendar *c = e->cal;
if (strcmp(c->calname, c->view->current_calendar) != 0) {
char buf[BUFSIZ], buf2[BUFSIZ];
int answer = 0;
char *title;
char *ident;
/*
* Make sure user really meant to insert appointment
* into somebody elses calendar.
*/
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?"));
sprintf(buf2, "%s %s", catgets(c->DT_catd, 1, 211, "Schedule in"),
c->view->current_calendar);
title = XtNewString(catgets(c->DT_catd, 1, 212,
"Calendar : Schedule Appointment"));
ident = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
answer = dialog_popup(e->frame,
DIALOG_TITLE, title,
DIALOG_TEXT, buf,
BUTTON_IDENT, 1, ident,
BUTTON_IDENT, 2, buf2,
NULL);
XtFree(ident);
XtFree(title);
if (answer == 1)
return;
}
_DtTurnOnHourGlass(e->frame);
if ((a = form_to_appt(e)) != NULL) {
if ((editor_insert(a, &new_a, e->cal)) == True)
csa_free((CSA_buffer)new_a);
free_appt_struct(&a);
}
_DtTurnOffHourGlass(e->frame);
}
static void
e_delete_proc(Widget w, XtPointer client_data, XtPointer data) {
int *item_list = NULL, item_cnt = 0;
CSA_entry_handle a;
Editor *e = (Editor *)client_data;
Calendar *c = e->cal;
Props_pu *p = (Props_pu *)e->cal->properties_pu;
static int answer;
if (strcmp(c->calname, c->view->current_calendar) != 0) {
char buf[BUFSIZ], buf2[BUFSIZ];
char *title;
char *ident;
/*
* Make sure user really meant to delete appointment
* from somebody elses calendar.
*/
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 ?"));
sprintf(buf2, "%s %s", catgets(c->DT_catd, 1, 1005, "Delete from"),
c->view->current_calendar);
title = XtNewString(catgets(c->DT_catd, 1, 252,
"Calendar : Appointment Editor - Delete"));
ident = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
answer = dialog_popup(e->frame,
DIALOG_TITLE, title,
DIALOG_TEXT, buf,
BUTTON_IDENT, 1, ident,
BUTTON_IDENT, 2, buf2,
NULL);
XtFree(ident);
XtFree(title);
if (answer == 1)
return;
}
_DtTurnOnHourGlass(e->frame);
if (!XmListGetSelectedPos(e->appt_list, &item_list, &item_cnt)) {
char *title = XtNewString(catgets(c->DT_catd, 1, 252,
"Calendar : Appointment Editor - Delete"));
char *text = XtNewString(catgets(c->DT_catd, 1, 253,
"Select an appointment and DELETE again."));
char *ident = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
answer = dialog_popup(e->frame,
DIALOG_TITLE, title,
DIALOG_TEXT, text,
BUTTON_IDENT, 1, ident,
DIALOG_IMAGE, p->xm_error_pixmap,
NULL);
XtFree(ident);
XtFree(text);
XtFree(title);
_DtTurnOffHourGlass(e->frame);
return;
}
if (!(a = editor_nth_appt(e, item_list[0] - 1))) {
char *title = XtNewString(catgets(c->DT_catd, 1, 252,
"Calendar : Appointment Editor - Delete"));
char *text = XtNewString(catgets(c->DT_catd, 1, 256,
"Internal error selecting appointment.\nAppointment was not deleted."));
char *ident = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
answer = dialog_popup(e->frame,
DIALOG_TITLE, title,
DIALOG_TEXT, text,
BUTTON_IDENT, 1, ident,
BUTTON_HELP, RESELECT_ERROR_HELP,
DIALOG_IMAGE, p->xm_error_pixmap,
NULL);
XtFree(ident);
XtFree(text);
XtFree(title);
XtFree((XtPointer)item_list);
_DtTurnOffHourGlass(e->frame);
return;
}
XtFree((XtPointer)item_list);
editor_delete(a, e->cal);
_DtTurnOffHourGlass(e->frame);
}
static void
e_change_proc(Widget w, XtPointer client_data, XtPointer data) {
int *item_list = NULL, item_cnt = 0;
Editor *e = (Editor *)client_data;
Calendar *c = e->cal;
CSA_entry_handle old_a, updated_a;
Props_pu *p = (Props_pu *)e->cal->properties_pu;
static int answer;
Dtcm_appointment *new_a;
if (strcmp(c->calname, c->view->current_calendar) != 0) {
char buf[BUFSIZ], buf2[BUFSIZ];
char *title = XtNewString(catgets(c->DT_catd, 1, 258,
"Calendar : Appointment Editor - Change"));
char *ident = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
/*
* Make sure user really meant to insert appointment
* into somebody elses calendar.
*/
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 ?"));
sprintf(buf2, "%s %s", catgets(c->DT_catd, 1, 1006, "Change in"),
c->view->current_calendar);
answer = dialog_popup(e->frame,
DIALOG_TITLE, title,
DIALOG_TEXT, buf,
BUTTON_IDENT, 1, ident,
BUTTON_IDENT, 2, buf2,
NULL);
XtFree(ident);
XtFree(title);
if (answer == 1)
return;
}
_DtTurnOnHourGlass(e->frame);
if (!XmListGetSelectedPos(e->appt_list, &item_list, &item_cnt)) {
char *title = XtNewString(catgets(c->DT_catd, 1, 258,
"Calendar : Appointment Editor - Change"));
char *text = XtNewString(catgets(c->DT_catd, 1, 259,
"Select an appointment and CHANGE again."));
char *ident = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
answer = dialog_popup(e->frame,
DIALOG_TITLE, title,
DIALOG_TEXT, text,
BUTTON_IDENT, 1, ident,
DIALOG_IMAGE, p->xm_error_pixmap,
NULL);
XtFree(ident);
XtFree(text);
XtFree(title);
_DtTurnOffHourGlass(e->frame);
return;
}
if (!(old_a = editor_nth_appt(e, item_list[0] - 1))) {
char *title = XtNewString(catgets(c->DT_catd, 1, 1075,
"Calendar : Error - Change Appointment"));
char *text = XtNewString(catgets(c->DT_catd, 1, 1007,
"Internal error selecting appointment.\nAppointment was not changed."));
char *ident = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
answer = dialog_popup(e->frame,
DIALOG_TITLE, title,
DIALOG_TEXT, text,
BUTTON_IDENT, 1, ident,
DIALOG_IMAGE, p->xm_error_pixmap,
NULL);
XtFree(ident);
XtFree(text);
XtFree(title);
XtFree((XtPointer)item_list);
_DtTurnOffHourGlass(e->frame);
return;
}
XtFree((XtPointer)item_list);
if ((new_a = form_to_appt(e)) == NULL) {
_DtTurnOffHourGlass(e->frame);
return;
}
if (editor_change(new_a, old_a, &updated_a, e->cal))
csa_free((CSA_buffer)updated_a);
free_appt_struct(&new_a);
_DtTurnOffHourGlass(e->frame);
}
static void
e_clear_proc(Widget w, XtPointer client_data, XtPointer data) {
Editor *e = (Editor *)client_data;
set_editor_defaults(e, 0, 0, False);
add_all_appt(e);
}
static void
e_close_proc(Widget w, XtPointer client_data, XtPointer data) {
Editor *e = (Editor *)client_data;
XtUnmanageChild(e->base_form_mgr);
e->editor_is_up = False;
}
/*
* dragMotionHandler
*
* Determine if the pointer has moved beyond the drag threshold while button 1
* was being held down.
*/
void
FormApptDragMotionHandler(
Widget dragInitiator,
XtPointer clientData,
XEvent *event)
{
int diffX, diffY;
Calendar *c = (Calendar *) clientData;
Editor *e = (Editor *) c->editor;
Dimension source_height, source_width;
Position source_x, source_y;
if (!e->doing_drag) {
/* check to see if the iniital value was within the
bounds for the drag source icon. */
XtVaGetValues(e->drag_source,
XmNx, &source_x,
XmNy, &source_y,
XmNheight, &source_height,
XmNwidth, &source_width,
NULL);
if ((event->xmotion.x < source_x) ||
(event->xmotion.y < source_y) ||
(event->xmotion.x > (int) (source_x + source_width)) ||
(event->xmotion.y > (int) (source_y + source_height)))
return;
/*
* If the drag is just starting, set initial button down coords
*/
if (e->initialX == -1 && e->initialY == -1) {
e->initialX = event->xmotion.x;
e->initialY = event->xmotion.y;
}
/*
* Find out how far pointer has moved since button press
*/
diffX = e->initialX - event->xmotion.x;
diffY = e->initialY - event->xmotion.y;
if ((ABS(diffX) >= DRAG_THRESHOLD) ||
(ABS(diffY) >= DRAG_THRESHOLD)) {
e->doing_drag = True;
ApptDragStart(dragInitiator, event, c, SingleEditorIcon);
e->initialX = -1;
e->initialY = -1;
}
}
}
extern void
e_make_editor(Calendar *c)
{
int cnt = 0;
Arg args[15];
Editor *e = (Editor *)c->editor;
Props_pu *p = (Props_pu *)c->properties_pu;
XmString xmstr;
Dimension label_height;
XtTranslations new_translations;
XFontSetExtents listfontextents;
static char translations[] = "\
~c ~s ~m ~a <Btn1Down>:\
dtcm-process-press(ListBeginSelect,TranslationDragStart)\n\
c ~s ~m ~a <Btn1Down>:\
dtcm-process-press(ListBeginToggle,TranslationDragStart)";
static char btn2_translations[] = "\
~c ~s ~m ~a <Btn2Down>:\
dtcm-process-press(ListBeginSelect,TranslationDragStart)\n\
c ~s ~m ~a <Btn2Down>:\
dtcm-process-press(ListBeginToggle,TranslationDragStart)\n\
<Btn2Motion>:ListButtonMotion()\n\
~c ~s ~m ~a <Btn2Up>:ListEndSelect()\n\
c ~s ~m ~a <Btn2Up>:ListEndToggle()";
Boolean btn1_transfer;
new_translations = XtParseTranslationTable(translations);
e->cal = c;
/*
** Dialog shell and the base form
*/
e->frame = XtVaCreatePopupShell("frame",
xmDialogShellWidgetClass, e->cal->frame,
XmNdeleteResponse, XmDO_NOTHING,
XmNallowShellResize, True,
NULL);
set_editor_title(e, c->view->current_calendar);
setup_quit_handler(e->frame, e_quit_handler, (caddr_t)e);
e->base_form_mgr = XtVaCreateWidget("base_form_mgr",
xmFormWidgetClass, e->frame,
XmNautoUnmanage, False,
XmNfractionBase, 8,
NULL);
/*
** Build the stuff in the upper portion of the form - the dssw widget,
** the scrolling appointment list, the expand/contract button, and the
** first separator.
*/
xmstr = XmStringCreateLocalized(
catgets(c->DT_catd, 1, 628, "Time What"));
e->list_label = XtVaCreateWidget("label",
xmLabelGadgetClass, e->base_form_mgr,
XmNlabelString, xmstr,
XmNtopAttachment, XmATTACH_FORM,
XmNtopOffset, 5,
NULL);
XmStringFree(xmstr);
XtVaGetValues(e->list_label, XmNheight, &label_height, NULL);
e->message_text = XtVaCreateWidget("message",
xmLabelGadgetClass, e->base_form_mgr,
XmNalignment, XmALIGNMENT_BEGINNING,
XmNbottomAttachment, XmATTACH_FORM,
XmNbottomOffset, 2,
XmNleftAttachment, XmATTACH_FORM,
XmNleftOffset, 2,
XmNrightAttachment, XmATTACH_FORM,
XmNrightOffset, 2,
NULL);
/*
** Create insert, delete, change, and clear buttons
*/
xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 342, "Insert"));
e->insert_button = XtVaCreateWidget("Insert",
xmPushButtonWidgetClass, e->base_form_mgr,
XmNlabelString, xmstr,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, e->message_text,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, 1,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, 2,
NULL);
XtAddCallback(e->insert_button, XmNactivateCallback, e_insert_proc, e);
XmStringFree(xmstr);
xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 343, "Change"));
e->change_button = XtVaCreateWidget("Change",
xmPushButtonWidgetClass, e->base_form_mgr,
XmNlabelString, xmstr,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, e->message_text,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, 2,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, 3,
XmNsensitive, False,
NULL);
XtAddCallback(e->change_button, XmNactivateCallback, e_change_proc, e);
XmStringFree(xmstr);
xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 419, "Delete"));
e->delete_button = XtVaCreateWidget("Delete",
xmPushButtonWidgetClass, e->base_form_mgr,
XmNlabelString, xmstr,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, e->message_text,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, 3,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, 4,
XmNsensitive, False,
NULL);
XtAddCallback(e->delete_button, XmNactivateCallback, e_delete_proc, e);
XmStringFree(xmstr);
xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 803, "Clear"));
e->clear_button = XtVaCreateWidget("Clear",
xmPushButtonWidgetClass, e->base_form_mgr,
XmNlabelString, xmstr,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, e->message_text,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, 4,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, 5,
NULL);
XtAddCallback(e->clear_button, XmNactivateCallback, e_clear_proc, e);
XmStringFree(xmstr);
xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 923, "Cancel"));
e->close_button = XtVaCreateWidget("Cancel",
xmPushButtonWidgetClass, e->base_form_mgr,
XmNlabelString, xmstr,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, e->message_text,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, 5,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, 6,
NULL);
XtAddCallback(e->close_button, XmNactivateCallback, e_close_proc, e);
XmStringFree(xmstr);
xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 77, "Help"));
e->help_button = XtVaCreateWidget("Help",
xmPushButtonWidgetClass, e->base_form_mgr,
XmNlabelString, xmstr,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, e->message_text,
XmNleftAttachment, XmATTACH_POSITION,
XmNleftPosition, 6,
XmNrightAttachment, XmATTACH_POSITION,
XmNrightPosition, 7,
NULL);
XmStringFree(xmstr);
e->separator2 = XtVaCreateWidget("separator2",
xmSeparatorGadgetClass, e->base_form_mgr,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, e->insert_button,
XmNbottomOffset, 5,
XmNleftAttachment, XmATTACH_FORM,
XmNleftOffset, 5,
XmNrightAttachment, XmATTACH_FORM,
XmNrightOffset, 5,
NULL);
e->separator1 = XtVaCreateWidget("separator1",
xmSeparatorGadgetClass, e->base_form_mgr,
XmNleftAttachment, XmATTACH_FORM,
XmNleftOffset, 5,
XmNrightAttachment, XmATTACH_FORM,
XmNrightOffset, 5,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, e->separator2,
NULL);
xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 626, "More"));
e->expand_ui_button = XtVaCreateWidget("expand_ui_button",
xmPushButtonWidgetClass, e->base_form_mgr,
XmNlabelString, xmstr,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, e->separator1,
XmNbottomOffset, 3,
XmNleftAttachment, XmATTACH_FORM,
XmNleftOffset, 5,
XmNnavigationType, XmTAB_GROUP,
NULL);
XtAddCallback(e->expand_ui_button, XmNactivateCallback,
e_expand_ui_proc, e);
XmStringFree(xmstr);
e->dsswFlags = 0;
build_dssw(&e->dssw, c, e->base_form_mgr, True, True);
XtVaSetValues(e->dssw.dssw_form_mgr,
XmNtopAttachment, XmATTACH_FORM,
XmNtopOffset, label_height + 5,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, e->expand_ui_button,
XmNbottomOffset, 3,
XmNleftAttachment, XmATTACH_FORM,
XmNleftOffset, 5,
NULL);
XtAddCallback(e->dssw.start_text, XmNvalueChangedCallback,
clear_flag_on_modify, (XtPointer)&e->dsswFlags);
XtAddCallback(e->dssw.start_am, XmNvalueChangedCallback,
clear_flag_on_modify, (XtPointer)&e->dsswFlags);
XtAddCallback(e->dssw.start_pm, XmNvalueChangedCallback,
clear_flag_on_modify, (XtPointer)&e->dsswFlags);
XtAddCallback(e->dssw.stop_text, XmNvalueChangedCallback,
clear_flag_on_modify, (XtPointer)&e->dsswFlags);
XtAddCallback(e->dssw.stop_am, XmNvalueChangedCallback,
clear_flag_on_modify, (XtPointer)&e->dsswFlags);
XtAddCallback(e->dssw.stop_pm, XmNvalueChangedCallback,
clear_flag_on_modify, (XtPointer)&e->dsswFlags);
/*
* Add a drag source icon inside the dssw, lower right
*/
xmstr = XmStringCreateLocalized(
catgets(c->DT_catd, 1, 627, "Drag Appt"));
e->drag_source = XtVaCreateWidget("drag_source",
dtIconGadgetClass, e->dssw.dssw_form_mgr,
XmNpixmapPosition, XmPIXMAP_TOP,
XmNstringPosition, XmSTRING_BOTTOM,
XmNalignment, XmALIGNMENT_CENTER,
XmNstring, xmstr,
XmNbottomAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNtraversalOn, False,
XmNbehavior, XmICON_DRAG,
NULL);
XmStringFree(xmstr);
XtAddEventHandler(XtParent(e->drag_source), Button1MotionMask, False,
(XtEventHandler)FormApptDragMotionHandler, (XtPointer) c);
XtVaGetValues((Widget)XmGetXmDisplay(XtDisplay(c->frame)),
"enableBtn1Transfer", &btn1_transfer,
NULL);
/* btn1_transfer is a tri-state variable - see 1195846 */
if ((Boolean)btn1_transfer != True) {
XtAddEventHandler(XtParent(e->drag_source),
Button2MotionMask, False,
(XtEventHandler)FormApptDragMotionHandler,
(XtPointer) c);
}
if (p->drag_icon_xbm)
XtVaSetValues(e->drag_source,
XmNpixmap, p->drag_icon_xbm,
NULL);
XtVaSetValues(e->dssw.what_scrollwindow,
XmNrightAttachment, XmATTACH_WIDGET,
XmNrightWidget, e->drag_source,
NULL);
ManageChildren(e->dssw.dssw_form_mgr);
CalFontExtents(c->fonts->labelfont, &listfontextents);
cnt = 0;
XtSetArg(args[cnt], XmNlistSizePolicy, XmCONSTANT); ++cnt;
XtSetArg(args[cnt], XmNwidth, 15 *
listfontextents.max_logical_extent.width); ++cnt;
XtSetArg(args[cnt], XmNscrollBarDisplayPolicy, XmSTATIC); ++cnt;
XtSetArg(args[cnt], XmNdoubleClickInterval, 5); ++cnt;
e->appt_list = XmCreateScrolledList(e->base_form_mgr, "appt_list",
args, cnt);
e->appt_list_sw = XtParent(e->appt_list);
XtOverrideTranslations(e->appt_list, new_translations);
/* Make btn 2 do dnd of appts */
/* btn1_transfer is a tri-state variable - see 1195846 */
if ((Boolean)btn1_transfer != True) {
new_translations = XtParseTranslationTable(btn2_translations);
XtOverrideTranslations(e->appt_list, new_translations);
}
XtVaSetValues(e->appt_list_sw,
XmNtopAttachment, XmATTACH_FORM,
XmNtopOffset, label_height + 11,
XmNleftAttachment, XmATTACH_WIDGET,
XmNleftWidget, e->dssw.dssw_form_mgr,
XmNleftOffset, 10,
XmNrightAttachment, XmATTACH_FORM,
XmNrightOffset, 5,
XmNbottomAttachment, XmATTACH_WIDGET,
XmNbottomWidget, e->expand_ui_button,
XmNbottomOffset, 3,
NULL);
XtManageChild(e->appt_list);
XtAddCallback(e->appt_list,
XmNbrowseSelectionCallback, e_list_select_proc, e);
XtVaSetValues(e->list_label,
XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET,
XmNleftWidget, e->appt_list_sw,
NULL);
XtAddCallback(e->help_button, XmNactivateCallback,
(XtCallbackProc)help_cb, APPT_EDITOR_HELP_BUTTON);
XtAddCallback(e->base_form_mgr, XmNhelpCallback,
(XtCallbackProc)help_cb, (XtPointer) APPT_EDITOR_HELP_BUTTON);
XtVaSetValues(e->base_form_mgr,
XmNdefaultButton, e->insert_button,
NULL);
XtVaSetValues(e->base_form_mgr,
XmNcancelButton, e->close_button,
NULL);
XmProcessTraversal(e->dssw.what_text, XmTRAVERSE_CURRENT);
XtVaSetValues(e->base_form_mgr,
XmNinitialFocus, e->dssw.what_text,
NULL);
ManageChildren(e->base_form_mgr);
XtManageChild(e->base_form_mgr);
/*
** Set up editor variables. The drag threshold variables are set to
** -1, so we are ready for first dnd operation.
*/
rfp_init(&e->rfp, c, e->base_form_mgr);
reminders_init(&e->reminders, c, e->base_form_mgr);
e->appt_count = 0;
e->appt_head = NULL;
e->initialX = -1;
e->initialY = -1;
e->doing_drag = False;
}
/*******************************************************************************
**
** External functions
**
*******************************************************************************/
extern void
add_to_appt_list(CSA_entry_handle entry, Editor *e) {
char buf[DEFAULT_APPT_LEN];
Props *p = (Props *)e->cal->properties;
XmString str;
CSA_return_code status;
DisplayType dt = get_int_prop(p, CP_DEFAULTDISP);
Dtcm_appointment *appt;
appt = allocate_appt_struct(appt_read,
e->cal->general->version,
CSA_ENTRY_ATTR_START_DATE_I,
CSA_ENTRY_ATTR_SUMMARY_I,
CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,
NULL);
status = query_appt_struct(e->cal->cal_handle, entry, appt);
backend_err_msg(e->frame, e->cal->view->current_calendar, status,
((Props_pu *)e->cal->properties_pu)->xm_error_pixmap);
if (status != CSA_SUCCESS) {
free_appt_struct(&appt);
return;
}
format_appt(appt, buf, dt, DEFAULT_APPT_LEN);
str = XmStringCreateLocalized(buf);
XmListAddItem(e->appt_list, str, 0);
XmStringFree(str);
free_appt_struct(&appt);
}
extern void
add_all_appt(Editor *e) {
int i;
CSA_uint32 j;
char *date;
Tick tick;
Props *p;
Calendar *c = e->cal;
CSA_entry_handle *entry_list;
OrderingType o;
SeparatorType s;
if (!editor_showing(e))
return;
p = (Props *)e->cal->properties;
o = get_int_prop(p, CP_DATEORDERING);
s = get_int_prop(p, CP_DATESEPARATOR);
date = get_date_from_widget(e->cal->view->date, e->dssw.date_text, o, s);
if (!date || (tick = cm_getdate(date, NULL)) <= 0)
return;
build_editor_list(e, tick, dayGlance, &entry_list, &j);
XmListDeleteAllItems(e->appt_list);
XtSetSensitive(e->delete_button, False);
XtSetSensitive(e->change_button, False);
if (e->appt_head && e->appt_count >= 0)
csa_free(e->appt_head);
e->appt_head = entry_list;
e->appt_count = j;
for (i = 0; i < j; i++)
add_to_appt_list(entry_list[i], e);
if (j <= 0)
XtSetSensitive(e->appt_list, False);
else
XtSetSensitive(e->appt_list, True);
}
static void
set_list_title(Editor *e) {
Calendar *c = e->cal;
Props *p = (Props *)c->properties;
char *header;
char buffer[BUFSIZ];
char buffer2[BUFSIZ];
XmString xmstr;
switch (e->view_list_glance) {
case yearGlance:
header = catgets(c->DT_catd, 1, 704, "Year of %d");
sprintf(buffer, header, year(e->view_list_date));
break;
case monthGlance:
header = catgets(c->DT_catd, 1, 705, "%s");
format_date(e->view_list_date+1, get_int_prop(p, CP_DATEORDERING), buffer2, 0, 0, 0);
sprintf(buffer, header, buffer2);
break;
case weekGlance:
header = catgets(c->DT_catd, 1, 706, "Week of %s");
format_date(e->view_list_date+1, get_int_prop(p, CP_DATEORDERING), buffer2, 1, 0, 0);
sprintf(buffer, header, buffer2);
break;
case dayGlance:
header = catgets(c->DT_catd, 1, 707, "%s");
format_date(e->view_list_date+1, get_int_prop(p, CP_DATEORDERING), buffer2, 1, 0, 0);
sprintf(buffer, header, buffer2);
break;
}
if (e->view_frame) {
xmstr = XmStringCreateLocalized(buffer);
XtVaSetValues(e->view_list_label, XmNlabelString, xmstr,
NULL);
XmStringFree(xmstr);
}
}
extern void
build_editor_list(Editor *e, Tick date, Glance glance,
CSA_entry_handle **entry_list, CSA_uint32 *count) {
int range_count;
time_t start, stop;
CSA_return_code status;
CSA_enum *ops;
CSA_attribute *range_attr;
switch(glance) {
case yearGlance:
start = lowerbound(jan1(date));
stop = nextyear(start) - 1;
break;
case monthGlance:
start = first_dom(date);
stop = nextmonth(start) - 1;
break;
case weekGlance:
start = first_dow(date);
stop = nextweek(start) - 1;
break;
case dayGlance:
default:
start = lowerbound(date);
stop = nextday(start) - 1;
break;
}
setup_range(&range_attr, &ops, &range_count, start, stop,
CSA_TYPE_EVENT, 0, B_FALSE, e->cal->general->version);
status = csa_list_entries(e->cal->cal_handle, range_count, range_attr, ops, count, entry_list, NULL);
backend_err_msg(e->frame, e->cal->view->current_calendar, status,
((Props_pu *)e->cal->properties_pu)->xm_error_pixmap);
if (status != CSA_SUCCESS) {
*entry_list = NULL;
*count = 0;
}
free_range(&range_attr, &ops, range_count);
}
extern int
build_editor_view(Editor *e, Glance glance, Boolean redisplay) {
int cnt;
CSA_uint32 entry_count;
char *buf, *what_str, str1[MAXNAMELEN],
str2[MAXNAMELEN];
CSA_entry_handle *entry_list;
Lines *lines;
Props *p = (Props *)e->cal->properties;
XmString str;
CSA_return_code status;
OrderingType o = get_int_prop(p, CP_DATEORDERING);
SeparatorType s = get_int_prop(p, CP_DATESEPARATOR);
DisplayType dt = get_int_prop(p, CP_DEFAULTDISP);
Dtcm_appointment *appt;
Tick start_time;
/*
** First, get the list of appointments and delete all items from the
** list
*/
if (redisplay == True) {
/* On a redisplay, rebuild the list based on the
parameters of the last query. */
build_editor_list(e, e->view_list_date, e->view_list_glance, &entry_list,
&entry_count);
}
else {
/* If this is a clean display of the appointment list,
save the context so that a redisplay can be done if
something changes, like the display format or something
like that. */
build_editor_list(e, e->cal->view->date, glance, &entry_list,
&entry_count);
e->view_list_glance = glance;
e->view_list_date = e->cal->view->date;
}
set_list_title(e);
XmListDeleteAllItems(e->view_list);
/*
** Now loop through and add each appt to the list
*/
appt = allocate_appt_struct(appt_read,
e->cal->general->version,
CSA_ENTRY_ATTR_START_DATE_I,
CSA_ENTRY_ATTR_SUMMARY_I,
NULL);
for (cnt = 0; cnt < entry_count; cnt++) {
/*
** Create the text string describing the editor and set that
** value in the scrolling list
*/
status = query_appt_struct(e->cal->cal_handle, entry_list[cnt], appt);
backend_err_msg(e->frame, e->cal->view->current_calendar, status,
((Props_pu *)e->cal->properties_pu)->xm_error_pixmap);
if (status != CSA_SUCCESS) {
csa_free(entry_list);
free_appt_struct(&appt);
entry_count = cnt = 0;
continue;
}
_csa_iso8601_to_tick(appt->time->value->item.date_time_value, &start_time);
format_tick(start_time, o, s, str1);
format_time(start_time, dt, str2);
lines = text_to_lines(appt->what->value->item.string_value, 1);
if (lines && lines->s) {
buf = (char *)ckalloc(cm_strlen(str1) + cm_strlen(str2)
+ cm_strlen(lines->s) + 5);
what_str = lines->s;
} else {
buf = (char *)ckalloc(cm_strlen(str1)
+ cm_strlen(str2) + 6);
what_str = "\0";
}
sprintf(buf, "%s %s %s", str1, str2, what_str);
str = XmStringCreateLocalized(buf);
XmListAddItem(e->view_list, str, 0);
XmStringFree(str);
free(buf);
destroy_lines(lines);
}
if (entry_list && entry_count > 0)
csa_free(entry_list);
free_appt_struct(&appt);
if (entry_count <= 0)
XtSetSensitive(e->view_list, False);
else
XtSetSensitive(e->view_list, True);
return (cnt);
}
boolean_t
compare_repeat_info(
Dtcm_appointment *old_a,
RFP *rfp,
CSA_session_handle cal_handle,
int cal_version)
{
Dtcm_appointment *appt;
CSA_return_code status;
CSA_enum ops[1];
CSA_entry_handle *entries;
CSA_uint32 num_entries;
/* Find the start date of the appointment. If it matches the
* current appt then we don't care if the rules match because we
* allow changes to the rules when you start from the first
* appt.
*/
ops[0] = CSA_MATCH_EQUAL_TO;
status = csa_list_entries(cal_handle, 1, old_a->identifier, ops,
&num_entries, &entries, NULL);
if (status != CSA_SUCCESS || num_entries == 0) {
return FALSE;
}
appt = allocate_appt_struct(appt_read,
cal_version,
CSA_ENTRY_ATTR_START_DATE_I,
NULL);
status = query_appt_struct(cal_handle, entries[0], appt);
if (status != CSA_SUCCESS) {
free_appt_struct(&appt);
return FALSE;
}
csa_free(entries);
if (!strcmp(old_a->time->value->item.date_time_value,
appt->time->value->item.date_time_value)) {
free_appt_struct(&appt);
return TRUE;
}
free_appt_struct(&appt);
/* We're not at the first event so we check to see if the rule
* has changed.
*/
if (!old_a->repeat_type->value)
return FALSE;
if (old_a->repeat_type->value->item.sint32_value !=
rfp->repeat_type)
return FALSE;
if (!old_a->repeat_interval || !old_a->repeat_interval->value)
return TRUE;
if (rfp->repeat_type == CSA_X_DT_REPEAT_EVERY_NDAY ||
rfp->repeat_type == CSA_X_DT_REPEAT_EVERY_NWEEK ||
rfp->repeat_type == CSA_X_DT_REPEAT_EVERY_NMONTH)
if (old_a->repeat_interval->value->item.sint32_value !=
rfp->repeat_nth)
return FALSE;
return TRUE;
}
void
trim_end_date_from_rule(char *rule, char *newrule)
{
char *ptr;
/* this is done with the assumption that 'Z' only appears
* in the end date of the rule and that there is at most
* one end date in the rule and that the end date is
* is always at the end of the rule
*/
if (ptr = strchr(rule, 'Z')) {
while (*ptr != ' ')
ptr--;
*ptr = '\0';
}
strcpy(newrule, rule);
if (ptr)
*ptr = ' ';
}
/*
* A single event in a repeating appt is beinging changed. If the rule is
* not being changed then we need to change it to D1 #1 since the change
* is suppose to effect this appt only.
*/
void
change_rule_for_this_one_only(
Calendar *c,
Dtcm_appointment *new,
Dtcm_appointment *old)
{
char buf[BUFSIZ];
if (c->general->version < DATAVER4) {
if ((new->repeat_type->value->item.sint32_value ==
old->repeat_type->value->item.sint32_value) &&
(new->repeat_times->value->item.uint32_value ==
old->repeat_times->value->item.uint32_value)) {
new->repeat_type->value->item.sint32_value =
CSA_X_DT_REPEAT_ONETIME;
new->repeat_times->value->item.uint32_value = 0;
}
} else {
/* an end date might be added to the rule if the user
* has done a delete/change forward operation on this
* appointment before. We need to get rid of the
* end date from the rule otherwise the 2 rules
* won't match
*/
trim_end_date_from_rule(old->recurrence_rule->value->\
item.string_value, buf);
if (!strcmp(new->recurrence_rule->value->item.string_value,
buf)) {
free (new->recurrence_rule->value->item.string_value);
new->recurrence_rule->value->item.string_value =
cm_strdup("D1 #1");
}
}
}
extern Boolean
editor_change(Dtcm_appointment *new_a, CSA_entry_handle old_a, CSA_entry_handle *updated_a,
Calendar *c) {
Editor *e = (Editor *)c->editor;
Props_pu *p = (Props_pu *)c->properties_pu;
CSA_return_code stat;
CSA_enum scope;
Dtcm_appointment *appt;
static int answer;
answer = 0;
appt = allocate_appt_struct(appt_read,
c->general->version,
CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I,
CSA_X_DT_ENTRY_ATTR_REPEAT_TIMES_I,
CSA_X_DT_ENTRY_ATTR_REPEAT_INTERVAL_I,
CSA_X_DT_ENTRY_ATTR_REPEAT_OCCURRENCE_NUM_I,
CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER_I,
CSA_ENTRY_ATTR_START_DATE_I,
CSA_ENTRY_ATTR_RECURRENCE_RULE_I,
NULL);
stat = query_appt_struct(c->cal_handle, old_a, appt);
backend_err_msg(e->frame, c->view->current_calendar, stat,
p->xm_error_pixmap);
if (stat != CSA_SUCCESS) {
free_appt_struct(&appt);
return FALSE;
}
if ((appt->repeat_type->value->item.sint32_value == CSA_X_DT_REPEAT_OTHER) ||
(appt->repeat_type->value->item.sint32_value == CSA_X_DT_REPEAT_OTHER_WEEKLY) ||
(appt->repeat_type->value->item.sint32_value == CSA_X_DT_REPEAT_OTHER_MONTHLY) ||
(appt->repeat_type->value->item.sint32_value == CSA_X_DT_REPEAT_OTHER_YEARLY)) {
char *title = XtNewString(catgets(c->DT_catd, 1, 258,
"Calendar : Appointment Editor - Change"));
char *text = XtNewString(catgets(c->DT_catd, 1, 708,
"This appointment repeats in an unknown fashion. All occurrences will be changed\nDo you still wish to change it?"));
char *ident1 = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
char *ident4 = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
answer = dialog_popup(e->frame,
DIALOG_TITLE, title,
DIALOG_TEXT, text,
BUTTON_IDENT, 1, ident1,
BUTTON_IDENT, 4, ident4,
DIALOG_IMAGE, p->xm_question_pixmap,
NULL);
XtFree(ident4);
XtFree(ident1);
XtFree(text);
XtFree(title);
}
else if (appt->repeat_type->value->item.sint32_value !=
CSA_X_DT_REPEAT_ONETIME) {
char *title = XtNewString(catgets(c->DT_catd, 1, 258,
"Calendar : Appointment Editor - Change"));
char *text = XtNewString(catgets(c->DT_catd, 1, 268,
"This appointment is part of a repeating series.\nDo you want to change ...?"));
char *ident1 = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
char *ident2 = XtNewString(catgets(c->DT_catd, 1, 270,
"This One Only"));
char *ident3 = XtNewString(catgets(c->DT_catd, 1, 271, "Forward"));
char *ident4 = XtNewString(catgets(c->DT_catd, 1, 272, "All"));
answer = dialog_popup(e->frame,
DIALOG_TITLE, title,
DIALOG_TEXT, text,
BUTTON_IDENT, 1, ident1,
BUTTON_IDENT, 2, ident2,
BUTTON_IDENT, 3, ident3,
(compare_repeat_info(appt, &(e->rfp), c->cal_handle, c->general->version) ?
BUTTON_IDENT : BUTTON_INSENSITIVE),
4, ident4,
DIALOG_IMAGE, p->xm_question_pixmap,
NULL);
XtFree(ident4);
XtFree(ident3);
XtFree(ident2);
XtFree(ident1);
XtFree(text);
XtFree(title);
if (answer == 2)
change_rule_for_this_one_only(c, new_a, appt);
}
switch(answer) {
case 1:
free_appt_struct(&appt);
return False;
case 2:
scope = CSA_SCOPE_ONE;
break;
case 3:
scope = CSA_SCOPE_FORWARD;
break;
case 4:
default:
scope = CSA_SCOPE_ALL;
break;
}
/* We are not allowed to change the type of the entry, so we will
remove that particular entry from the list for writing. */
if (new_a->type) {
if (new_a->type->name){
free(new_a->type->name);
new_a->type->name = NULL;
}
}
/* if the repeat type/times is changed, reset the sequence end date */
if (c->general->version == DATAVER3 &&
appt->repeat_type->value->item.sint32_value !=
CSA_X_DT_REPEAT_ONETIME &&
(appt->repeat_type->value->item.sint32_value !=
new_a->repeat_type->value->item.sint32_value ||
appt->repeat_times->value->item.uint32_value !=
new_a->repeat_times->value->item.uint32_value))
{
if (new_a->sequence_end_date && new_a->sequence_end_date->value)
{
if (new_a->sequence_end_date->value->item.date_time_value)
free(new_a->sequence_end_date->value->\
item.date_time_value);
free(new_a->sequence_end_date->value);
new_a->sequence_end_date->value = NULL;
}
} else {
if (new_a->sequence_end_date && new_a->sequence_end_date->name)
{
free (new_a->sequence_end_date->name);
new_a->sequence_end_date->name = NULL;
}
}
free_appt_struct(&appt);
stat = csa_update_entry_attributes(c->cal_handle, old_a, scope, CSA_FALSE, new_a->count, new_a->attrs, updated_a, NULL);
backend_err_msg(e->frame, c->view->current_calendar, stat,
p->xm_error_pixmap);
if (stat != CSA_SUCCESS)
return FALSE;
set_editor_msg_defaults(e);
add_all_appt(e);
if (editor_view_showing(e))
build_editor_view(e, dayGlance, False);
if (geditor_showing((GEditor *)calendar->geditor))
add_all_gappt((GEditor *)calendar->geditor);
reset_alarm(c);
invalidate_cache(c);
paint_canvas(c, NULL, RENDER_CLEAR_FIRST);
if (c->browser)
br_display(c);
if (geditor_showing((GEditor *)c->geditor))
add_all_gappt((GEditor *)c->geditor);
return True;
}
extern void
editor_clean_up(Editor *e) {
if (e->appt_head && e->appt_count >= 0)
csa_free(e->appt_head);
e->appt_head = NULL;
e->appt_count = 0;
}
extern Boolean
editor_delete(CSA_entry_handle entry, Calendar *c) {
Editor *e = (Editor *)c->editor;
Props_pu *p = (Props_pu *)c->properties_pu;
CSA_return_code stat;
CSA_enum scope;
Dtcm_appointment *appt;
static int answer;
answer = 0;
appt = allocate_appt_struct(appt_read,
c->general->version,
CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I,
NULL);
stat = query_appt_struct(c->cal_handle, entry, appt);
backend_err_msg(e->frame, c->view->current_calendar, stat,
p->xm_error_pixmap);
if (stat != CSA_SUCCESS) {
free_appt_struct(&appt);
return False;
}
if (appt->repeat_type->value) {
if (appt->repeat_type->value->item.sint32_value != CSA_X_DT_REPEAT_ONETIME) {
char *title = XtNewString(catgets(c->DT_catd, 1, 252,
"Calendar : Appointment Editor - Delete"));
char *text = XtNewString(catgets(c->DT_catd, 1, 274,
"This appointment is part of a repeating series.\nDo you want to delete ...?"));
char *ident1 = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
char *ident2 = XtNewString(catgets(c->DT_catd, 1, 270,
"This One Only"));
char *ident3 = XtNewString(catgets(c->DT_catd, 1, 271, "Forward"));
char *ident4 = XtNewString(catgets(c->DT_catd, 1, 272, "All"));
answer = dialog_popup(e->frame,
DIALOG_TITLE, title,
DIALOG_TEXT, text,
BUTTON_IDENT, 1, ident1,
BUTTON_IDENT, 2, ident2,
BUTTON_IDENT, 3, ident3,
BUTTON_IDENT, 4, ident4,
DIALOG_IMAGE, p->xm_question_pixmap,
NULL);
XtFree(ident4);
XtFree(ident3);
XtFree(ident2);
XtFree(ident1);
XtFree(text);
XtFree(title);
}
}
else if (appt->recurrence_rule->value) {
char *title = XtNewString(catgets(c->DT_catd, 1, 252,
"Calendar : Appointment Editor - Delete"));
char *text = XtNewString(catgets(c->DT_catd, 1, 711,
"This appointment repeats in an unknown fashion. All occurrences will be deleted\nDo you still wish to delete it?"));
char *ident1 = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
char *ident4 = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
answer = dialog_popup(e->frame,
DIALOG_TITLE, title,
DIALOG_TEXT, text,
BUTTON_IDENT, 1, ident1,
BUTTON_IDENT, 4, ident4,
DIALOG_IMAGE, p->xm_question_pixmap,
NULL);
XtFree(ident4);
XtFree(ident1);
XtFree(text);
XtFree(title);
}
free_appt_struct(&appt);
switch(answer) {
case 1:
return False;
case 2:
scope = CSA_SCOPE_ONE;
break;
case 3:
scope = CSA_SCOPE_FORWARD;
break;
case 4:
default:
scope = CSA_SCOPE_ALL;
break;
}
stat = csa_delete_entry(c->cal_handle, entry, scope, NULL);
backend_err_msg(e->frame, c->view->current_calendar, stat,
p->xm_error_pixmap);
if (stat != CSA_SUCCESS)
return FALSE;
set_editor_msg_defaults(e);
add_all_appt(e);
if (editor_view_showing(e))
build_editor_view(e, dayGlance, False);
reset_alarm(c);
invalidate_cache(c);
paint_canvas(c, NULL, RENDER_CLEAR_FIRST);
if (c->browser)
br_display(c);
return True;
}
extern Boolean
editor_insert(Dtcm_appointment *appt, CSA_entry_handle *new_a, Calendar *c) {
CSA_return_code stat;
Editor *e = (Editor *)c->editor;
Props_pu *p = (Props_pu *)c->properties_pu;
CSA_enum scope;
static int answer=0;
/* the gui does not support specifying the sequence end date */
if (appt->sequence_end_date && appt->sequence_end_date->name) {
free(appt->sequence_end_date->name);
appt->sequence_end_date->name = NULL;
}
if ((appt->repeat_type) && (appt->repeat_type->value) &&
(appt->repeat_type->value->item.sint32_value != CSA_X_DT_REPEAT_ONETIME))
{
char *title = XtNewString(catgets(c->DT_catd, 1, 1101,
"Insert Appointment"));
char *text = XtNewString(catgets(c->DT_catd, 1, 984,
"This appointment is part of a repeating series.\nDo you want to insert appointment ...?"));
char *ident1 = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
char *ident4 = XtNewString(catgets(c->DT_catd, 1, 272, "All"));
answer = dialog_popup(e->frame,
DIALOG_TITLE, title,
DIALOG_TEXT, text,
BUTTON_IDENT, 1, ident1,
BUTTON_IDENT, 4, ident4,
DIALOG_IMAGE, p->xm_question_pixmap,
NULL);
XtFree(ident4);
XtFree(ident1);
XtFree(text);
XtFree(title);
}
switch(answer) {
case 1:
/*
* Free the CSA_buffer here since before, this routine
* only returned false when failure to obtain the CSA_structure
* occurred.
*/
csa_free((CSA_buffer)new_a);
return 2;
case 4:
default:
/*
* scope is not used at this time. However, to follow
* the change/delete style, this is here so in case
* later the same type of dialog is required.
*/
scope = CSA_SCOPE_ALL;
break;
}
stat = csa_add_entry(c->cal_handle, appt->count, appt->attrs, new_a, NULL);
backend_err_msg(c->frame, c->view->current_calendar, stat,
p->xm_error_pixmap);
if (stat != CSA_SUCCESS)
return FALSE;
set_editor_msg_defaults(e);
add_all_appt(e);
if (editor_view_showing(e))
build_editor_view(e, dayGlance, False);
if (geditor_showing((GEditor *)calendar->geditor))
add_all_gappt((GEditor *)calendar->geditor);
reset_alarm(c);
invalidate_cache(c);
paint_canvas(c, NULL, RENDER_CLEAR_FIRST);
if (c->browser)
br_display(c);
return True;
}
extern Boolean
editor_created(Editor *e) {
if (!e || !e->base_form_mgr)
return False;
return True;
}
/*
** Return the nth appointment from the array
*/
extern CSA_entry_handle
editor_nth_appt(Editor *e, int idx) {
if (idx >= 0 && idx < e->appt_count)
return e->appt_head[idx];
return 0;
}
extern Boolean
editor_showing(Editor *e) {
if (e)
return e->editor_is_up;
return False;
}
extern Boolean
editor_view_showing(Editor *e) {
if (e)
return e->editor_view_is_up;
return False;
}
/*
** External function to set editor defaults
*/
extern void
set_editor_defaults(Editor *e, Tick start, Tick stop, Boolean show_notime) {
if (start > 0 || stop > 0) {
load_dssw_times(&e->dssw, start, stop, show_notime);
set_dssw_defaults(&e->dssw, e->cal->view->date, False);
} else
set_dssw_defaults(&e->dssw, e->cal->view->date, True);
if (e->reminders.bfpm_form_mgr) {
set_rfp_defaults(&e->rfp);
set_reminders_defaults(&e->reminders);
}
set_message(e->message_text, " ");
e->dsswFlags = 0;
e->rfpFlags = 0;
}
extern void
set_editor_title(Editor *e, char *name) {
char buf[MAXNAMELEN];
Calendar *c = e->cal;
if (e->frame) {
sprintf(buf, "%s - %s", catgets(c->DT_catd, 1, 279,
"Calendar : Appointment Editor"), name);
XtVaSetValues(e->frame, XmNtitle, buf,
NULL);
}
}
extern void
set_editor_vals(Editor *e, Tick start, Tick stop) {
if (start > 0 || stop > 0)
load_dssw_times(&e->dssw, start, stop, False);
set_dssw_vals(&e->dssw, e->cal->view->date);
set_rfp_vals(&e->rfp);
set_reminders_vals(&e->reminders, True);
}
extern void
show_editor(Calendar *c, time_t start, time_t stop, Boolean show_notime) {
Editor *e = (Editor *)c->editor;
if (!editor_created(e))
e_make_editor(c);
else if (!XtIsManaged(e->base_form_mgr))
XtManageChild(e->base_form_mgr);
else
XRaiseWindow(XtDisplay(e->base_form_mgr),
XtWindow(XtParent(e->base_form_mgr)));
if (!editor_showing(e)) {
ds_position_popup(c->frame, e->frame, DS_POPUP_LOR);
XmProcessTraversal(e->dssw.what_text, XmTRAVERSE_CURRENT);
XtVaSetValues(e->base_form_mgr,
XmNinitialFocus, e->dssw.what_text,
NULL);
}
if (! e->editor_is_up)
{
e->editor_is_up = True;
set_editor_defaults(e, start, stop, show_notime);
}
add_all_appt(e);
if (e->frame) XtPopup(e->frame, XtGrabNone);
/* if (e->view_frame) XtPopup(e->view_frame, XtGrabNone); */
}
extern void
show_editor_view(Calendar *c, Glance glance) {
Editor *e = (Editor *)c->editor;
Props_pu *p = (Props_pu *)c->properties_pu;
if (!e->view_frame) {
e->cal = c;
e_build_view_popup(e);
}
XtVaSetValues(e->view_form, XmNdefaultButton, e->view_cancel_button, NULL);
XtVaSetValues(e->view_form, XmNcancelButton, e->view_cancel_button, NULL);
if (build_editor_view(e, glance, False) <= 0) {
char *title = XtNewString(catgets(c->DT_catd, 1, 280,
"Calendar : Error - Appointment List"));
char *text = XtNewString(catgets(c->DT_catd, 1, 281,
"Sorry, no appointments to list. "));
char *ident1 = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
dialog_popup(e->cal->frame,
DIALOG_TITLE, title,
DIALOG_TEXT, text,
BUTTON_IDENT, 1, ident1,
DIALOG_IMAGE, p->xm_error_pixmap,
NULL);
XtFree(ident1);
XtFree(text);
XtFree(title);
XtUnmanageChild(e->view_form);
e->editor_view_is_up = False;
} else {
if (!editor_view_showing(e))
ds_position_popup(c->frame, e->view_frame,
DS_POPUP_LOR);
XtManageChild(e->view_form);
e->editor_view_is_up = True;
}
/* if (e->frame) XtPopup(e->frame, XtGrabNone); */
if (e->view_frame) XtPopup(e->view_frame, XtGrabNone);
}
/*
** Function to set some editor defaults
*/
static void
set_editor_msg_defaults(Editor *e) {
set_dssw_defaults(&e->dssw, e->cal->view->date, False);
set_message(e->message_text, " ");
}