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 libraries 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 accommodate 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;
346 char *attrstring = NULL;
348 /* Convert appointment into string. If not successful, don't start drag. */
349 appt = allocate_appt_struct(appt_write, DATAVER_ARCHIVE, NULL);
350 load_appt_defaults(appt, de->p);
351 preDsswFlags = de->dsswFlags;
352 preRfpFlags = de->rfpFlags;
353 if (!dssw_form_flags_to_appt(de->dssw, appt, de->c->calname,
354 now(), &de->dsswFlags) ||
355 !rfp_form_flags_to_appt(de->rfp, appt, de->c->calname,
357 (preDsswFlags != de->dsswFlags) ||
358 (preRfpFlags != de->rfpFlags))
360 de->doing_drag = False;
361 free_appt_struct(&appt);
366 /* save the old count of attributes so that when this appointment
367 gets freed, we can prevent the added attribute references from
370 old_attr_count = appt->count;
371 merge_old_values(de->orig_appt, appt);
372 attrstring = attrs_to_string(appt->attrs, appt->count);
373 apptstr = parse_attrs_to_string(appt, de->p, attrstring);
375 appt->count = old_attr_count;
376 free_appt_struct(&appt);
378 context->data = apptstr;
379 context->calendar = c;
380 context->editor_type = editor_type;
381 context->editor = (caddr_t) de;
385 convertCBRec[0].closure = (XtPointer)context;
386 dragFinishCBRec[0].closure = (XtPointer)context;
388 if (de->drag_icon == NULL) {
389 de->drag_icon = CreateDragSourceIcon(widget, de->drag_bitmap, de->drag_mask);
392 if (DtDndVaDragStart(widget, event, DtDND_BUFFER_TRANSFER, 1,
394 convertCBRec, dragFinishCBRec,
395 DtNsourceIcon, de->drag_icon,
399 printf("%s", catgets(c->DT_catd, 1, 239, "DragStart returned NULL.\n"));
406 * Determine if the pointer has moved beyond the drag threshold while button 1
407 * was being held down.
410 EditApptDragMotionHandler(
411 Widget dragInitiator,
412 XtPointer clientData,
416 DTCM_editor *de = (DTCM_editor *) clientData;
418 Dimension source_height, source_width;
419 Position source_x, source_y;
421 if (!de->doing_drag) {
423 /* check to see if the iniital value was within the
424 bounds for the drag source icon. */
426 XtVaGetValues(de->drag_source,
429 XmNheight, &source_height,
430 XmNwidth, &source_width,
433 if ((event->xmotion.x < source_x) ||
434 (event->xmotion.y < source_y) ||
435 (event->xmotion.x > (int) (source_x + source_width)) ||
436 (event->xmotion.y > (int) (source_y + source_height)))
441 * If the drag is just starting, set initial button down coords
443 if (de->initialX == -1 && de->initialY == -1) {
444 de->initialX = event->xmotion.x;
445 de->initialY = event->xmotion.y;
448 * Find out how far pointer has moved since button press
450 diffX = de->initialX - event->xmotion.x;
451 diffY = de->initialY - event->xmotion.y;
453 if ((ABS(diffX) >= DRAG_THRESHOLD) ||
454 (ABS(diffY) >= DRAG_THRESHOLD)) {
455 de->doing_drag = True;
456 StandaloneApptDragStart(dragInitiator, event, de, StandAloneEditor);
467 de_quit_handler(Widget w, XtPointer cdata, XtPointer data) {
468 DTCM_editor *de = (DTCM_editor *)cdata;
471 if (de->modified == True) {
472 char *title = XtNewString(catgets(de->c->DT_catd, 1, 1008, "Calendar Appointment : Help"));
473 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."));
474 char *ident1 = XtNewString(catgets(de->c->DT_catd, 1, 452, "Save"));
475 char *ident2 = XtNewString(catgets(de->c->DT_catd, 1, 700, "Discard"));
476 char *ident3 = XtNewString(catgets(de->c->DT_catd, 1, 923, "Cancel"));
477 answer = dialog_popup(de->top_level,
480 BUTTON_IDENT, 1, ident1,
481 BUTTON_IDENT, 2, ident2,
482 BUTTON_IDENT, 3, ident3,
483 DIALOG_IMAGE, de->pu->xm_warning_pixmap,
492 de_apply_proc(NULL, (XtPointer)de, NULL);
493 XtPopdown(de->top_level);
495 else if (answer == 2) {
497 tttk_message_fail(de->contract, TT_DESKTOP_ECANCELED, NULL, True);
498 XtPopdown(de->top_level);
500 else if (answer == 3) {
507 tttk_message_fail(de->contract, TT_DESKTOP_ECANCELED, NULL, True);
508 XtPopdown(de->top_level);
523 load_from_file(DTCM_editor *de) {
525 CmDataList *list = NULL;
526 Dtcm_appointment *appt;
528 list = CmDataListCreate();
529 parse_appt_from_file(de->c->DT_catd, de->file, list, de->p,
530 query_user, de->c, DATAVER_ARCHIVE);
531 if (appt = (Dtcm_appointment *)CmDataListGetData(list, 1)) {
532 dssw_attrs_to_form(de->dssw, appt);
533 rfp_attrs_to_form(de->rfp, appt);
535 for (i = 1; i <= list->count; i++)
536 if (appt = (Dtcm_appointment *)
537 CmDataListGetData(list, i)) {
539 free_appt_struct(&de->orig_appt);
541 de->orig_appt = appt;
543 CmDataListDestroy(list, B_FALSE);
544 de->dsswFlags = de->rfpFlags = 0;
548 de_set_defaults(DTCM_editor *de) {
550 if (de->file && (access(de->file, R_OK) == 0)) {
553 set_dssw_defaults(de->dssw, now(), True);
554 set_rfp_defaults(de->rfp);
555 de->dsswFlags = de->rfpFlags = 0;
558 de->modified = False;
562 de_apply_proc(Widget w, XtPointer client_data, XtPointer data) {
565 DTCM_editor *de = (DTCM_editor *)client_data;
566 Dtcm_appointment *appt;
568 Display *dpy = XtDisplayOfObject(w);
569 char *attrstring = NULL;
571 appt = allocate_appt_struct(appt_write,
574 load_appt_defaults(appt, de->p);
576 dssw_form_to_appt(de->dssw, appt, de->c->calname, now());
578 rfp_form_to_appt(de->rfp, appt, de->c->calname);
580 /* save the old count of attributes so that when this appointment
581 gets freed, we can prevent the added attribute references from
584 old_attr_count = appt->count;
585 merge_old_values(de->orig_appt, appt);
586 attrstring = attrs_to_string(appt->attrs, appt->count);
587 str = parse_attrs_to_string(appt, de->p, attrstring);
589 appt->count = old_attr_count;
590 de->modified = False;
593 free_appt_struct(&appt);
597 /* we need to distinguish between whether the data is being
598 saved as part of application termination, or as part of
599 pressing the "Apply" button. If it's is app termination,
600 we need to call ttmedia_load_reply, and if it is an
601 intermediate save, we are supposed to call ttmedia_Deposit.
602 Hmmph. We also need to be pretty clear about saving it back
603 in the same fashion is was supplied. If it came as part of
604 a buffer, it needs to go back that way. */
607 /* The first case is from application exit */
611 /* if it was a file transfer, we should write out the
612 file, and set the buffer to null. If it came from
613 a buffer, we don't bother to write out the file. */
616 ttmedia_load_reply(de->contract, NULL, 0, True);
619 if (de->init == file_tt) {
620 fp = fopen(de->file, "w");
625 free_appt_struct(&appt);
629 fprintf(fp, "%s", str);
631 ttmedia_load_reply(de->contract, NULL, 0, True);
634 ttmedia_load_reply(de->contract, (unsigned char *) str, strlen(str), True);
640 /* This case is from the "Apply" button. In this case,
641 if the app was started normally (no tt), then we
642 just write out the file. If it was from tt, we then
643 use ttmedia_Deposit to send the data back. */
645 if ((de->init == no_tt) || (de->init == file_tt)) {
646 fp = fopen(de->file, "w");
651 free_appt_struct(&appt);
655 fprintf(fp, "%s", str);
658 if (de->init == file_tt)
659 ttmedia_Deposit(de->contract,
669 ttmedia_Deposit(de->contract,
672 (const unsigned char *)str,
682 free_appt_struct(&appt);
686 de_reset_proc(Widget w, XtPointer client_data, XtPointer data) {
687 DTCM_editor *de = (DTCM_editor *)client_data;
690 de->dsswFlags = de->rfpFlags = 0;
694 display_command_usage(void)
696 fprintf(stderr, "\ndtcm_editor Usage: dtcm [filename]\n\n");
701 OKCB (Widget dialog, XtPointer client_data, XtPointer call_data)
703 XtUnmanageChild((Widget) client_data);
707 DieFromToolTalkError(DTCM_editor *de, char *errfmt, Tt_status status)
710 Widget dialog, dialogShell;
711 char *errmsg, *statmsg, *title;
712 XmString xms_errmsg, xms_ok, xms_title;
715 if (! tt_is_err(status)) return;
717 statmsg = tt_status_message(status);
718 errmsg = XtMalloc(strlen(errfmt) + strlen(statmsg) + 2);
719 sprintf(errmsg, errfmt, statmsg);
721 xms_ok = XmStringCreateLocalized(catgets(de->c->DT_catd, 2, 3, "OK"));
722 xms_errmsg = XmStringCreateLocalized(errmsg);
723 xms_title = XmStringCreateLocalized(catgets(de->c->DT_catd, 2, 4,
724 "Calendar : Appointment Editor - Warning"));
727 XtSetArg(args[n], XmNautoUnmanage, False); n++;
728 XtSetArg(args[n], XmNokLabelString, xms_ok); n++;
729 XtSetArg(args[n], XmNdialogTitle, xms_title); n++;
730 XtSetArg(args[n], XmNmessageString, xms_errmsg); n++;
731 XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
732 XtSetArg(args[n], XmNdialogType, XmDIALOG_WARNING); n++;
734 dialog = XmCreateMessageDialog(de->top_level, "IconEditorError", args, n);
735 XtAddCallback(dialog, XmNokCallback, OKCB, (XtPointer) dialog);
736 XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
737 XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
740 * Disable the frame menu from dialog since we don't want the user
741 * to be able to close dialogs with the frame menu
743 dialogShell = XtParent(dialog);
745 XtSetArg(args[n], XmNmwmDecorations, MWM_DECOR_ALL | MWM_DECOR_MENU); n++;
746 XtSetValues(dialogShell, args, n);
747 XtManageChild(dialog);
748 XtRealizeWidget(dialogShell);
750 _DtSimpleError("Dtcm", DtWarning, NULL, errmsg);
753 XmStringFree(xms_ok);
754 XmStringFree(xms_errmsg);
755 XmStringFree(xms_title);
761 * Initialize tooltalk. Can be called multiple times: the first call
762 * initializes tooltalk, subsequent calls are no-ops.
765 * -1 Error. Tooltalk not initialized
766 * 0 Tooltalk already initialized
767 * 1 Tooltalk succussfully intialized
774 XtAppContext context,
778 static int initialized = 0;
784 if (de->c->tt_procid) {
788 ttenv = (char *)getenv("TT_SESSION");
789 if (!ttenv || strlen(ttenv) == 0) {
790 session = tt_X_session(XDisplayString(XtDisplay(shell)));
791 tt_default_session_set(session);
795 de->c->tt_procid = ttdt_open(&ttfd, toolname, "SunSoft", "%I", 1);
796 status = tt_ptr_error(de->c->tt_procid);
797 if (tt_is_err(status)) {
798 de->c->tt_procid = NULL;
803 * Declare our ptype, and register the callback to handle
804 * Edit/Display/Compose requests
806 status = ttmedia_ptype_declare(ptype, 0, load_cb, (void *)de, 1);
808 if (tt_is_err(status)) {
809 fprintf(stderr, "cmtt_init could not declare ptype: %s\n",
810 tt_status_message(status));
814 status = ttmedia_ptype_declare(ptype, 1000, load_cb, (void *)de, 0);
816 if (tt_is_err(status)) {
817 fprintf(stderr, "cmtt_init could not declare ptype: %s\n",
818 tt_status_message(status));
821 ttdt_session_join(0, NULL, shell, de->c, 1);
823 XtAppAddInput(context, ttfd, (XtPointer)XtInputReadMask,
824 tttk_Xt_input_handler, de->c->tt_procid);
826 tttk_Xt_input_handler( 0, 0, 0 );
832 reply_cb(Tt_message m,
835 unsigned char *contents,
839 char *client_procID = tt_message_handler(m);
840 if ( debug && (client_procID != NULL) ) {
841 fprintf(stderr, "DEBUG: reply_cb():client_procID = %s\n", client_procID);
842 fprintf(stderr, "DEBUG: reply_cb():message_op = %s\n", tt_message_op(m));
854 /* For now do nothing
858 case TTDT_GET_STATUS:
868 * Handle Edit, Display and Compose requests
876 unsigned char *contents,
888 CmDataList *list = NULL;
889 Dtcm_appointment *appt;
892 de = (DTCM_editor *)clientdata;
894 de->vtype = strdup(tt_message_arg_type(msg, 0));
896 if (diagnosis != TT_OK) {
897 if (tt_message_status(msg) == TT_WRN_START_MESSAGE) {
899 * Error in start message! we may want to exit
900 * here, but for now let toolkit handle error
905 /* Let toolkit handle the error */
909 de->contract_pats = ttdt_message_accept(msg, contract_cb, clientdata,
912 tt_ptype_undeclare(ptype);
914 if ((status = tt_ptr_error(de->contract_pats)) != TT_OK) {
915 fprintf(stderr, "dtcm: load_cb could not accept message: %s\n",
916 tt_status_message(status));
919 tttk_patterns_destroy(de->contract_pats);
923 de->read_only = False;
928 XtSetSensitive(de->attach_button, True);
932 /* for Display only messages, the "Attach"
933 button makes no sense */
936 XtSetSensitive(de->attach_button, True);
938 XtSetSensitive(de->attach_button, False);
939 de->read_only = True;
941 list = CmDataListCreate();
945 * Save data to a file so we can pass it to parse_appt_from_file
948 strcpy(filename, "/tmp/cmXXXXXX");
950 if ((fp = fopen(filename, "w")) == 0) {
951 tttk_message_fail( msg, TT_DESKTOP_ENODATA, 0, 1 );
955 fwrite(contents, 1, len, fp);
957 parse_appt_from_file(de->c->DT_catd, filename,
958 list, de->p, query_user,
959 de->c, DATAVER_ARCHIVE);
961 de->init = buffer_tt;
965 de->file = strdup(file);
966 parse_appt_from_file(de->c->DT_catd, de->file,
967 list, de->p, query_user,
968 de->c, DATAVER_ARCHIVE);
972 if (appt = (Dtcm_appointment *)CmDataListGetData(list, 1)) {
973 dssw_attrs_to_form(de->dssw, appt);
974 rfp_attrs_to_form(de->rfp, appt);
976 for (i = 1; i <= list->count; i++)
977 if (appt = (Dtcm_appointment *)
978 CmDataListGetData(list, i)) {
980 free_appt_struct(&de->orig_appt);
982 de->orig_appt = appt;
984 CmDataListDestroy(list, B_FALSE);
990 de->modified = False;
991 de->dsswFlags = de->rfpFlags = 0;
993 tt_free((caddr_t)contents);
1003 XtPointer client_data,
1004 XtPointer call_data)
1006 Display *display = XtDisplay(w);
1007 DtDndDropCallbackStruct *transfer_info = (DtDndDropCallbackStruct *)call_data;
1015 de = (DTCM_editor *)client_data;
1017 transfer_info->status = DtDND_SUCCESS;
1019 for (i = 0; i < transfer_info->dropData->numItems; i++) {
1020 switch(transfer_info->dropData->protocol) {
1021 case DtDND_FILENAME_TRANSFER:
1022 /* REMIND -- handle multiple filenames */
1023 data = transfer_info->dropData->data.files[0];
1025 de->file = strdup(data);
1028 case DtDND_BUFFER_TRANSFER:
1031 * Save data to a file so we can pass it to drag_load_proc().
1033 strcpy(filename, "/tmp/cmXXXXXX");
1036 if ((fp = fopen(filename, "w")) == 0) {
1037 transfer_info->status = DtDND_FAILURE;
1041 data = transfer_info->dropData->data.buffers[0].bp;
1042 size = transfer_info->dropData->data.buffers[0].size;
1043 fwrite(data, 1, size, fp);
1046 de->file = strdup(filename);
1052 transfer_info->status = DtDND_FAILURE;
1061 de_register_drop_site(
1064 Boolean registerchildren)
1067 XtCallbackRec transfer_cb_rec[] = { {handle_drop_cb, NULL},
1069 Display *display = XtDisplayOfObject(w);
1071 transfer_cb_rec[0].closure = (XtPointer)de;
1073 DtDndVaDropRegister(w, DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER,
1074 XmDROP_COPY | XmDROP_MOVE,
1076 DtNregisterChildren, registerchildren,
1085 main(int argc, char **argv) {
1086 int dssw_loffset, rfp_loffset, start, stop;
1087 Dimension dssw_x, rfp_x;
1090 Boolean btn1_transfer;
1091 Dimension width, longest_dssw_label, longest_rfp_label;
1092 WidgetList children;
1101 de = (DTCM_editor *)ckalloc(sizeof(DTCM_editor));
1105 if (strcasecmp(argv[1], "-h") == 0)
1106 display_command_usage();
1107 else if (argv[1][0] != '-')
1108 de->file = cm_strdup(argv[1]);
1111 XtSetLanguageProc(NULL, NULL, NULL);
1112 _DtEnvControl(DT_ENV_SET); /* set up environment variables */
1114 de->top_level = XtVaAppInitialize(&app,
1115 "Dtcm", NULL, 0, &argc, argv, NULL,
1116 XmNallowShellResize, True,
1117 XmNdeleteResponse, XmDO_NOTHING,
1119 setup_quit_handler(de->top_level, de_quit_handler, (caddr_t)de);
1122 ** First, create a calendar and fill only the stuff we're going to
1125 calendar = (Calendar *)ckalloc(sizeof(Calendar));
1127 de->p = (Props *)ckalloc(sizeof(Props));
1128 de->c->properties = (caddr_t)de->p;
1129 de->c->general = (General*) ckalloc(sizeof(General));
1130 de->c->general->version = DATAVER_ARCHIVE;
1131 de->c->frame = de->top_level;
1132 de->pu = (Props_pu *)ckalloc(sizeof(Props_pu));
1133 de->c->properties_pu = (caddr_t)de->pu;
1136 cal_convert_cmrc(de->p);
1137 if ((start = get_int_prop(de->p, CP_DAYBEGIN)) < 0)
1139 else if (start > 22)
1141 if ((stop = get_int_prop(de->p, CP_DAYEND)) <= start)
1145 set_int_prop(de->p, CP_DAYBEGIN, start);
1146 set_int_prop(de->p, CP_DAYEND, stop);
1147 de->c->calname = cm_strdup(get_char_prop(de->p, CP_DEFAULTCAL));
1148 de->c->DT_catd = catopen(DTCM_CAT, NL_CAT_LOCALE);
1150 /* Open the message catalog for internationalization */
1151 calendar->DT_catd = catopen(DTCM_CAT, NL_CAT_LOCALE);
1153 title = XtNewString(catgets(calendar->DT_catd, 1, 1074,
1154 "Calendar Appointment"));
1155 XtVaSetValues(de->top_level,
1161 ** Okay, now create the form manager and the widgets
1163 de->form = XtVaCreateWidget("form",
1164 xmFormWidgetClass, de->top_level,
1165 XmNautoUnmanage, True,
1169 label_str = XmStringCreateLocalized(catgets(de->c->DT_catd, 1, 846, "Save"));
1170 de->attach_button = XtVaCreateWidget("attach_button",
1171 xmPushButtonGadgetClass, de->form,
1172 XmNlabelString, label_str,
1173 XmNleftAttachment, XmATTACH_POSITION,
1175 XmNrightAttachment, XmATTACH_POSITION,
1176 XmNrightPosition, 2,
1177 XmNbottomAttachment, XmATTACH_FORM,
1178 XmNbottomOffset, 10,
1180 XmStringFree(label_str);
1181 XtAddCallback(de->attach_button, XmNactivateCallback, de_apply_proc, (XtPointer)de);
1183 XtSetSensitive(de->attach_button, False);
1185 label_str = XmStringCreateLocalized(catgets(de->c->DT_catd, 1, 691, "Reset"));
1186 de->reset_button = XtVaCreateWidget("reset_button",
1187 xmPushButtonGadgetClass, de->form,
1188 XmNlabelString, label_str,
1189 XmNleftAttachment, XmATTACH_POSITION,
1191 XmNrightAttachment, XmATTACH_POSITION,
1192 XmNrightPosition, 4,
1193 XmNbottomAttachment, XmATTACH_FORM,
1194 XmNbottomOffset, 10,
1196 XmStringFree(label_str);
1197 XtAddCallback(de->reset_button, XmNactivateCallback, de_reset_proc, de);
1199 create_all_pixmaps(de->pu, de->form);
1202 de->rfp = (RFP *)ckalloc(sizeof(RFP));
1203 build_rfp(de->rfp, de->c, de->form);
1204 XtVaSetValues(de->rfp->rfp_form_mgr,
1205 XmNbottomAttachment, XmATTACH_WIDGET,
1206 XmNbottomWidget, de->attach_button,
1207 XmNbottomOffset, 25,
1208 XmNleftAttachment, XmATTACH_FORM,
1211 XtVaGetValues(de->rfp->rfp_form_mgr,
1212 XmNchildren, &children,
1215 /* We don't want to manage the privacy widgets */
1216 for (i = 0; i < n; i++) {
1217 if ((children[i] == de->rfp->privacy_label) ||
1218 (children[i] == de->rfp->privacy_menu))
1220 widgets[j++] = children[i];
1222 XtManageChildren(widgets, n - 2);
1225 * Add a drag source icon inside the dssw, lower right
1227 xmstr = XmStringCreateLocalized(
1228 catgets(de->c->DT_catd, 1, 627, "Drag Appt"));
1229 de->drag_source = XtVaCreateWidget("drag_source",
1230 dtIconGadgetClass, de->form,
1231 XmNpixmapPosition, XmPIXMAP_TOP,
1232 XmNstringPosition, XmSTRING_BOTTOM,
1233 XmNalignment, XmALIGNMENT_CENTER,
1235 XmNbottomAttachment, XmATTACH_WIDGET,
1236 XmNbottomWidget, de->attach_button,
1237 XmNbottomOffset, 25,
1238 XmNleftAttachment, XmATTACH_WIDGET,
1239 XmNleftWidget, de->rfp->rfp_form_mgr,
1240 XmNrightAttachment, XmATTACH_FORM,
1241 XmNtraversalOn, False,
1243 XmStringFree(xmstr);
1245 XtAddEventHandler(XtParent(de->drag_source), Button1MotionMask, False,
1246 (XtEventHandler)EditApptDragMotionHandler, (XtPointer) de);
1248 XtVaGetValues((Widget)XmGetXmDisplay(XtDisplay(de->form)),
1249 "enableBtn1Transfer", &btn1_transfer,
1252 /* btn1_transfer is a tri-state variable - see 1195846 */
1253 if ((Boolean)btn1_transfer != True)
1254 XtAddEventHandler(XtParent(de->drag_source),
1255 Button2MotionMask, False,
1256 (XtEventHandler)EditApptDragMotionHandler,
1260 if (de->pu->drag_icon_xbm)
1261 XtVaSetValues(de->drag_source,
1262 XmNpixmap, de->pu->drag_icon_xbm,
1266 de->dssw = (DSSW *)ckalloc(sizeof(DSSW));
1267 build_dssw(de->dssw, de->c, de->form, True, True);
1268 XtVaSetValues(de->dssw->dssw_form_mgr,
1269 XmNtopAttachment, XmATTACH_FORM,
1271 XmNbottomAttachment, XmATTACH_WIDGET,
1272 XmNbottomWidget, de->rfp->rfp_form_mgr,
1273 XmNbottomOffset, 15,
1274 XmNleftAttachment, XmATTACH_FORM,
1277 ManageChildren(de->dssw->dssw_form_mgr);
1279 /* set up callback to detect whether the appointment
1280 definition has been modified */
1282 XtAddCallback(de->dssw->start_text, XmNvalueChangedCallback, de_mark_change, de);
1283 XtAddCallback(de->dssw->start_am, XmNvalueChangedCallback, de_mark_change, de);
1284 XtAddCallback(de->dssw->start_pm, XmNvalueChangedCallback, de_mark_change, de);
1285 XtAddCallback(de->dssw->stop_text, XmNvalueChangedCallback, de_mark_change, de);
1286 XtAddCallback(de->dssw->stop_am, XmNvalueChangedCallback, de_mark_change, de);
1287 XtAddCallback(de->dssw->stop_pm, XmNvalueChangedCallback, de_mark_change, de);
1288 XtAddCallback(de->dssw->what_text, XmNvalueChangedCallback, de_mark_change, de);
1289 XtAddCallback(de->rfp->repeat_menu, XmNselectionCallback, de_mark_change, de);
1290 XtAddCallback(de->rfp->for_menu, XmNselectionCallback, de_mark_change, de);
1292 ManageChildren(de->form);
1293 XtManageChild(de->form);
1294 XtRealizeWidget(de->top_level);
1297 ** Do some monkeying to compensate for Motif's pitiful form managers
1298 XtVaGetValues(de->dssw->start_menu, XmNx, &dssw_x,
1299 XmNleftOffset, &dssw_loffset,
1301 XtVaGetValues(de->rfp->repeat_menu, XmNx, &rfp_x,
1302 XmNleftOffset, &rfp_loffset,
1306 XtVaSetValues(de->rfp->rfp_form_mgr,
1307 XmNleftOffset, rfp_loffset + (dssw_x - rfp_x),
1309 else if (rfp_x > dssw_x)
1310 XtVaSetValues(de->dssw->dssw_form_mgr,
1311 XmNleftOffset, dssw_loffset + (rfp_x - dssw_x),
1315 /* Don't need these any more.
1316 XtVaGetValues(de->dssw->date_label, XmNwidth, &longest_dssw_label, NULL);
1318 XtVaGetValues(de->dssw->start_label, XmNwidth, &width, NULL);
1319 if (width > longest_dssw_label)
1320 longest_dssw_label = width;
1322 XtVaGetValues(de->dssw->stop_label, XmNwidth, &width, NULL);
1323 if (width > longest_dssw_label)
1324 longest_dssw_label = width;
1326 XtVaGetValues(de->dssw->what_label, XmNwidth, &width, NULL);
1327 if (width > longest_dssw_label)
1328 longest_dssw_label = width;
1330 XtVaGetValues(de->rfp->frequency_label, XmNwidth, &longest_rfp_label, NULL);
1331 XtVaGetValues(de->rfp->for_label, XmNwidth, &width, NULL);
1332 if (width > longest_rfp_label)
1333 longest_rfp_label = width;
1335 XtVaSetValues(de->dssw->dssw_form_mgr,
1336 XmNleftOffset, longest_rfp_label - longest_dssw_label,
1340 de_set_defaults(de);
1342 de_register_drop_site(de, de->form, True);
1343 de_register_drop_site(de, de->dssw->dssw_form_mgr, False);
1344 de_register_drop_site(de, de->rfp->rfp_form_mgr, False);
1346 XmProcessTraversal(de->dssw->what_text, XmTRAVERSE_CURRENT);
1347 XtVaSetValues(de->form, XmNinitialFocus, de->dssw->what_text, NULL);
1350 status = cmtt_init("AppointmentEditor", de, app, calendar->frame);
1351 if (TT_OK != status) {
1353 errfmt = catgets(calendar->DT_catd, 2, 2,
1354 "Could not connect to ToolTalk:\n%s\n");
1355 DieFromToolTalkError( de, errfmt, status );