Files
cdesktop/cde/programs/dtcm/dtcm/dnd.c

1055 lines
28 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 librararies and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $TOG: dnd.c /main/12 1998/04/09 11:43:47 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 <unistd.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <memory.h>
#include <stdlib.h>
#include <rpc/rpc.h>
#include <X11/Xlib.h>
#include <Xm/Xm.h>
#include <Xm/Text.h>
#include <Xm/List.h>
#include <Xm/DragC.h>
#include <Xm/DragIcon.h>
#include <Xm/AtomMgr.h>
#include <Xm/ToggleBG.h>
#include <Dt/Dt.h>
#include <Dt/Dnd.h>
#include <csa.h>
#include "util.h"
#include "editor.h"
#include "todo.h"
#include "group_editor.h"
#include "calendar.h"
#include "props_pu.h"
#include "props.h"
#include "dnd.h"
#include "getdate.h"
#include "cm_tty.h"
#include "misc.h"
#include "help.h"
#ifdef FNS
#include "cmfns.h"
#endif
#include "drag_xbm"
#include "drag_mask_xbm"
static Bool lookForButton(Display *, XEvent *, XPointer);
#if !defined(linux) && !defined(CSRG_BASED)
extern char *sys_errlist[];
#endif
extern int drag_load_proc(char*, Calendar *);
static char dnd_filename[20];
static Boolean
validate_dropped_appt(char *filename, Calendar *c) {
Props *p = (Props *)c->properties;
Props_pu *pu = (Props_pu *)c->properties_pu;
CmDataList *list = CmDataListCreate();
Validate_op op;
int i;
Dtcm_appointment *a;
if (!filename || *filename == '\0')
return(False);
op = parse_appt_from_file(c->DT_catd, filename, list, p, query_user,
(void *)c, c->general->version);
for (i = 1; i <= list->count; i++)
if (a = (Dtcm_appointment *)CmDataListGetData(list, i))
free_appt_struct(&a);
CmDataListDestroy(list, B_FALSE);
if (op == VALID_APPT)
return(True);
else
return(False);
}
static void
handle_animate_cb(
Widget dragContext,
XtPointer client_data,
XtPointer call_data)
{
DtDndDropAnimateCallbackStruct *animateInfo = (DtDndDropAnimateCallbackStruct *)call_data;
Calendar *c;
char *data;
int size;
FILE *fp;
int i;
#if defined(FNS) && defined(FNS_DEMO)
char buf[256];
char addr_buf[256];
#endif
c = (Calendar *)client_data;
for (i = 0; i < animateInfo->dropData->numItems; i++) {
switch(animateInfo->dropData->protocol) {
case DtDND_FILENAME_TRANSFER:
data = animateInfo->dropData->data.files[i];
#if defined(FNS) && defined(FNS_DEMO)
if (cmfns_use_fns(c->properties) &&
cmfns_name_from_file(data, buf, sizeof(buf)) == 1) {
/*
* Looks like an HFS file has been dropped on us.
* Get the calendar service associated with the
* FNS name and browse it
*/
if (cmfns_lookup_calendar(buf,
addr_buf, sizeof(addr_buf)) == 1) {
switch_it(c, addr_buf, main_win);
return;
}
}
#endif
drag_load_proc(data, c);
break;
case DtDND_BUFFER_TRANSFER:
/*
* Save data to a file so we can pass it to drag_load_proc().
*/
#ifdef NOT
strcpy(filename, "/tmp/cmXXXXXX");
mktemp(filename);
#endif
if (!dnd_filename[0]){
return;
}
#ifdef NOT
if ((fp = fopen(dnd_filename, "w")) == 0) {
return;
}
data = animateInfo->dropData->data.buffers[0].bp;
size = animateInfo->dropData->data.buffers[0].size;
fwrite(data, 1, size, fp);
fclose(fp);
#endif
drag_load_proc(dnd_filename, c);
unlink(dnd_filename);
dnd_filename[0] = NULL;
break;
default:
return;
}
}
return;
}
static void
handle_drop_cb(
Widget w,
XtPointer client_data,
XtPointer call_data)
{
Display *display = XtDisplay(w);
DtDndDropCallbackStruct *transfer_info = (DtDndDropCallbackStruct *)call_data;
Calendar *c;
char filename[20];
char *data;
int size;
FILE *fp;
int i;
#if defined(FNS) && defined(FNS_DEMO)
char buf[256];
char addr_buf[256];
#endif
c = (Calendar *)client_data;
transfer_info->status = DtDND_SUCCESS;
for (i = 0; i < transfer_info->dropData->numItems; i++) {
switch(transfer_info->dropData->protocol) {
case DtDND_FILENAME_TRANSFER:
data = transfer_info->dropData->data.files[i];
#if defined(FNS) && defined(FNS_DEMO)
if (cmfns_use_fns(c->properties) &&
cmfns_name_from_file(data, buf, sizeof(buf)) == 1) {
/*
* Looks like an HFS file has been dropped on us.
* Get the calendar service associated with the
* FNS name and browse it
*/
if (cmfns_lookup_calendar(buf,
addr_buf, sizeof(addr_buf)) == 1) {
switch_it(c, addr_buf, main_win);
return;
}
}
#endif
if (validate_dropped_appt(data, c) == False) {
transfer_info->status = DtDND_FAILURE;
}
break;
case DtDND_BUFFER_TRANSFER:
/*
* Save data to a file so we can pass it to drag_load_proc().
*/
strcpy(dnd_filename, "/tmp/cmXXXXXX");
mktemp(dnd_filename);
if ((fp = fopen(dnd_filename, "w")) == 0) {
transfer_info->status = DtDND_FAILURE;
return;
}
data = transfer_info->dropData->data.buffers[0].bp;
size = transfer_info->dropData->data.buffers[0].size;
fwrite(data, 1, size, fp);
fclose(fp);
if (validate_dropped_appt(dnd_filename, c) == False) {
unlink(dnd_filename);
dnd_filename[0] = NULL;
transfer_info->status = DtDND_FAILURE;
}
#ifdef NOT
unlink(filename);
#endif
break;
default:
transfer_info->status = DtDND_FAILURE;
return;
}
}
return;
}
void
cm_register_drop_site(
Calendar *c,
Widget w)
{
XtCallbackRec transfer_cb_rec[] = { {handle_drop_cb, NULL},
{NULL, NULL} };
static XtCallbackRec animateCBRec[] = { {handle_animate_cb, NULL},
{NULL, NULL} };
Display *display = XtDisplayOfObject(w);
/*
* The above string "CalendarAppointment" is hard coded to match the type
* used in dtdnddemo. In the future we need to use the true
* type from the data typing database
*/
transfer_cb_rec[0].closure = (XtPointer)c;
animateCBRec[0].closure = (XtPointer)c;
DtDndVaDropRegister(w, DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER,
XmDROP_COPY,
transfer_cb_rec,
DtNdropAnimateCallback, animateCBRec,
DtNtextIsBuffer, True,
NULL);
return;
}
/*
* Insert the appointment into the calendar.
*
* Returns:
* 1 Success
* 0 User overuled. Appointment not inserted.
* -1 Failure
*/
static int
schedule_appt(Calendar *c, Dtcm_appointment *a) {
char date_buf[MAXNAMELEN], buf[BUFSIZ], buf2[BUFSIZ];
int answer;
Editor *e = (Editor *)c->editor;
ToDo *t = (ToDo *)c->todo;
Props *p = (Props *)c->properties;
CSA_entry_handle entry;
OrderingType ot = get_int_prop(p, CP_DATEORDERING);
SeparatorType st = get_int_prop(p, CP_DATESEPARATOR);
Tick tick;
int rc;
if (strcmp(c->calname, c->view->current_calendar) != 0) {
/*
* Make sure user really meant to insert appointment
* into somebody elses calendar.
*/
char *ident = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
char *title = XtNewString(catgets(c->DT_catd, 1, 212,
"Calendar : Schedule Appointment"));
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);
answer = dialog_popup(c->frame,
DIALOG_TITLE, title,
DIALOG_TEXT, buf,
BUTTON_IDENT, 1, ident,
BUTTON_IDENT, 2, buf2,
NULL);
XtFree(title);
XtFree(ident);
if (answer == 1)
return 0;
}
if (a->end_time) {
if (!editor_created(e))
{
e_make_editor(c);
XtUnmanageChild(e->base_form_mgr);
e->editor_is_up = False;
}
if ((rc = editor_insert(a, &entry, c)) == True) {
_csa_iso8601_to_tick(a->time->value->item.string_value, &tick);
format_tick(tick, ot, st, date_buf);
sprintf(buf, catgets(c->DT_catd, 1, 214,
"Appointment scheduled: %s"), date_buf);
set_message(c->message_text, buf);
return 1;
} else {
set_message(c->message_text, "");
if ( rc == 2)
return 0;
return -1;
}
} else {
if (!t->frame)
{
t_make_todo(c);
XtUnmanageChild(t->frame);
t->todo_is_up = False;
}
if (todo_insert(a, &entry, c)) {
/*
* No messages displayed on calendar for todo.
*/
return 1;
} else {
/*
* No messages displayed on calendar for todo.
*/
return -1;
}
}
}
/*
* Call the routines in file_parse (in libDtCm) to read the appointments!
*/
extern int
drag_load_proc(char *filename, Calendar *c) {
int ret_val, i = 1;
char buf[MAXNAMELEN * 2];
CmDataList *list = CmDataListCreate();
Props *p = (Props *)c->properties;
Props_pu *pu = (Props_pu *)c->properties_pu;
Validate_op op;
Dtcm_appointment *a;
char *msg;
if (!filename || *filename == '\0')
return -1;
op = parse_appt_from_file(c->DT_catd, filename, list, p, query_user,
(void *)c, c->general->version);
if (list->count <= 0) {
op = CANCEL_APPT;
sprintf(buf, "%s", catgets(c->DT_catd, 1, 842,
"The information transferred did not\ncontain any appointments."));
}
switch(op) {
case COULD_NOT_OPEN_FILE:
msg = XtNewString(catgets(c->DT_catd, 1, 843,
"Drag and Drop operation failed."));
sprintf(buf, "%s\n%s",
msg,
catgets(c->DT_catd, 1, 844,
"Unable to locate the transferred information."));
XtFree(msg);
break;
case INVALID_DATE:
sprintf(buf, "%s",
catgets(c->DT_catd, 1, 218, "Invalid DATE specified"));
break;
case INVALID_START:
sprintf(buf, "%s", catgets(c->DT_catd, 1, 219,
"Invalid START time specified"));
break;
case INVALID_STOP:
sprintf(buf, "%s", catgets(c->DT_catd, 1, 220,
"Invalid END time specified"));
break;
case MISSING_DATE:
sprintf(buf, "%s", catgets(c->DT_catd, 1, 221,
"Empty or missing DATE field"));
break;
case MISSING_START:
sprintf(buf, "%s", catgets(c->DT_catd, 1, 222,
"Empty or missing START field"));
break;
case MISSING_WHAT:
sprintf(buf, "%s", catgets(c->DT_catd, 1, 223,
"Empty or missing WHAT field"));
break;
case REPEAT_FOR_MISMATCH:
sprintf(buf, "%s", catgets(c->DT_catd, 1, 224,
"REPEAT and FOR field mismatch"));
break;
case VALID_APPT:
break;
case CANCEL_APPT:
sprintf(buf, "%s", catgets(c->DT_catd, 1, 225,
"Schedule appointment was cancelled."));
break;
default:
op = CANCEL_APPT;
sprintf(buf, "%s", catgets(c->DT_catd, 1, 225,
"Schedule appointment was cancelled."));
break;
}
while (op == VALID_APPT && i <= list->count) {
extern void scrub_attr_list(Dtcm_appointment *);
a = (Dtcm_appointment *)CmDataListGetData(list, i);
scrub_attr_list(a);
ret_val = schedule_appt(c, a);
if (ret_val < 0) {
op = CANCEL_APPT;
sprintf(buf, "%s", catgets(c->DT_catd, 1, 226,
"Internal error scheduling appointment."));
} else if (ret_val == 0) {
op = CANCEL_APPT;
sprintf(buf, "%s", catgets(c->DT_catd, 1, 225,
"Schedule appointment was cancelled."));
}
++i;
}
for (i = 1; i <= list->count; i++)
if (a = (Dtcm_appointment *)CmDataListGetData(list, i))
free_appt_struct(&a);
CmDataListDestroy(list, B_FALSE);
if (op != VALID_APPT) {
char *title = XtNewString(catgets(c->DT_catd, 1, 1073,
"Calendar : Error - Drag and Drop"));
char *ident = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
dialog_popup(c->frame,
DIALOG_TITLE, title,
DIALOG_TEXT, buf,
BUTTON_IDENT, 1, ident,
BUTTON_HELP, DND_ERROR_HELP,
DIALOG_IMAGE, pu->xm_error_pixmap,
NULL);
XtFree(ident);
XtFree(title);
return -1;
}
return 0;
}
/* gets a pointer to the currently selected appointment in the editor.
This will need to be changed if we ever allow more than one item
to be selected in the editor at a time. */
CSA_entry_handle
get_appt_struct(DragContext *context) {
int *item_list = NULL, item_cnt = 0, answer;
char buf[MAXNAMELEN];
Widget list;
Calendar *c = context->calendar;
Props_pu *pr;
CSA_entry_handle entry;
Access_data *ad;
pr = (Props_pu *)(c->properties_pu);
if (context->editor_type == SingleEditorList)
list = ((Editor *) context->editor)->appt_list;
else if (context->editor_type == GroupEditorList)
list = ((GEditor *) context->editor)->appt_list;
else if (context->editor_type == TodoEditorList)
list = ((ToDo *) context->editor)->todo_list;
if (!XmListGetSelectedPos(list, &item_list, &item_cnt)) {
char *title = XtNewString(catgets(c->DT_catd, 1, 230,
"Calendar : Error - Drag Appointment"));
char *text = XtNewString(catgets(c->DT_catd, 1, 231, "Select an appointment and DRAG again."));
char *ident = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
answer = dialog_popup(c->frame,
DIALOG_TITLE, title,
DIALOG_TEXT, text,
BUTTON_IDENT, 1, ident,
BUTTON_HELP, RESELECT_ERROR_HELP,
DIALOG_IMAGE, pr->xm_error_pixmap,
NULL);
XtFree(ident);
XtFree(text);
XtFree(title);
return(NULL);
}
if (context->editor_type == SingleEditorList)
entry = editor_nth_appt((Editor *)context->editor,
item_list[0] - 1);
else if (context->editor_type == GroupEditorList)
entry = geditor_nth_appt((GEditor *)context->editor,
item_list[0] - 1, &ad);
else if (context->editor_type == TodoEditorList)
entry = t_nth_appt((ToDo *)context->editor,
item_list[0] - 1);
if (!entry) {
char *title = XtNewString(catgets(c->DT_catd, 1, 230,
"Calendar : Error - Drag Appointment"));
char *ident = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
sprintf(buf, "%s", catgets(c->DT_catd, 1, 845,
"Drag and Drop operation Failed\nInternal consistency error."));
answer = dialog_popup(c->frame,
DIALOG_TITLE, title,
DIALOG_TEXT, buf,
BUTTON_IDENT, 1, ident,
DIALOG_IMAGE, pr->xm_error_pixmap,
NULL);
XtFree(ident);
XtFree(title);
XtFree((XtPointer)item_list);
return(NULL);
}
return entry;
}
/*
* ApptConvertCB
*
* Fills in data object with calendar appointment string based on which
* appointment in the list was under the pointer when the drag started.
*/
static void
ApptConvertCB(
Widget dragContext,
XtPointer clientData,
XtPointer callData)
{
DtDndConvertCallbackStruct *convertInfo
= (DtDndConvertCallbackStruct*)callData;
DtDndBuffer *data = &(convertInfo->dragData->data.buffers[0]);
DragContext *context = (DragContext *)clientData;
Display *display = XtDisplay(dragContext);
Atom CMAPPOINTMENT
= XmInternAtom(display, "CalendarAppointment", False);
Calendar *c = context->calendar;
if (convertInfo->reason != DtCR_DND_CONVERT_DATA)
return;
/* REMIND: Need to check convertInfo->reason, handle DELETE, etc */
data->bp = XtNewString(context->data);
data->size = strlen(data->bp);
data->name = XtNewString(catgets(c->DT_catd, 1, 236, "CalendarAppointment"));
}
/*
* getIcon
*
* Returns a new IconInfo structure with bitmap, mask, width, height,
* icon type and name.
*/
static void
GetIcon(Calendar *calendar)
{
Display *display = XtDisplay(calendar->frame);
Window window = XtWindow(calendar->frame);
unsigned char *bitmapData, *bitmapMask;
Editor *e = (Editor *) calendar->editor;
GEditor *ge = (GEditor *) calendar->geditor;
if (e->drag_bitmap == NULL) {
e->drag_bitmap = XCreateBitmapFromData(display,
window, (char *) drag_xbm_bits,
drag_xbm_width, drag_xbm_height);
if (e->drag_bitmap == NULL) {
printf("%s", catgets(calendar->DT_catd, 1, 237, "XCreateBitmapFromData() failed for bitmap.\n"));
return;
}
else
ge->drag_bitmap = e->drag_bitmap;
}
if (e->drag_mask == NULL) {
e->drag_mask = XCreateBitmapFromData(display,
window, (char *) drag_mask_xbm_bits,
drag_mask_xbm_width, drag_mask_xbm_height);
if (e->drag_mask == NULL) {
printf("%s", catgets(calendar->DT_catd, 1, 238, "XCreateBitmapFromData() failed for mask.\n"));
return;
}
else
ge->drag_mask = e->drag_mask;
}
}
/*
* DragFinishCB
*
* Resets drag state to indicate the drag is over. Free memory allocated
* with the drag.
*/
static void
DragFinishCB(
Widget widget,
XtPointer clientData,
XtPointer callData)
{
DragContext *context = (DragContext *) clientData;
if (!context)
return;
if ((context->editor_type == SingleEditorList) ||
(context->editor_type == SingleEditorIcon))
((Editor *) context->editor)->doing_drag = False;
else if ((context->editor_type == TodoEditorList) ||
(context->editor_type == TodoEditorIcon))
((ToDo *) context->editor)->doing_drag = False;
else if ((context->editor_type == GroupEditorList) ||
(context->editor_type == GroupEditorIcon))
((GEditor *) context->editor)->doing_drag = False;
if (context->data)
free(context->data);
free(context);
}
Widget
CreateDragSourceIcon(
Widget widget,
Pixmap pixmap,
Pixmap mask)
{
Widget dragIcon;
Window rootWindow;
int pixmapX, pixmapY;
unsigned int pixmapWidth, pixmapHeight, pixmapBorder, pixmapDepth;
Arg args[20];
Cardinal nn = 0;
XGetGeometry (XtDisplayOfObject(widget), pixmap, &rootWindow,
&pixmapX, &pixmapY, &pixmapWidth, &pixmapHeight,
&pixmapBorder, &pixmapDepth);
XtSetArg(args[nn], XmNwidth, pixmapWidth); nn++;
XtSetArg(args[nn], XmNheight, pixmapHeight); nn++;
XtSetArg(args[nn], XmNmaxWidth, pixmapWidth); nn++;
XtSetArg(args[nn], XmNmaxHeight, pixmapHeight); nn++;
XtSetArg(args[nn], XmNpixmap, pixmap); nn++;
XtSetArg(args[nn], XmNmask, mask); nn++;
XtSetArg(args[nn], XmNdepth, pixmapDepth); nn++;
dragIcon = XmCreateDragIcon(widget, "sourceIcon", args, nn);
return(dragIcon);
}
void
TranslationDragStart(
Widget widget,
XEvent *event,
String *parms,
Cardinal *num_params)
{
static XtCallbackRec convertCBRec[] = { {ApptConvertCB, NULL},
{NULL, NULL} };
static XtCallbackRec dragFinishCBRec[] = { {DragFinishCB, NULL},
{NULL, NULL} };
Display *display = XtDisplay(widget);
DragContext *context = calloc(sizeof(DragContext), 1);
Editor *e = (Editor *) calendar->editor;
CSA_entry_handle entry;
char *apptstr;
Props *p = (Props *)calendar->properties;
context->calendar = calendar;
if (((Editor *)calendar->editor)->appt_list == widget) {
context->editor_type = SingleEditorList;
context->editor = (caddr_t) calendar->editor;
} else if (((GEditor *)calendar->geditor)->appt_list == widget) {
context->editor_type = GroupEditorList;
context->editor = (caddr_t) calendar->geditor;
} else if (((ToDo *)calendar->todo)->todo_list == widget) {
context->editor_type = TodoEditorList;
context->editor = (caddr_t) calendar->todo;
}
else
{
free(context);
return;
}
if (((entry = get_appt_struct(context)) == (CSA_entry_handle)NULL) ||
((apptstr = parse_appt_to_string(calendar->cal_handle,
entry, p,
calendar->general->version))
== (char *)NULL))
{
switch (context->editor_type)
{
case SingleEditorList:
((Editor *)context->editor)->doing_drag = False;
break;
case GroupEditorList:
((GEditor *)context->editor)->doing_drag = False;
break;
case TodoEditorList:
((ToDo *)context->editor)->doing_drag = False;
break;
}
free(context);
return;
}
context->data = apptstr;
GetIcon(calendar);
convertCBRec[0].closure = (XtPointer)context;
dragFinishCBRec[0].closure = (XtPointer)context;
if (e->drag_icon == NULL) {
e->drag_icon = CreateDragSourceIcon(widget,
e->drag_bitmap,
e->drag_mask);
}
if (DtDndVaDragStart(widget, event, DtDND_BUFFER_TRANSFER, 1,
XmDROP_COPY,
convertCBRec, dragFinishCBRec,
DtNsourceIcon, e->drag_icon,
NULL) == NULL) {
printf("%s", catgets(calendar->DT_catd, 1, 239,
"DragStart returned NULL.\n"));
}
}
void
ApptDragStart(
Widget widget,
XEvent *event,
Calendar *calendar,
EditorType editor_type)
{
static XtCallbackRec convertCBRec[] = { {ApptConvertCB, NULL},
{NULL, NULL} };
static XtCallbackRec dragFinishCBRec[] = { {DragFinishCB, NULL},
{NULL, NULL} };
Display *display = XtDisplay(widget);
DragContext *context = calloc(sizeof(DragContext), 1);
Editor *e = (Editor *) calendar->editor;
GEditor *ge = (GEditor *) calendar->geditor;
ToDo *t = (ToDo *) calendar->todo;
Dtcm_appointment *appt;
char *apptstr;
int preDsswFlags, preRfpFlags;
context->calendar = calendar;
context->editor_type = editor_type;
if (editor_type == SingleEditorIcon)
{
context->editor = (caddr_t) e;
appt = allocate_appt_struct(appt_write, DATAVER_ARCHIVE, NULL);
load_appt_defaults(appt, (Props *) calendar->properties);
preDsswFlags = e->dsswFlags;
preRfpFlags = e->rfpFlags;
if (!dssw_form_flags_to_appt(&e->dssw, appt,
calendar->calname,
now(), &e->dsswFlags) ||
!rfp_form_flags_to_appt(&e->rfp, appt,
calendar->calname,
&e->rfpFlags) ||
(preDsswFlags != e->dsswFlags) ||
(preRfpFlags != e->rfpFlags))
{
e->doing_drag = False;
free_appt_struct(&appt);
free(context);
return;
}
}
else if (editor_type == GroupEditorIcon)
{
context->editor = (caddr_t) ge;
appt = allocate_appt_struct(appt_write, DATAVER_ARCHIVE, NULL);
load_appt_defaults(appt, (Props *) calendar->properties);
preDsswFlags = ge->dsswFlags;
preRfpFlags = ge->rfpFlags;
if (!dssw_form_flags_to_appt(&ge->dssw, appt,
calendar->calname,
now(), &ge->dsswFlags) ||
!rfp_form_flags_to_appt(&ge->rfp, appt,
calendar->calname,
&ge->rfpFlags) ||
(preDsswFlags != ge->dsswFlags) ||
(preRfpFlags != ge->rfpFlags))
{
ge->doing_drag = False;
free_appt_struct(&appt);
free(context);
return;
}
}
else if (editor_type == TodoEditorIcon)
{
context->editor = (caddr_t) t;
if (t->cal->general->version < DATAVER4)
appt = allocate_appt_struct(appt_write, DATAVER_ARCHIVE,
CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER_I,
CSA_ENTRY_ATTR_LAST_UPDATE_I,
CSA_ENTRY_ATTR_ORGANIZER_I,
CSA_ENTRY_ATTR_START_DATE_I,
CSA_ENTRY_ATTR_TYPE_I,
CSA_ENTRY_ATTR_CLASSIFICATION_I,
CSA_ENTRY_ATTR_END_DATE_I,
CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,
CSA_ENTRY_ATTR_SUMMARY_I,
CSA_ENTRY_ATTR_STATUS_I,
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_AUDIO_REMINDER_I,
CSA_ENTRY_ATTR_FLASHING_REMINDER_I,
CSA_ENTRY_ATTR_MAIL_REMINDER_I,
CSA_ENTRY_ATTR_POPUP_REMINDER_I,
NULL);
else
appt = allocate_appt_struct(appt_write,
DATAVER_ARCHIVE, NULL);
dssw_form_to_todo(&t->dssw, appt, calendar->calname, now());
preRfpFlags = t->rfpFlags;
if (!rfp_form_flags_to_appt(&t->rfp, appt,
calendar->calname,
&t->rfpFlags) ||
(preRfpFlags != t->rfpFlags))
{
t->doing_drag = False;
free_appt_struct(&appt);
free(context);
return;
}
appt->type->value->item.sint32_value = CSA_TYPE_TODO;
appt->show_time->value->item.sint32_value = True;
t->completed_val =
XmToggleButtonGadgetGetState(t->completed_toggle);
appt->state->value->item.sint32_value =
(t->completed_val) ?
CSA_STATUS_COMPLETED : CSA_X_DT_STATUS_ACTIVE;
}
else
{
free(context);
return;
}
apptstr = parse_attrs_to_string(appt, (Props *)calendar->properties,
attrs_to_string(appt->attrs,
appt->count));
free_appt_struct(&appt);
context->data = apptstr;
GetIcon(calendar);
convertCBRec[0].closure = (XtPointer)context;
dragFinishCBRec[0].closure = (XtPointer)context;
if (e->drag_icon == NULL) {
e->drag_icon = CreateDragSourceIcon(widget, e->drag_bitmap,
e->drag_mask);
}
if (DtDndVaDragStart(widget, event, DtDND_BUFFER_TRANSFER, 1,
XmDROP_COPY,
convertCBRec, dragFinishCBRec,
DtNsourceIcon, e->drag_icon,
NULL)
== NULL) {
printf("%s", catgets(calendar->DT_catd, 1, 239,
"DragStart returned NULL.\n"));
}
}
#define DAMPING 5
#define ABS_DELTA(x1, x2) (x1 < x2 ? x2 - x1 : x1 - x2)
static Bool
lookForButton(
Display * display,
XEvent * event,
XPointer arg)
{
if (event->type == MotionNotify)
{
XEvent *press = (XEvent *)arg;
if ((ABS_DELTA(press->xbutton.x_root,
event->xmotion.x_root) > DAMPING) ||
(ABS_DELTA(press->xbutton.y_root,
event->xmotion.y_root) > DAMPING))
return(True);
}
else if (event->type == ButtonRelease)
return(True);
return(False);
}
/*
*
// DtcmProcessPress
//
// Translation implementing Motif 1.2.5 ProcessPress function
//
* Taken from dtmail/dtmail/RoamMenuWindow.C
*/
#define SELECTION_ACTION 0
#define TRANSFER_ACTION 1
void
DtcmProcessPress(
Widget w,
XEvent *event,
String *params,
Cardinal *num_params)
{
int i, action, cur_item;
int *selected_positions, nselected_positions;
/*
* This action happens when Button1 is pressed and the Selection
* and Transfer are integrated on Button1. It is passed two
* parameters: the action to call when the event is a selection,
* and the action to call when the event is a transfer.
*/
if (*num_params != 2 || !XmIsList(w))
return;
action = SELECTION_ACTION;
cur_item = XmListYToPos(w, event->xbutton.y);
if (cur_item > 0)
{
XtVaGetValues(w,
XmNselectedPositions, &selected_positions,
XmNselectedPositionCount, &nselected_positions,
NULL);
for (i=0; i<nselected_positions; i++)
{
if (cur_item == selected_positions[i])
{
/*
* The determination of whether this is a transfer drag
* cannot be made until a Motion event comes in. It is
* not a drag as soon as a ButtonUp event happens.
*/
XEvent new_event;
XPeekIfEvent(
XtDisplay(w),
&new_event,
lookForButton,
(XPointer)event);
switch (new_event.type)
{
case MotionNotify:
action = TRANSFER_ACTION;
break;
case ButtonRelease:
action = SELECTION_ACTION;
break;
}
break;
}
}
}
XtCallActionProc(w, params[action], event, params, *num_params);
}