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: dtcm_editor.c /main/14 1999/09/20 10:32:17 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>
36 #include <Dt/EnvControlP.h>
39 #include <Dt/UserMsg.h>
52 #if !defined(NL_CAT_LOCALE)
53 #define NL_CAT_LOCALE 0
57 static Tt_message load_cb();
59 static const char *ptype = "Dt_AppointmentEditor";
61 typedef enum {no_tt, file_tt, buffer_tt} Dtcm_editor_start;
63 /* Absolute value macro */
65 #define ABS(x) (((x) > 0) ? (x) : (-(x)))
70 #include "drag_mask_xbm"
73 ** Structure for stand-alone editor
81 Dtcm_editor_start init;
83 Tt_pattern *contract_pats;
92 Dtcm_appointment *orig_appt;
104 static void de_apply_proc(Widget , XtPointer , XtPointer );
107 ** Hate like hell to make this global, but I can find no way to get at it
108 ** when I need it in other methods ...
110 ** Also, help uses a global reference to calendar which hoses us ...
116 de_mark_change(Widget w, XtPointer data, XtPointer cbs) {
118 DTCM_editor *de = (DTCM_editor *)data;
122 if ((w == de->dssw->start_text) ||
123 (w == de->dssw->start_am) ||
124 (w == de->dssw->start_pm) ||
125 (w == de->dssw->stop_text) ||
126 (w == de->dssw->stop_am) ||
127 (w == de->dssw->stop_pm))
130 if (w == de->rfp->repeat_menu)
135 merge_old_values(Dtcm_appointment *original, Dtcm_appointment *new) {
137 /* This routine takes in the original appointment structure
138 from the edited appointment, and merges back in any attributes
139 that aren't controlled by our editor, so that when the
140 appointment is written back out to the buffering agent, those
141 attributes are not lost. */
143 int source_count, dest_count, new_attrs;
144 int dest_attr_num = new->count;
147 if (original == NULL)
150 /* We need to see how much larger the attribute array needs to
151 get. For each of the guys in the source attribute array,
152 we need to look and see if it's already a member of the
153 destination array. Those that don't exist, we count, and
156 for (source_count = 0, new_attrs = 0; source_count < original->count; source_count++) {
158 for (dest_count = 0; dest_count < dest_attr_num; dest_count++) {
159 if (original->attrs[source_count].name && new->attrs[dest_count].name) {
160 if (strcmp(original->attrs[source_count].name, new->attrs[dest_count].name) == 0) {
174 /* realloc the attrs array to be large enough to accomodate the new
177 new->attrs = (CSA_attribute *) realloc(new->attrs, (dest_attr_num + new_attrs) * sizeof(CSA_attribute));
179 /* Copy in the new attribute values */
180 for (source_count = 0; source_count < original->count; source_count++) {
182 for (dest_count = 0; dest_count < new->count; dest_count++) {
183 if (original->attrs[source_count].name && new->attrs[dest_count].name) {
184 if (strcmp(original->attrs[source_count].name, new->attrs[dest_count].name) == 0) {
193 new->attrs[new->count] = original->attrs[source_count];
198 /* reset the appointment links, as the old ones have been
199 thrashed by reallocing the attribute array. */
205 CreateDragSourceIcon(
212 int pixmapX, pixmapY;
213 unsigned int pixmapWidth, pixmapHeight, pixmapBorder, pixmapDepth;
217 XGetGeometry (XtDisplayOfObject(widget), pixmap, &rootWindow,
218 &pixmapX, &pixmapY, &pixmapWidth, &pixmapHeight,
219 &pixmapBorder, &pixmapDepth);
221 XtSetArg(args[nn], XmNwidth, pixmapWidth); nn++;
222 XtSetArg(args[nn], XmNheight, pixmapHeight); nn++;
223 XtSetArg(args[nn], XmNmaxWidth, pixmapWidth); nn++;
224 XtSetArg(args[nn], XmNmaxHeight, pixmapHeight); nn++;
225 XtSetArg(args[nn], XmNpixmap, pixmap); nn++;
226 XtSetArg(args[nn], XmNmask, mask); nn++;
227 XtSetArg(args[nn], XmNdepth, pixmapDepth); nn++;
228 dragIcon = XmCreateDragIcon(widget, "sourceIcon", args, nn);
236 * Returns a new IconInfo structure with bitmap, mask, width, height,
237 * icon type and name.
240 GetIcon(DTCM_editor *de)
243 Display *display = XtDisplay(calendar->frame);
244 Window window = XtWindow(calendar->frame);
245 unsigned char *bitmapData, *bitmapMask;
247 if (de->drag_bitmap == 0) {
248 de->drag_bitmap = XCreateBitmapFromData(display,
249 window, (char *) drag_xbm_bits,
250 drag_xbm_width, drag_xbm_height);
251 if (de->drag_bitmap == 0) {
253 printf("%s", catgets(calendar->DT_catd, 1, 237, "XCreateBitmapFromData() failed for bitmap.\n"));
257 if (de->drag_mask == 0) {
258 de->drag_mask = XCreateBitmapFromData(display,
259 window, (char *) drag_mask_xbm_bits,
260 drag_mask_xbm_width, drag_mask_xbm_height);
261 if (de->drag_mask == 0) {
262 printf("%s", catgets(calendar->DT_catd, 1, 238, "XCreateBitmapFromData() failed for mask.\n"));
272 * Resets drag state to indicate the drag is over. Free memory allocated
278 XtPointer clientData,
281 DragContext *context = (DragContext *) clientData;
286 if (context->editor_type == StandAloneEditor)
287 ((DTCM_editor *) context->editor)->doing_drag = False;
298 * Fills in data object with calendar appointment string based on which
299 * appointment in the list was under the pointer when the drag started.
304 XtPointer clientData,
307 DtDndConvertCallbackStruct *convertInfo
308 = (DtDndConvertCallbackStruct*)callData;
309 DtDndBuffer *data = &(convertInfo->dragData->data.buffers[0]);
310 DragContext *context = (DragContext *)clientData;
311 Display *display = XtDisplay(dragContext);
313 = XmInternAtom(display, "CalendarAppointment", False);
314 Calendar *c = context->calendar;
316 if (convertInfo->reason != DtCR_DND_CONVERT_DATA)
319 /* REMIND: Need to check convertInfo->reason, handle DELETE, etc */
321 data->bp = XtNewString(context->data);
322 data->size = strlen(data->bp);
323 data->name = XtNewString(catgets(c->DT_catd, 1, 236, "CalendarAppointment"));
327 StandaloneApptDragStart(
331 EditorType editor_type)
333 static XtCallbackRec convertCBRec[] = { {ApptConvertCB, NULL},
335 static XtCallbackRec dragFinishCBRec[] = { {DragFinishCB, NULL},
338 Display *display = XtDisplay(widget);
339 int itemCount, selectedPos;
340 DragContext *context = calloc(sizeof(DragContext), 1);
342 Dtcm_appointment *appt;
345 int preDsswFlags, preRfpFlags;
347 /* Convert appointment into string. If not successful, don't start drag. */
348 appt = allocate_appt_struct(appt_write, DATAVER_ARCHIVE, NULL);
349 load_appt_defaults(appt, de->p);
350 preDsswFlags = de->dsswFlags;
351 preRfpFlags = de->rfpFlags;
352 if (!dssw_form_flags_to_appt(de->dssw, appt, de->c->calname,
353 now(), &de->dsswFlags) ||
354 !rfp_form_flags_to_appt(de->rfp, appt, de->c->calname,
356 (preDsswFlags != de->dsswFlags) ||
357 (preRfpFlags != de->rfpFlags))
359 de->doing_drag = False;
360 free_appt_struct(&appt);
365 /* save the old count of attributes so that when this appointment
366 gets freed, we can prevent the added attribute references from
369 old_attr_count = appt->count;
370 merge_old_values(de->orig_appt, appt);
371 apptstr = parse_attrs_to_string(appt, de->p,
372 attrs_to_string(appt->attrs, appt->count));
373 appt->count = old_attr_count;
374 free_appt_struct(&appt);
376 context->data = apptstr;
377 context->calendar = c;
378 context->editor_type = editor_type;
379 context->editor = (caddr_t) de;
383 convertCBRec[0].closure = (XtPointer)context;
384 dragFinishCBRec[0].closure = (XtPointer)context;
386 if (de->drag_icon == NULL) {
387 de->drag_icon = CreateDragSourceIcon(widget, de->drag_bitmap, de->drag_mask);
390 if (DtDndVaDragStart(widget, event, DtDND_BUFFER_TRANSFER, 1,
392 convertCBRec, dragFinishCBRec,
393 DtNsourceIcon, de->drag_icon,
397 printf("%s", catgets(c->DT_catd, 1, 239, "DragStart returned NULL.\n"));
404 * Determine if the pointer has moved beyond the drag threshold while button 1
405 * was being held down.
408 EditApptDragMotionHandler(
409 Widget dragInitiator,
410 XtPointer clientData,
414 DTCM_editor *de = (DTCM_editor *) clientData;
416 Dimension source_height, source_width;
417 Position source_x, source_y;
419 if (!de->doing_drag) {
421 /* check to see if the iniital value was within the
422 bounds for the drag source icon. */
424 XtVaGetValues(de->drag_source,
427 XmNheight, &source_height,
428 XmNwidth, &source_width,
431 if ((event->xmotion.x < source_x) ||
432 (event->xmotion.y < source_y) ||
433 (event->xmotion.x > (int) (source_x + source_width)) ||
434 (event->xmotion.y > (int) (source_y + source_height)))
439 * If the drag is just starting, set initial button down coords
441 if (de->initialX == -1 && de->initialY == -1) {
442 de->initialX = event->xmotion.x;
443 de->initialY = event->xmotion.y;
446 * Find out how far pointer has moved since button press
448 diffX = de->initialX - event->xmotion.x;
449 diffY = de->initialY - event->xmotion.y;
451 if ((ABS(diffX) >= DRAG_THRESHOLD) ||
452 (ABS(diffY) >= DRAG_THRESHOLD)) {
453 de->doing_drag = True;
454 StandaloneApptDragStart(dragInitiator, event, de, StandAloneEditor);
465 de_quit_handler(Widget w, XtPointer cdata, XtPointer data) {
466 DTCM_editor *de = (DTCM_editor *)cdata;
469 if (de->modified == True) {
470 char *title = XtNewString(catgets(de->c->DT_catd, 1, 1008, "Calendar Appointment : Help"));
471 char *text = XtNewString(catgets(de->c->DT_catd, 1, 451, "You have made unsaved changes.\nYou may save your changes, discard your changes, \nor return to your previous place in the dialog."));
472 char *ident1 = XtNewString(catgets(de->c->DT_catd, 1, 452, "Save"));
473 char *ident2 = XtNewString(catgets(de->c->DT_catd, 1, 700, "Discard"));
474 char *ident3 = XtNewString(catgets(de->c->DT_catd, 1, 923, "Cancel"));
475 answer = dialog_popup(de->top_level,
478 BUTTON_IDENT, 1, ident1,
479 BUTTON_IDENT, 2, ident2,
480 BUTTON_IDENT, 3, ident3,
481 DIALOG_IMAGE, de->pu->xm_warning_pixmap,
490 de_apply_proc(NULL, (XtPointer)de, NULL);
491 XtPopdown(de->top_level);
493 else if (answer == 2) {
495 tttk_message_fail(de->contract, TT_DESKTOP_ECANCELED, NULL, True);
496 XtPopdown(de->top_level);
498 else if (answer == 3) {
505 tttk_message_fail(de->contract, TT_DESKTOP_ECANCELED, NULL, True);
506 XtPopdown(de->top_level);
521 load_from_file(DTCM_editor *de) {
523 CmDataList *list = NULL;
524 Dtcm_appointment *appt;
526 list = CmDataListCreate();
527 parse_appt_from_file(de->c->DT_catd, de->file, list, de->p,
528 query_user, de->c, DATAVER_ARCHIVE);
529 if (appt = (Dtcm_appointment *)CmDataListGetData(list, 1)) {
530 dssw_attrs_to_form(de->dssw, appt);
531 rfp_attrs_to_form(de->rfp, appt);
533 for (i = 1; i <= list->count; i++)
534 if (appt = (Dtcm_appointment *)
535 CmDataListGetData(list, i)) {
537 free_appt_struct(&de->orig_appt);
539 de->orig_appt = appt;
541 CmDataListDestroy(list, B_FALSE);
542 de->dsswFlags = de->rfpFlags = 0;
546 de_set_defaults(DTCM_editor *de) {
548 if (de->file && (access(de->file, R_OK) == 0)) {
551 set_dssw_defaults(de->dssw, now(), True);
552 set_rfp_defaults(de->rfp);
553 de->dsswFlags = de->rfpFlags = 0;
556 de->modified = False;
560 de_apply_proc(Widget w, XtPointer client_data, XtPointer data) {
563 DTCM_editor *de = (DTCM_editor *)client_data;
564 Dtcm_appointment *appt;
566 Display *dpy = XtDisplayOfObject(w);
568 appt = allocate_appt_struct(appt_write,
571 load_appt_defaults(appt, de->p);
573 dssw_form_to_appt(de->dssw, appt, de->c->calname, now());
575 rfp_form_to_appt(de->rfp, appt, de->c->calname);
577 /* save the old count of attributes so that when this appointment
578 gets freed, we can prevent the added attribute references from
581 old_attr_count = appt->count;
582 merge_old_values(de->orig_appt, appt);
583 str = parse_attrs_to_string(appt, de->p, attrs_to_string(appt->attrs, appt->count));
584 appt->count = old_attr_count;
585 de->modified = False;
590 /* we need to distinguish between whether the data is being
591 saved as part of application termination, or as part of
592 pressing the "Apply" button. If it's is app termination,
593 we need to call ttmedia_load_reply, and if it is an
594 intermediate save, we are supposed to call ttmedia_Deposit.
595 Hmmph. We also need to be pretty clear about saving it back
596 in the same fashion is was supplied. If it came as part of
597 a buffer, it needs to go back that way. */
600 /* The first case is from application exit */
604 /* if it was a file transfer, we should write out the
605 file, and set the buffer to null. If it came from
606 a buffer, we don't bother to write out the file. */
609 ttmedia_load_reply(de->contract, NULL, 0, True);
612 if (de->init == file_tt) {
613 fp = fopen(de->file, "w");
620 fprintf(fp, "%s", str);
622 ttmedia_load_reply(de->contract, NULL, 0, True);
625 ttmedia_load_reply(de->contract, (unsigned char *) str, strlen(str), True);
631 /* This case is from the "Apply" button. In this case,
632 if the app was started normally (no tt), then we
633 just write out the file. If it was from tt, we then
634 use ttmedia_Deposit to send the data back. */
636 if ((de->init == no_tt) || (de->init == file_tt)) {
637 fp = fopen(de->file, "w");
644 fprintf(fp, "%s", str);
647 if (de->init == file_tt)
648 ttmedia_Deposit(de->contract,
658 ttmedia_Deposit(de->contract,
661 (const unsigned char *)str,
671 free_appt_struct(&appt);
675 de_reset_proc(Widget w, XtPointer client_data, XtPointer data) {
676 DTCM_editor *de = (DTCM_editor *)client_data;
679 de->dsswFlags = de->rfpFlags = 0;
683 display_command_usage() {
684 fprintf(stderr, "\ndtcm_editor Usage: dtcm [filename]\n\n");
689 OKCB (Widget dialog, XtPointer client_data, XtPointer call_data)
691 XtUnmanageChild((Widget) client_data);
695 DieFromToolTalkError(DTCM_editor *de, char *errfmt, Tt_status status)
698 Widget dialog, dialogShell;
699 char *errmsg, *statmsg, *title;
700 XmString xms_errmsg, xms_ok, xms_title;
703 if (! tt_is_err(status)) return;
705 statmsg = tt_status_message(status);
706 errmsg = XtMalloc(strlen(errfmt) + strlen(statmsg) + 2);
707 sprintf(errmsg, errfmt, statmsg);
709 xms_ok = XmStringCreateLocalized(catgets(de->c->DT_catd, 2, 3, "OK"));
710 xms_errmsg = XmStringCreateLocalized(errmsg);
711 xms_title = XmStringCreateLocalized(catgets(de->c->DT_catd, 2, 4,
712 "Calendar : Appointment Editor - Warning"));
715 XtSetArg(args[n], XmNautoUnmanage, False); n++;
716 XtSetArg(args[n], XmNokLabelString, xms_ok); n++;
717 XtSetArg(args[n], XmNdialogTitle, xms_title); n++;
718 XtSetArg(args[n], XmNmessageString, xms_errmsg); n++;
719 XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
720 XtSetArg(args[n], XmNdialogType, XmDIALOG_WARNING); n++;
722 dialog = XmCreateMessageDialog(de->top_level, "IconEditorError", args, n);
723 XtAddCallback(dialog, XmNokCallback, OKCB, (XtPointer) dialog);
724 XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
725 XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
728 * Disable the frame menu from dialog since we don't want the user
729 * to be able to close dialogs with the frame menu
731 dialogShell = XtParent(dialog);
733 XtSetArg(args[n], XmNmwmDecorations, MWM_DECOR_ALL | MWM_DECOR_MENU); n++;
734 XtSetValues(dialogShell, args, n);
735 XtManageChild(dialog);
736 XtRealizeWidget(dialogShell);
738 _DtSimpleError("Dtcm", DtWarning, NULL, errmsg);
741 XmStringFree(xms_ok);
742 XmStringFree(xms_errmsg);
743 XmStringFree(xms_title);
749 * Initialize tooltalk. Can be called multiple times: the first call
750 * initializes tooltalk, subsequent calls are no-ops.
753 * -1 Error. Tooltalk not initialized
754 * 0 Tooltalk already initialized
755 * 1 Tooltalk succussfully intialized
762 XtAppContext context,
766 static int initialized = 0;
772 if (de->c->tt_procid) {
776 ttenv = (char *)getenv("TT_SESSION");
777 if (!ttenv || strlen(ttenv) == 0) {
778 session = tt_X_session(XDisplayString(XtDisplay(shell)));
779 tt_default_session_set(session);
783 de->c->tt_procid = ttdt_open(&ttfd, toolname, "SunSoft", "%I", 1);
784 status = tt_ptr_error(de->c->tt_procid);
785 if (tt_is_err(status)) {
786 de->c->tt_procid = NULL;
791 * Declare our ptype, and register the callback to handle
792 * Edit/Display/Compose requests
794 status = ttmedia_ptype_declare(ptype, 0, load_cb, (void *)de, 1);
796 if (tt_is_err(status)) {
797 fprintf(stderr, "cmtt_init could not declare ptype: %s\n",
798 tt_status_message(status));
802 status = ttmedia_ptype_declare(ptype, 1000, load_cb, (void *)de, 0);
804 if (tt_is_err(status)) {
805 fprintf(stderr, "cmtt_init could not declare ptype: %s\n",
806 tt_status_message(status));
809 ttdt_session_join(0, NULL, shell, de->c, 1);
811 XtAppAddInput(context, ttfd, (XtPointer)XtInputReadMask,
812 tttk_Xt_input_handler, de->c->tt_procid);
814 tttk_Xt_input_handler( 0, 0, 0 );
820 reply_cb(Tt_message m,
823 unsigned char *contents,
827 char *client_procID = tt_message_handler(m);
828 if ( debug && (client_procID != NULL) ) {
829 fprintf(stderr, "DEBUG: reply_cb():client_procID = %s\n", client_procID);
830 fprintf(stderr, "DEBUG: reply_cb():message_op = %s\n", tt_message_op(m));
842 /* For now do nothing
846 case TTDT_GET_STATUS:
856 * Handle Edit, Display and Compose requests
864 unsigned char *contents,
876 CmDataList *list = NULL;
877 Dtcm_appointment *appt;
880 de = (DTCM_editor *)clientdata;
882 de->vtype = strdup(tt_message_arg_type(msg, 0));
884 if (diagnosis != TT_OK) {
885 if (tt_message_status(msg) == TT_WRN_START_MESSAGE) {
887 * Error in start message! we may want to exit
888 * here, but for now let toolkit handle error
893 /* Let toolkit handle the error */
897 de->contract_pats = ttdt_message_accept(msg, contract_cb, clientdata,
900 tt_ptype_undeclare(ptype);
902 if ((status = tt_ptr_error(de->contract_pats)) != TT_OK) {
903 fprintf(stderr, "dtcm: load_cb could not accept message: %s\n",
904 tt_status_message(status));
907 tttk_patterns_destroy(de->contract_pats);
911 de->read_only = False;
916 XtSetSensitive(de->attach_button, True);
920 /* for Display only messages, the "Attach"
921 button makes no sense */
924 XtSetSensitive(de->attach_button, True);
926 XtSetSensitive(de->attach_button, False);
927 de->read_only = True;
929 list = CmDataListCreate();
933 * Save data to a file so we can pass it to parse_appt_from_file
936 strcpy(filename, "/tmp/cmXXXXXX");
938 if ((fp = fopen(filename, "w")) == 0) {
939 tttk_message_fail( msg, TT_DESKTOP_ENODATA, 0, 1 );
943 fwrite(contents, 1, len, fp);
945 parse_appt_from_file(de->c->DT_catd, filename,
946 list, de->p, query_user,
947 de->c, DATAVER_ARCHIVE);
949 de->init = buffer_tt;
953 de->file = strdup(file);
954 parse_appt_from_file(de->c->DT_catd, de->file,
955 list, de->p, query_user,
956 de->c, DATAVER_ARCHIVE);
960 if (appt = (Dtcm_appointment *)CmDataListGetData(list, 1)) {
961 dssw_attrs_to_form(de->dssw, appt);
962 rfp_attrs_to_form(de->rfp, appt);
964 for (i = 1; i <= list->count; i++)
965 if (appt = (Dtcm_appointment *)
966 CmDataListGetData(list, i)) {
968 free_appt_struct(&de->orig_appt);
970 de->orig_appt = appt;
972 CmDataListDestroy(list, B_FALSE);
978 de->modified = False;
979 de->dsswFlags = de->rfpFlags = 0;
981 tt_free((caddr_t)contents);
991 XtPointer client_data,
994 Display *display = XtDisplay(w);
995 DtDndDropCallbackStruct *transfer_info = (DtDndDropCallbackStruct *)call_data;
1003 de = (DTCM_editor *)client_data;
1005 transfer_info->status = DtDND_SUCCESS;
1007 for (i = 0; i < transfer_info->dropData->numItems; i++) {
1008 switch(transfer_info->dropData->protocol) {
1009 case DtDND_FILENAME_TRANSFER:
1010 /* REMIND -- handle multiple filenames */
1011 data = transfer_info->dropData->data.files[0];
1013 de->file = strdup(data);
1016 case DtDND_BUFFER_TRANSFER:
1019 * Save data to a file so we can pass it to drag_load_proc().
1021 strcpy(filename, "/tmp/cmXXXXXX");
1024 if ((fp = fopen(filename, "w")) == 0) {
1025 transfer_info->status = DtDND_FAILURE;
1029 data = transfer_info->dropData->data.buffers[0].bp;
1030 size = transfer_info->dropData->data.buffers[0].size;
1031 fwrite(data, 1, size, fp);
1034 de->file = strdup(filename);
1040 transfer_info->status = DtDND_FAILURE;
1049 de_register_drop_site(
1052 Boolean registerchildren)
1055 XtCallbackRec transfer_cb_rec[] = { {handle_drop_cb, NULL},
1057 Display *display = XtDisplayOfObject(w);
1059 transfer_cb_rec[0].closure = (XtPointer)de;
1061 DtDndVaDropRegister(w, DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER,
1062 XmDROP_COPY | XmDROP_MOVE,
1064 DtNregisterChildren, registerchildren,
1073 main(int argc, char **argv) {
1074 int dssw_loffset, rfp_loffset, start, stop;
1075 Dimension dssw_x, rfp_x;
1078 Boolean btn1_transfer;
1079 Dimension width, longest_dssw_label, longest_rfp_label;
1080 WidgetList children;
1089 de = (DTCM_editor *)ckalloc(sizeof(DTCM_editor));
1093 if (strcasecmp(argv[1], "-h") == 0)
1094 display_command_usage();
1095 else if (argv[1][0] != '-')
1096 de->file = cm_strdup(argv[1]);
1099 XtSetLanguageProc(NULL, NULL, NULL);
1100 _DtEnvControl(DT_ENV_SET); /* set up environment variables */
1102 de->top_level = XtVaAppInitialize(&app,
1103 "Dtcm", NULL, 0, &argc, argv, NULL,
1104 XmNallowShellResize, True,
1105 XmNdeleteResponse, XmDO_NOTHING,
1107 setup_quit_handler(de->top_level, de_quit_handler, (caddr_t)de);
1110 ** First, create a calendar and fill only the stuff we're going to
1113 calendar = (Calendar *)ckalloc(sizeof(Calendar));
1115 de->p = (Props *)ckalloc(sizeof(Props));
1116 de->c->properties = (caddr_t)de->p;
1117 de->c->general = (General*) ckalloc(sizeof(General));
1118 de->c->general->version = DATAVER_ARCHIVE;
1119 de->c->frame = de->top_level;
1120 de->pu = (Props_pu *)ckalloc(sizeof(Props_pu));
1121 de->c->properties_pu = (caddr_t)de->pu;
1124 cal_convert_cmrc(de->p);
1125 if ((start = get_int_prop(de->p, CP_DAYBEGIN)) < 0)
1127 else if (start > 22)
1129 if ((stop = get_int_prop(de->p, CP_DAYEND)) <= start)
1133 set_int_prop(de->p, CP_DAYBEGIN, start);
1134 set_int_prop(de->p, CP_DAYEND, stop);
1135 de->c->calname = cm_strdup(get_char_prop(de->p, CP_DEFAULTCAL));
1136 de->c->DT_catd = catopen(DTCM_CAT, NL_CAT_LOCALE);
1138 /* Open the message catalog for internationalization */
1139 calendar->DT_catd = catopen(DTCM_CAT, NL_CAT_LOCALE);
1141 title = XtNewString(catgets(calendar->DT_catd, 1, 1074,
1142 "Calendar Appointment"));
1143 XtVaSetValues(de->top_level,
1149 ** Okay, now create the form manager and the widgets
1151 de->form = XtVaCreateWidget("form",
1152 xmFormWidgetClass, de->top_level,
1153 XmNautoUnmanage, True,
1157 label_str = XmStringCreateLocalized(catgets(de->c->DT_catd, 1, 846, "Save"));
1158 de->attach_button = XtVaCreateWidget("attach_button",
1159 xmPushButtonGadgetClass, de->form,
1160 XmNlabelString, label_str,
1161 XmNleftAttachment, XmATTACH_POSITION,
1163 XmNrightAttachment, XmATTACH_POSITION,
1164 XmNrightPosition, 2,
1165 XmNbottomAttachment, XmATTACH_FORM,
1166 XmNbottomOffset, 10,
1168 XmStringFree(label_str);
1169 XtAddCallback(de->attach_button, XmNactivateCallback, de_apply_proc, (XtPointer)de);
1171 XtSetSensitive(de->attach_button, False);
1173 label_str = XmStringCreateLocalized(catgets(de->c->DT_catd, 1, 691, "Reset"));
1174 de->reset_button = XtVaCreateWidget("reset_button",
1175 xmPushButtonGadgetClass, de->form,
1176 XmNlabelString, label_str,
1177 XmNleftAttachment, XmATTACH_POSITION,
1179 XmNrightAttachment, XmATTACH_POSITION,
1180 XmNrightPosition, 4,
1181 XmNbottomAttachment, XmATTACH_FORM,
1182 XmNbottomOffset, 10,
1184 XmStringFree(label_str);
1185 XtAddCallback(de->reset_button, XmNactivateCallback, de_reset_proc, de);
1187 create_all_pixmaps(de->pu, de->form);
1190 de->rfp = (RFP *)ckalloc(sizeof(RFP));
1191 build_rfp(de->rfp, de->c, de->form);
1192 XtVaSetValues(de->rfp->rfp_form_mgr,
1193 XmNbottomAttachment, XmATTACH_WIDGET,
1194 XmNbottomWidget, de->attach_button,
1195 XmNbottomOffset, 25,
1196 XmNleftAttachment, XmATTACH_FORM,
1199 XtVaGetValues(de->rfp->rfp_form_mgr,
1200 XmNchildren, &children,
1203 /* We don't want to manage the privacy widgets */
1204 for (i = 0; i < n; i++) {
1205 if ((children[i] == de->rfp->privacy_label) ||
1206 (children[i] == de->rfp->privacy_menu))
1208 widgets[j++] = children[i];
1210 XtManageChildren(widgets, n - 2);
1213 * Add a drag source icon inside the dssw, lower right
1215 xmstr = XmStringCreateLocalized(
1216 catgets(de->c->DT_catd, 1, 627, "Drag Appt"));
1217 de->drag_source = XtVaCreateWidget("drag_source",
1218 dtIconGadgetClass, de->form,
1219 XmNpixmapPosition, XmPIXMAP_TOP,
1220 XmNstringPosition, XmSTRING_BOTTOM,
1221 XmNalignment, XmALIGNMENT_CENTER,
1223 XmNbottomAttachment, XmATTACH_WIDGET,
1224 XmNbottomWidget, de->attach_button,
1225 XmNbottomOffset, 25,
1226 XmNleftAttachment, XmATTACH_WIDGET,
1227 XmNleftWidget, de->rfp->rfp_form_mgr,
1228 XmNrightAttachment, XmATTACH_FORM,
1229 XmNtraversalOn, False,
1231 XmStringFree(xmstr);
1233 XtAddEventHandler(XtParent(de->drag_source), Button1MotionMask, False,
1234 (XtEventHandler)EditApptDragMotionHandler, (XtPointer) de);
1236 XtVaGetValues((Widget)XmGetXmDisplay(XtDisplay(de->form)),
1237 "enableBtn1Transfer", &btn1_transfer,
1240 /* btn1_transfer is a tri-state variable - see 1195846 */
1241 if ((Boolean)btn1_transfer != True)
1242 XtAddEventHandler(XtParent(de->drag_source),
1243 Button2MotionMask, False,
1244 (XtEventHandler)EditApptDragMotionHandler,
1248 if (de->pu->drag_icon_xbm)
1249 XtVaSetValues(de->drag_source,
1250 XmNpixmap, de->pu->drag_icon_xbm,
1254 de->dssw = (DSSW *)ckalloc(sizeof(DSSW));
1255 build_dssw(de->dssw, de->c, de->form, True, True);
1256 XtVaSetValues(de->dssw->dssw_form_mgr,
1257 XmNtopAttachment, XmATTACH_FORM,
1259 XmNbottomAttachment, XmATTACH_WIDGET,
1260 XmNbottomWidget, de->rfp->rfp_form_mgr,
1261 XmNbottomOffset, 15,
1262 XmNleftAttachment, XmATTACH_FORM,
1265 ManageChildren(de->dssw->dssw_form_mgr);
1267 /* set up callback to detect whether the appointment
1268 definition has been modified */
1270 XtAddCallback(de->dssw->start_text, XmNvalueChangedCallback, de_mark_change, de);
1271 XtAddCallback(de->dssw->start_am, XmNvalueChangedCallback, de_mark_change, de);
1272 XtAddCallback(de->dssw->start_pm, XmNvalueChangedCallback, de_mark_change, de);
1273 XtAddCallback(de->dssw->stop_text, XmNvalueChangedCallback, de_mark_change, de);
1274 XtAddCallback(de->dssw->stop_am, XmNvalueChangedCallback, de_mark_change, de);
1275 XtAddCallback(de->dssw->stop_pm, XmNvalueChangedCallback, de_mark_change, de);
1276 XtAddCallback(de->dssw->what_text, XmNvalueChangedCallback, de_mark_change, de);
1277 XtAddCallback(de->rfp->repeat_menu, XmNselectionCallback, de_mark_change, de);
1278 XtAddCallback(de->rfp->for_menu, XmNselectionCallback, de_mark_change, de);
1280 ManageChildren(de->form);
1281 XtManageChild(de->form);
1282 XtRealizeWidget(de->top_level);
1285 ** Do some monkeying to compensate for Motif's pitiful form managers
1286 XtVaGetValues(de->dssw->start_menu, XmNx, &dssw_x,
1287 XmNleftOffset, &dssw_loffset,
1289 XtVaGetValues(de->rfp->repeat_menu, XmNx, &rfp_x,
1290 XmNleftOffset, &rfp_loffset,
1294 XtVaSetValues(de->rfp->rfp_form_mgr,
1295 XmNleftOffset, rfp_loffset + (dssw_x - rfp_x),
1297 else if (rfp_x > dssw_x)
1298 XtVaSetValues(de->dssw->dssw_form_mgr,
1299 XmNleftOffset, dssw_loffset + (rfp_x - dssw_x),
1303 /* Don't need these any more.
1304 XtVaGetValues(de->dssw->date_label, XmNwidth, &longest_dssw_label, NULL);
1306 XtVaGetValues(de->dssw->start_label, XmNwidth, &width, NULL);
1307 if (width > longest_dssw_label)
1308 longest_dssw_label = width;
1310 XtVaGetValues(de->dssw->stop_label, XmNwidth, &width, NULL);
1311 if (width > longest_dssw_label)
1312 longest_dssw_label = width;
1314 XtVaGetValues(de->dssw->what_label, XmNwidth, &width, NULL);
1315 if (width > longest_dssw_label)
1316 longest_dssw_label = width;
1318 XtVaGetValues(de->rfp->frequency_label, XmNwidth, &longest_rfp_label, NULL);
1319 XtVaGetValues(de->rfp->for_label, XmNwidth, &width, NULL);
1320 if (width > longest_rfp_label)
1321 longest_rfp_label = width;
1323 XtVaSetValues(de->dssw->dssw_form_mgr,
1324 XmNleftOffset, longest_rfp_label - longest_dssw_label,
1328 de_set_defaults(de);
1330 de_register_drop_site(de, de->form, True);
1331 de_register_drop_site(de, de->dssw->dssw_form_mgr, False);
1332 de_register_drop_site(de, de->rfp->rfp_form_mgr, False);
1334 XmProcessTraversal(de->dssw->what_text, XmTRAVERSE_CURRENT);
1335 XtVaSetValues(de->form, XmNinitialFocus, de->dssw->what_text, NULL);
1338 status = cmtt_init("AppointmentEditor", de, app, calendar->frame);
1339 if (TT_OK != status) {
1341 errfmt = catgets(calendar->DT_catd, 2, 2,
1342 "Could not connect to ToolTalk:\n%s\n");
1343 DieFromToolTalkError( de, errfmt, status );