2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $TOG: dnd.c /main/12 1998/04/09 11:43:47 mgreess $ */
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.
31 #include <EUSCompat.h>
46 #include <Xm/DragIcon.h>
47 #include <Xm/AtomMgr.h>
48 #include <Xm/ToggleBG.h>
56 #include "group_editor.h"
71 #include "drag_mask_xbm"
73 static Bool lookForButton(Display *, XEvent *, XPointer);
75 #if !defined(linux) && !defined(CSRG_BASED)
76 extern char *sys_errlist[];
79 extern int drag_load_proc(char*, Calendar *);
80 static char dnd_filename[20];
83 validate_dropped_appt(char *filename, Calendar *c) {
84 Props *p = (Props *)c->properties;
85 Props_pu *pu = (Props_pu *)c->properties_pu;
86 CmDataList *list = CmDataListCreate();
91 if (!filename || *filename == '\0')
94 op = parse_appt_from_file(c->DT_catd, filename, list, p, query_user,
95 (void *)c, c->general->version);
97 for (i = 1; i <= list->count; i++)
98 if (a = (Dtcm_appointment *)CmDataListGetData(list, i))
100 CmDataListDestroy(list, B_FALSE);
102 if (op == VALID_APPT)
112 XtPointer client_data,
115 DtDndDropAnimateCallbackStruct *animateInfo = (DtDndDropAnimateCallbackStruct *)call_data;
121 #if defined(FNS) && defined(FNS_DEMO)
126 c = (Calendar *)client_data;
128 for (i = 0; i < animateInfo->dropData->numItems; i++) {
129 switch(animateInfo->dropData->protocol) {
130 case DtDND_FILENAME_TRANSFER:
131 data = animateInfo->dropData->data.files[i];
133 #if defined(FNS) && defined(FNS_DEMO)
134 if (cmfns_use_fns(c->properties) &&
135 cmfns_name_from_file(data, buf, sizeof(buf)) == 1) {
137 * Looks like an HFS file has been dropped on us.
138 * Get the calendar service associated with the
139 * FNS name and browse it
141 if (cmfns_lookup_calendar(buf,
142 addr_buf, sizeof(addr_buf)) == 1) {
144 switch_it(c, addr_buf, main_win);
149 drag_load_proc(data, c);
151 case DtDND_BUFFER_TRANSFER:
154 * Save data to a file so we can pass it to drag_load_proc().
158 strcpy(filename, "/tmp/cmXXXXXX");
162 if (!dnd_filename[0]){
168 if ((fp = fopen(dnd_filename, "w")) == 0) {
172 data = animateInfo->dropData->data.buffers[0].bp;
173 size = animateInfo->dropData->data.buffers[0].size;
174 fwrite(data, 1, size, fp);
178 drag_load_proc(dnd_filename, c);
180 unlink(dnd_filename);
181 dnd_filename[0] = NULL;
194 XtPointer client_data,
197 Display *display = XtDisplay(w);
198 DtDndDropCallbackStruct *transfer_info = (DtDndDropCallbackStruct *)call_data;
205 #if defined(FNS) && defined(FNS_DEMO)
210 c = (Calendar *)client_data;
212 transfer_info->status = DtDND_SUCCESS;
214 for (i = 0; i < transfer_info->dropData->numItems; i++) {
215 switch(transfer_info->dropData->protocol) {
216 case DtDND_FILENAME_TRANSFER:
217 data = transfer_info->dropData->data.files[i];
219 #if defined(FNS) && defined(FNS_DEMO)
220 if (cmfns_use_fns(c->properties) &&
221 cmfns_name_from_file(data, buf, sizeof(buf)) == 1) {
223 * Looks like an HFS file has been dropped on us.
224 * Get the calendar service associated with the
225 * FNS name and browse it
227 if (cmfns_lookup_calendar(buf,
228 addr_buf, sizeof(addr_buf)) == 1) {
230 switch_it(c, addr_buf, main_win);
236 if (validate_dropped_appt(data, c) == False) {
237 transfer_info->status = DtDND_FAILURE;
240 case DtDND_BUFFER_TRANSFER:
243 * Save data to a file so we can pass it to drag_load_proc().
245 strcpy(dnd_filename, "/tmp/cmXXXXXX");
246 mktemp(dnd_filename);
248 if ((fp = fopen(dnd_filename, "w")) == 0) {
249 transfer_info->status = DtDND_FAILURE;
253 data = transfer_info->dropData->data.buffers[0].bp;
254 size = transfer_info->dropData->data.buffers[0].size;
255 fwrite(data, 1, size, fp);
258 if (validate_dropped_appt(dnd_filename, c) == False) {
259 unlink(dnd_filename);
260 dnd_filename[0] = NULL;
261 transfer_info->status = DtDND_FAILURE;
268 transfer_info->status = DtDND_FAILURE;
277 cm_register_drop_site(
282 XtCallbackRec transfer_cb_rec[] = { {handle_drop_cb, NULL},
284 static XtCallbackRec animateCBRec[] = { {handle_animate_cb, NULL},
286 Display *display = XtDisplayOfObject(w);
289 * The above string "CalendarAppointment" is hard coded to match the type
290 * used in dtdnddemo. In the future we need to use the true
291 * type from the data typing database
294 transfer_cb_rec[0].closure = (XtPointer)c;
295 animateCBRec[0].closure = (XtPointer)c;
297 DtDndVaDropRegister(w, DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER,
300 DtNdropAnimateCallback, animateCBRec,
301 DtNtextIsBuffer, True,
307 * Insert the appointment into the calendar.
311 * 0 User overuled. Appointment not inserted.
315 schedule_appt(Calendar *c, Dtcm_appointment *a) {
316 char date_buf[MAXNAMELEN], buf[BUFSIZ], buf2[BUFSIZ];
318 Editor *e = (Editor *)c->editor;
319 ToDo *t = (ToDo *)c->todo;
320 Props *p = (Props *)c->properties;
321 CSA_entry_handle entry;
322 OrderingType ot = get_int_prop(p, CP_DATEORDERING);
323 SeparatorType st = get_int_prop(p, CP_DATESEPARATOR);
327 if (strcmp(c->calname, c->view->current_calendar) != 0) {
329 * Make sure user really meant to insert appointment
330 * into somebody elses calendar.
332 char *ident = XtNewString(catgets(c->DT_catd, 1, 923, "Cancel"));
333 char *title = XtNewString(catgets(c->DT_catd, 1, 212,
334 "Calendar : Schedule Appointment"));
335 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?"));
336 sprintf(buf2, "%s %s", catgets(c->DT_catd, 1, 211, "Schedule in"),
337 c->view->current_calendar);
338 answer = dialog_popup(c->frame,
341 BUTTON_IDENT, 1, ident,
342 BUTTON_IDENT, 2, buf2,
351 if (!editor_created(e))
354 XtUnmanageChild(e->base_form_mgr);
355 e->editor_is_up = False;
357 if ((rc = editor_insert(a, &entry, c)) == True) {
359 _csa_iso8601_to_tick(a->time->value->item.string_value, &tick);
360 format_tick(tick, ot, st, date_buf);
361 sprintf(buf, catgets(c->DT_catd, 1, 214,
362 "Appointment scheduled: %s"), date_buf);
363 set_message(c->message_text, buf);
366 set_message(c->message_text, "");
375 XtUnmanageChild(t->frame);
376 t->todo_is_up = False;
378 if (todo_insert(a, &entry, c)) {
380 * No messages displayed on calendar for todo.
385 * No messages displayed on calendar for todo.
393 * Call the routines in file_parse (in libDtCm) to read the appointments!
396 drag_load_proc(char *filename, Calendar *c) {
398 char buf[MAXNAMELEN * 2];
399 CmDataList *list = CmDataListCreate();
400 Props *p = (Props *)c->properties;
401 Props_pu *pu = (Props_pu *)c->properties_pu;
406 if (!filename || *filename == '\0')
409 op = parse_appt_from_file(c->DT_catd, filename, list, p, query_user,
410 (void *)c, c->general->version);
411 if (list->count <= 0) {
413 sprintf(buf, "%s", catgets(c->DT_catd, 1, 842,
414 "The information transferred did not\ncontain any appointments."));
418 case COULD_NOT_OPEN_FILE:
419 msg = XtNewString(catgets(c->DT_catd, 1, 843,
420 "Drag and Drop operation failed."));
421 sprintf(buf, "%s\n%s",
423 catgets(c->DT_catd, 1, 844,
424 "Unable to locate the transferred information."));
429 catgets(c->DT_catd, 1, 218, "Invalid DATE specified"));
432 sprintf(buf, "%s", catgets(c->DT_catd, 1, 219,
433 "Invalid START time specified"));
436 sprintf(buf, "%s", catgets(c->DT_catd, 1, 220,
437 "Invalid END time specified"));
440 sprintf(buf, "%s", catgets(c->DT_catd, 1, 221,
441 "Empty or missing DATE field"));
444 sprintf(buf, "%s", catgets(c->DT_catd, 1, 222,
445 "Empty or missing START field"));
448 sprintf(buf, "%s", catgets(c->DT_catd, 1, 223,
449 "Empty or missing WHAT field"));
451 case REPEAT_FOR_MISMATCH:
452 sprintf(buf, "%s", catgets(c->DT_catd, 1, 224,
453 "REPEAT and FOR field mismatch"));
458 sprintf(buf, "%s", catgets(c->DT_catd, 1, 225,
459 "Schedule appointment was cancelled."));
463 sprintf(buf, "%s", catgets(c->DT_catd, 1, 225,
464 "Schedule appointment was cancelled."));
468 while (op == VALID_APPT && i <= list->count) {
469 extern void scrub_attr_list(Dtcm_appointment *);
471 a = (Dtcm_appointment *)CmDataListGetData(list, i);
475 ret_val = schedule_appt(c, a);
478 sprintf(buf, "%s", catgets(c->DT_catd, 1, 226,
479 "Internal error scheduling appointment."));
480 } else if (ret_val == 0) {
482 sprintf(buf, "%s", catgets(c->DT_catd, 1, 225,
483 "Schedule appointment was cancelled."));
488 for (i = 1; i <= list->count; i++)
489 if (a = (Dtcm_appointment *)CmDataListGetData(list, i))
490 free_appt_struct(&a);
491 CmDataListDestroy(list, B_FALSE);
493 if (op != VALID_APPT) {
494 char *title = XtNewString(catgets(c->DT_catd, 1, 1073,
495 "Calendar : Error - Drag and Drop"));
496 char *ident = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
497 dialog_popup(c->frame,
500 BUTTON_IDENT, 1, ident,
501 BUTTON_HELP, DND_ERROR_HELP,
502 DIALOG_IMAGE, pu->xm_error_pixmap,
512 /* gets a pointer to the currently selected appointment in the editor.
513 This will need to be changed if we ever allow more than one item
514 to be selected in the editor at a time. */
517 get_appt_struct(DragContext *context) {
518 int *item_list = NULL, item_cnt = 0, answer;
519 char buf[MAXNAMELEN];
521 Calendar *c = context->calendar;
523 CSA_entry_handle entry;
526 pr = (Props_pu *)(c->properties_pu);
528 if (context->editor_type == SingleEditorList)
529 list = ((Editor *) context->editor)->appt_list;
530 else if (context->editor_type == GroupEditorList)
531 list = ((GEditor *) context->editor)->appt_list;
532 else if (context->editor_type == TodoEditorList)
533 list = ((ToDo *) context->editor)->todo_list;
535 if (!XmListGetSelectedPos(list, &item_list, &item_cnt)) {
536 char *title = XtNewString(catgets(c->DT_catd, 1, 230,
537 "Calendar : Error - Drag Appointment"));
538 char *text = XtNewString(catgets(c->DT_catd, 1, 231, "Select an appointment and DRAG again."));
539 char *ident = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
540 answer = dialog_popup(c->frame,
543 BUTTON_IDENT, 1, ident,
544 BUTTON_HELP, RESELECT_ERROR_HELP,
545 DIALOG_IMAGE, pr->xm_error_pixmap,
554 if (context->editor_type == SingleEditorList)
555 entry = editor_nth_appt((Editor *)context->editor,
557 else if (context->editor_type == GroupEditorList)
558 entry = geditor_nth_appt((GEditor *)context->editor,
559 item_list[0] - 1, &ad);
560 else if (context->editor_type == TodoEditorList)
561 entry = t_nth_appt((ToDo *)context->editor,
566 char *title = XtNewString(catgets(c->DT_catd, 1, 230,
567 "Calendar : Error - Drag Appointment"));
568 char *ident = XtNewString(catgets(c->DT_catd, 1, 95, "Continue"));
569 sprintf(buf, "%s", catgets(c->DT_catd, 1, 845,
570 "Drag and Drop operation Failed\nInternal consistency error."));
571 answer = dialog_popup(c->frame,
574 BUTTON_IDENT, 1, ident,
575 DIALOG_IMAGE, pr->xm_error_pixmap,
579 XtFree((XtPointer)item_list);
589 * Fills in data object with calendar appointment string based on which
590 * appointment in the list was under the pointer when the drag started.
595 XtPointer clientData,
598 DtDndConvertCallbackStruct *convertInfo
599 = (DtDndConvertCallbackStruct*)callData;
600 DtDndBuffer *data = &(convertInfo->dragData->data.buffers[0]);
601 DragContext *context = (DragContext *)clientData;
602 Display *display = XtDisplay(dragContext);
604 = XmInternAtom(display, "CalendarAppointment", False);
605 Calendar *c = context->calendar;
607 if (convertInfo->reason != DtCR_DND_CONVERT_DATA)
610 /* REMIND: Need to check convertInfo->reason, handle DELETE, etc */
612 data->bp = XtNewString(context->data);
613 data->size = strlen(data->bp);
614 data->name = XtNewString(catgets(c->DT_catd, 1, 236, "CalendarAppointment"));
620 * Returns a new IconInfo structure with bitmap, mask, width, height,
621 * icon type and name.
624 GetIcon(Calendar *calendar)
627 Display *display = XtDisplay(calendar->frame);
628 Window window = XtWindow(calendar->frame);
629 unsigned char *bitmapData, *bitmapMask;
630 Editor *e = (Editor *) calendar->editor;
631 GEditor *ge = (GEditor *) calendar->geditor;
633 if (e->drag_bitmap == NULL) {
634 e->drag_bitmap = XCreateBitmapFromData(display,
635 window, (char *) drag_xbm_bits,
636 drag_xbm_width, drag_xbm_height);
637 if (e->drag_bitmap == NULL) {
639 printf("%s", catgets(calendar->DT_catd, 1, 237, "XCreateBitmapFromData() failed for bitmap.\n"));
643 ge->drag_bitmap = e->drag_bitmap;
645 if (e->drag_mask == NULL) {
646 e->drag_mask = XCreateBitmapFromData(display,
647 window, (char *) drag_mask_xbm_bits,
648 drag_mask_xbm_width, drag_mask_xbm_height);
649 if (e->drag_mask == NULL) {
650 printf("%s", catgets(calendar->DT_catd, 1, 238, "XCreateBitmapFromData() failed for mask.\n"));
654 ge->drag_mask = e->drag_mask;
661 * Resets drag state to indicate the drag is over. Free memory allocated
667 XtPointer clientData,
670 DragContext *context = (DragContext *) clientData;
675 if ((context->editor_type == SingleEditorList) ||
676 (context->editor_type == SingleEditorIcon))
677 ((Editor *) context->editor)->doing_drag = False;
678 else if ((context->editor_type == TodoEditorList) ||
679 (context->editor_type == TodoEditorIcon))
680 ((ToDo *) context->editor)->doing_drag = False;
681 else if ((context->editor_type == GroupEditorList) ||
682 (context->editor_type == GroupEditorIcon))
683 ((GEditor *) context->editor)->doing_drag = False;
692 CreateDragSourceIcon(
699 int pixmapX, pixmapY;
700 unsigned int pixmapWidth, pixmapHeight, pixmapBorder, pixmapDepth;
704 XGetGeometry (XtDisplayOfObject(widget), pixmap, &rootWindow,
705 &pixmapX, &pixmapY, &pixmapWidth, &pixmapHeight,
706 &pixmapBorder, &pixmapDepth);
708 XtSetArg(args[nn], XmNwidth, pixmapWidth); nn++;
709 XtSetArg(args[nn], XmNheight, pixmapHeight); nn++;
710 XtSetArg(args[nn], XmNmaxWidth, pixmapWidth); nn++;
711 XtSetArg(args[nn], XmNmaxHeight, pixmapHeight); nn++;
712 XtSetArg(args[nn], XmNpixmap, pixmap); nn++;
713 XtSetArg(args[nn], XmNmask, mask); nn++;
714 XtSetArg(args[nn], XmNdepth, pixmapDepth); nn++;
715 dragIcon = XmCreateDragIcon(widget, "sourceIcon", args, nn);
721 TranslationDragStart(
725 Cardinal *num_params)
727 static XtCallbackRec convertCBRec[] = { {ApptConvertCB, NULL},
729 static XtCallbackRec dragFinishCBRec[] = { {DragFinishCB, NULL},
732 Display *display = XtDisplay(widget);
733 DragContext *context = calloc(sizeof(DragContext), 1);
734 Editor *e = (Editor *) calendar->editor;
735 CSA_entry_handle entry;
737 Props *p = (Props *)calendar->properties;
739 context->calendar = calendar;
741 if (((Editor *)calendar->editor)->appt_list == widget) {
742 context->editor_type = SingleEditorList;
743 context->editor = (caddr_t) calendar->editor;
744 } else if (((GEditor *)calendar->geditor)->appt_list == widget) {
745 context->editor_type = GroupEditorList;
746 context->editor = (caddr_t) calendar->geditor;
747 } else if (((ToDo *)calendar->todo)->todo_list == widget) {
748 context->editor_type = TodoEditorList;
749 context->editor = (caddr_t) calendar->todo;
757 if (((entry = get_appt_struct(context)) == (CSA_entry_handle)NULL) ||
758 ((apptstr = parse_appt_to_string(calendar->cal_handle,
760 calendar->general->version))
763 switch (context->editor_type)
765 case SingleEditorList:
766 ((Editor *)context->editor)->doing_drag = False;
769 case GroupEditorList:
770 ((GEditor *)context->editor)->doing_drag = False;
774 ((ToDo *)context->editor)->doing_drag = False;
782 context->data = apptstr;
786 convertCBRec[0].closure = (XtPointer)context;
787 dragFinishCBRec[0].closure = (XtPointer)context;
789 if (e->drag_icon == NULL) {
790 e->drag_icon = CreateDragSourceIcon(widget,
795 if (DtDndVaDragStart(widget, event, DtDND_BUFFER_TRANSFER, 1,
797 convertCBRec, dragFinishCBRec,
798 DtNsourceIcon, e->drag_icon,
801 printf("%s", catgets(calendar->DT_catd, 1, 239,
802 "DragStart returned NULL.\n"));
811 EditorType editor_type)
813 static XtCallbackRec convertCBRec[] = { {ApptConvertCB, NULL},
815 static XtCallbackRec dragFinishCBRec[] = { {DragFinishCB, NULL},
818 Display *display = XtDisplay(widget);
819 DragContext *context = calloc(sizeof(DragContext), 1);
820 Editor *e = (Editor *) calendar->editor;
821 GEditor *ge = (GEditor *) calendar->geditor;
822 ToDo *t = (ToDo *) calendar->todo;
823 Dtcm_appointment *appt;
825 int preDsswFlags, preRfpFlags;
827 context->calendar = calendar;
828 context->editor_type = editor_type;
830 if (editor_type == SingleEditorIcon)
832 context->editor = (caddr_t) e;
833 appt = allocate_appt_struct(appt_write, DATAVER_ARCHIVE, NULL);
834 load_appt_defaults(appt, (Props *) calendar->properties);
835 preDsswFlags = e->dsswFlags;
836 preRfpFlags = e->rfpFlags;
837 if (!dssw_form_flags_to_appt(&e->dssw, appt,
839 now(), &e->dsswFlags) ||
840 !rfp_form_flags_to_appt(&e->rfp, appt,
843 (preDsswFlags != e->dsswFlags) ||
844 (preRfpFlags != e->rfpFlags))
846 e->doing_drag = False;
847 free_appt_struct(&appt);
852 else if (editor_type == GroupEditorIcon)
854 context->editor = (caddr_t) ge;
855 appt = allocate_appt_struct(appt_write, DATAVER_ARCHIVE, NULL);
856 load_appt_defaults(appt, (Props *) calendar->properties);
857 preDsswFlags = ge->dsswFlags;
858 preRfpFlags = ge->rfpFlags;
859 if (!dssw_form_flags_to_appt(&ge->dssw, appt,
861 now(), &ge->dsswFlags) ||
862 !rfp_form_flags_to_appt(&ge->rfp, appt,
865 (preDsswFlags != ge->dsswFlags) ||
866 (preRfpFlags != ge->rfpFlags))
868 ge->doing_drag = False;
869 free_appt_struct(&appt);
874 else if (editor_type == TodoEditorIcon)
876 context->editor = (caddr_t) t;
877 if (t->cal->general->version < DATAVER4)
878 appt = allocate_appt_struct(appt_write, DATAVER_ARCHIVE,
879 CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER_I,
880 CSA_ENTRY_ATTR_LAST_UPDATE_I,
881 CSA_ENTRY_ATTR_ORGANIZER_I,
882 CSA_ENTRY_ATTR_START_DATE_I,
883 CSA_ENTRY_ATTR_TYPE_I,
884 CSA_ENTRY_ATTR_CLASSIFICATION_I,
885 CSA_ENTRY_ATTR_END_DATE_I,
886 CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,
887 CSA_ENTRY_ATTR_SUMMARY_I,
888 CSA_ENTRY_ATTR_STATUS_I,
889 CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I,
890 CSA_X_DT_ENTRY_ATTR_REPEAT_TIMES_I,
891 CSA_X_DT_ENTRY_ATTR_REPEAT_INTERVAL_I,
892 CSA_X_DT_ENTRY_ATTR_REPEAT_OCCURRENCE_NUM_I,
893 CSA_ENTRY_ATTR_AUDIO_REMINDER_I,
894 CSA_ENTRY_ATTR_FLASHING_REMINDER_I,
895 CSA_ENTRY_ATTR_MAIL_REMINDER_I,
896 CSA_ENTRY_ATTR_POPUP_REMINDER_I,
899 appt = allocate_appt_struct(appt_write,
900 DATAVER_ARCHIVE, NULL);
902 dssw_form_to_todo(&t->dssw, appt, calendar->calname, now());
903 preRfpFlags = t->rfpFlags;
904 if (!rfp_form_flags_to_appt(&t->rfp, appt,
907 (preRfpFlags != t->rfpFlags))
909 t->doing_drag = False;
910 free_appt_struct(&appt);
914 appt->type->value->item.sint32_value = CSA_TYPE_TODO;
915 appt->show_time->value->item.sint32_value = True;
917 XmToggleButtonGadgetGetState(t->completed_toggle);
918 appt->state->value->item.sint32_value =
920 CSA_STATUS_COMPLETED : CSA_X_DT_STATUS_ACTIVE;
927 apptstr = parse_attrs_to_string(appt, (Props *)calendar->properties,
928 attrs_to_string(appt->attrs,
930 free_appt_struct(&appt);
932 context->data = apptstr;
936 convertCBRec[0].closure = (XtPointer)context;
937 dragFinishCBRec[0].closure = (XtPointer)context;
939 if (e->drag_icon == NULL) {
940 e->drag_icon = CreateDragSourceIcon(widget, e->drag_bitmap,
944 if (DtDndVaDragStart(widget, event, DtDND_BUFFER_TRANSFER, 1,
946 convertCBRec, dragFinishCBRec,
947 DtNsourceIcon, e->drag_icon,
951 printf("%s", catgets(calendar->DT_catd, 1, 239,
952 "DragStart returned NULL.\n"));
957 #define ABS_DELTA(x1, x2) (x1 < x2 ? x2 - x1 : x1 - x2)
965 if (event->type == MotionNotify)
967 XEvent *press = (XEvent *)arg;
969 if ((ABS_DELTA(press->xbutton.x_root,
970 event->xmotion.x_root) > DAMPING) ||
971 (ABS_DELTA(press->xbutton.y_root,
972 event->xmotion.y_root) > DAMPING))
975 else if (event->type == ButtonRelease)
985 // Translation implementing Motif 1.2.5 ProcessPress function
987 * Taken from dtmail/dtmail/RoamMenuWindow.C
990 #define SELECTION_ACTION 0
991 #define TRANSFER_ACTION 1
998 Cardinal *num_params)
1000 int i, action, cur_item;
1001 int *selected_positions, nselected_positions;
1004 * This action happens when Button1 is pressed and the Selection
1005 * and Transfer are integrated on Button1. It is passed two
1006 * parameters: the action to call when the event is a selection,
1007 * and the action to call when the event is a transfer.
1010 if (*num_params != 2 || !XmIsList(w))
1013 action = SELECTION_ACTION;
1014 cur_item = XmListYToPos(w, event->xbutton.y);
1019 XmNselectedPositions, &selected_positions,
1020 XmNselectedPositionCount, &nselected_positions,
1023 for (i=0; i<nselected_positions; i++)
1025 if (cur_item == selected_positions[i])
1028 * The determination of whether this is a transfer drag
1029 * cannot be made until a Motion event comes in. It is
1030 * not a drag as soon as a ButtonUp event happens.
1039 switch (new_event.type)
1042 action = TRANSFER_ACTION;
1045 action = SELECTION_ACTION;
1053 XtCallActionProc(w, params[action], event, params, *num_params);