1 /* $TOG: dtcm_editor.c /main/14 1999/09/20 10:32:17 mgreess $ */
3 * (c) Copyright 1993, 1994 Hewlett-Packard Company
4 * (c) Copyright 1993, 1994 International Business Machines Corp.
5 * (c) Copyright 1993, 1994 Novell, Inc.
6 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
14 #include <Dt/EnvControlP.h>
17 #include <Dt/UserMsg.h>
30 #if !defined(NL_CAT_LOCALE)
31 #define NL_CAT_LOCALE 0
35 static Tt_message load_cb();
37 static const char *ptype = "Dt_AppointmentEditor";
39 typedef enum {no_tt, file_tt, buffer_tt} Dtcm_editor_start;
41 /* Absolute value macro */
43 #define ABS(x) (((x) > 0) ? (x) : (-(x)))
48 #include "drag_mask_xbm"
51 ** Structure for stand-alone editor
59 Dtcm_editor_start init;
61 Tt_pattern *contract_pats;
70 Dtcm_appointment *orig_appt;
82 static void de_apply_proc(Widget , XtPointer , XtPointer );
85 ** Hate like hell to make this global, but I can find no way to get at it
86 ** when I need it in other methods ...
88 ** Also, help uses a global reference to calendar which hoses us ...
94 de_mark_change(Widget w, XtPointer data, XtPointer cbs) {
96 DTCM_editor *de = (DTCM_editor *)data;
100 if ((w == de->dssw->start_text) ||
101 (w == de->dssw->start_am) ||
102 (w == de->dssw->start_pm) ||
103 (w == de->dssw->stop_text) ||
104 (w == de->dssw->stop_am) ||
105 (w == de->dssw->stop_pm))
108 if (w == de->rfp->repeat_menu)
113 merge_old_values(Dtcm_appointment *original, Dtcm_appointment *new) {
115 /* This routine takes in the original appointment structure
116 from the edited appointment, and merges back in any attributes
117 that aren't controlled by our editor, so that when the
118 appointment is written back out to the buffering agent, those
119 attributes are not lost. */
121 int source_count, dest_count, new_attrs;
122 int dest_attr_num = new->count;
125 if (original == NULL)
128 /* We need to see how much larger the attribute array needs to
129 get. For each of the guys in the source attribute array,
130 we need to look and see if it's already a member of the
131 destination array. Those that don't exist, we count, and
134 for (source_count = 0, new_attrs = 0; source_count < original->count; source_count++) {
136 for (dest_count = 0; dest_count < dest_attr_num; dest_count++) {
137 if (original->attrs[source_count].name && new->attrs[dest_count].name) {
138 if (strcmp(original->attrs[source_count].name, new->attrs[dest_count].name) == 0) {
152 /* realloc the attrs array to be large enough to accomodate the new
155 new->attrs = (CSA_attribute *) realloc(new->attrs, (dest_attr_num + new_attrs) * sizeof(CSA_attribute));
157 /* Copy in the new attribute values */
158 for (source_count = 0; source_count < original->count; source_count++) {
160 for (dest_count = 0; dest_count < new->count; dest_count++) {
161 if (original->attrs[source_count].name && new->attrs[dest_count].name) {
162 if (strcmp(original->attrs[source_count].name, new->attrs[dest_count].name) == 0) {
171 new->attrs[new->count] = original->attrs[source_count];
176 /* reset the appointment links, as the old ones have been
177 thrashed by reallocing the attribute array. */
183 CreateDragSourceIcon(
190 int pixmapX, pixmapY;
191 unsigned int pixmapWidth, pixmapHeight, pixmapBorder, pixmapDepth;
195 XGetGeometry (XtDisplayOfObject(widget), pixmap, &rootWindow,
196 &pixmapX, &pixmapY, &pixmapWidth, &pixmapHeight,
197 &pixmapBorder, &pixmapDepth);
199 XtSetArg(args[nn], XmNwidth, pixmapWidth); nn++;
200 XtSetArg(args[nn], XmNheight, pixmapHeight); nn++;
201 XtSetArg(args[nn], XmNmaxWidth, pixmapWidth); nn++;
202 XtSetArg(args[nn], XmNmaxHeight, pixmapHeight); nn++;
203 XtSetArg(args[nn], XmNpixmap, pixmap); nn++;
204 XtSetArg(args[nn], XmNmask, mask); nn++;
205 XtSetArg(args[nn], XmNdepth, pixmapDepth); nn++;
206 dragIcon = XmCreateDragIcon(widget, "sourceIcon", args, nn);
214 * Returns a new IconInfo structure with bitmap, mask, width, height,
215 * icon type and name.
218 GetIcon(DTCM_editor *de)
221 Display *display = XtDisplay(calendar->frame);
222 Window window = XtWindow(calendar->frame);
223 unsigned char *bitmapData, *bitmapMask;
225 if (de->drag_bitmap == NULL) {
226 de->drag_bitmap = XCreateBitmapFromData(display,
227 window, (char *) drag_xbm_bits,
228 drag_xbm_width, drag_xbm_height);
229 if (de->drag_bitmap == NULL) {
231 printf(catgets(calendar->DT_catd, 1, 237, "XCreateBitmapFromData() failed for bitmap.\n"));
235 if (de->drag_mask == NULL) {
236 de->drag_mask = XCreateBitmapFromData(display,
237 window, (char *) drag_mask_xbm_bits,
238 drag_mask_xbm_width, drag_mask_xbm_height);
239 if (de->drag_mask == NULL) {
240 printf(catgets(calendar->DT_catd, 1, 238, "XCreateBitmapFromData() failed for mask.\n"));
250 * Resets drag state to indicate the drag is over. Free memory allocated
256 XtPointer clientData,
259 DragContext *context = (DragContext *) clientData;
264 if (context->editor_type == StandAloneEditor)
265 ((DTCM_editor *) context->editor)->doing_drag = False;
276 * Fills in data object with calendar appointment string based on which
277 * appointment in the list was under the pointer when the drag started.
282 XtPointer clientData,
285 DtDndConvertCallbackStruct *convertInfo
286 = (DtDndConvertCallbackStruct*)callData;
287 DtDndBuffer *data = &(convertInfo->dragData->data.buffers[0]);
288 DragContext *context = (DragContext *)clientData;
289 Display *display = XtDisplay(dragContext);
291 = XmInternAtom(display, "CalendarAppointment", False);
292 Calendar *c = context->calendar;
294 if (convertInfo->reason != DtCR_DND_CONVERT_DATA)
297 /* REMIND: Need to check convertInfo->reason, handle DELETE, etc */
299 data->bp = XtNewString(context->data);
300 data->size = strlen(data->bp);
301 data->name = XtNewString(catgets(c->DT_catd, 1, 236, "CalendarAppointment"));
305 StandaloneApptDragStart(
309 EditorType editor_type)
311 static XtCallbackRec convertCBRec[] = { {ApptConvertCB, NULL},
313 static XtCallbackRec dragFinishCBRec[] = { {DragFinishCB, NULL},
316 Display *display = XtDisplay(widget);
317 int itemCount, selectedPos;
318 DragContext *context = calloc(sizeof(DragContext), 1);
320 Dtcm_appointment *appt;
323 int preDsswFlags, preRfpFlags;
325 /* Convert appointment into string. If not successful, don't start drag. */
326 appt = allocate_appt_struct(appt_write, DATAVER_ARCHIVE, NULL);
327 load_appt_defaults(appt, de->p);
328 preDsswFlags = de->dsswFlags;
329 preRfpFlags = de->rfpFlags;
330 if (!dssw_form_flags_to_appt(de->dssw, appt, de->c->calname,
331 now(), &de->dsswFlags) ||
332 !rfp_form_flags_to_appt(de->rfp, appt, de->c->calname,
334 (preDsswFlags != de->dsswFlags) ||
335 (preRfpFlags != de->rfpFlags))
337 de->doing_drag = False;
338 free_appt_struct(&appt);
343 /* save the old count of attributes so that when this appointment
344 gets freed, we can prevent the added attribute references from
347 old_attr_count = appt->count;
348 merge_old_values(de->orig_appt, appt);
349 apptstr = parse_attrs_to_string(appt, de->p,
350 attrs_to_string(appt->attrs, appt->count));
351 appt->count = old_attr_count;
352 free_appt_struct(&appt);
354 context->data = apptstr;
355 context->calendar = c;
356 context->editor_type = editor_type;
357 context->editor = (caddr_t) de;
361 convertCBRec[0].closure = (XtPointer)context;
362 dragFinishCBRec[0].closure = (XtPointer)context;
364 if (de->drag_icon == NULL) {
365 de->drag_icon = CreateDragSourceIcon(widget, de->drag_bitmap, de->drag_mask);
368 if (DtDndVaDragStart(widget, event, DtDND_BUFFER_TRANSFER, 1,
370 convertCBRec, dragFinishCBRec,
371 DtNsourceIcon, de->drag_icon,
375 printf(catgets(c->DT_catd, 1, 239, "DragStart returned NULL.\n"));
382 * Determine if the pointer has moved beyond the drag threshold while button 1
383 * was being held down.
386 EditApptDragMotionHandler(
387 Widget dragInitiator,
388 XtPointer clientData,
392 DTCM_editor *de = (DTCM_editor *) clientData;
394 Dimension source_height, source_width;
395 Position source_x, source_y;
397 if (!de->doing_drag) {
399 /* check to see if the iniital value was within the
400 bounds for the drag source icon. */
402 XtVaGetValues(de->drag_source,
405 XmNheight, &source_height,
406 XmNwidth, &source_width,
409 if ((event->xmotion.x < source_x) ||
410 (event->xmotion.y < source_y) ||
411 (event->xmotion.x > (int) (source_x + source_width)) ||
412 (event->xmotion.y > (int) (source_y + source_height)))
417 * If the drag is just starting, set initial button down coords
419 if (de->initialX == -1 && de->initialY == -1) {
420 de->initialX = event->xmotion.x;
421 de->initialY = event->xmotion.y;
424 * Find out how far pointer has moved since button press
426 diffX = de->initialX - event->xmotion.x;
427 diffY = de->initialY - event->xmotion.y;
429 if ((ABS(diffX) >= DRAG_THRESHOLD) ||
430 (ABS(diffY) >= DRAG_THRESHOLD)) {
431 de->doing_drag = True;
432 StandaloneApptDragStart(dragInitiator, event, de, StandAloneEditor);
443 de_quit_handler(Widget w, XtPointer cdata, XtPointer data) {
444 DTCM_editor *de = (DTCM_editor *)cdata;
447 if (de->modified == True) {
448 char *title = XtNewString(catgets(de->c->DT_catd, 1, 1008, "Calendar Appointment : Help"));
449 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."));
450 char *ident1 = XtNewString(catgets(de->c->DT_catd, 1, 452, "Save"));
451 char *ident2 = XtNewString(catgets(de->c->DT_catd, 1, 700, "Discard"));
452 char *ident3 = XtNewString(catgets(de->c->DT_catd, 1, 923, "Cancel"));
453 answer = dialog_popup(de->top_level,
456 BUTTON_IDENT, 1, ident1,
457 BUTTON_IDENT, 2, ident2,
458 BUTTON_IDENT, 3, ident3,
459 DIALOG_IMAGE, de->pu->xm_warning_pixmap,
468 de_apply_proc(NULL, (XtPointer)de, NULL);
469 XtPopdown(de->top_level);
471 else if (answer == 2) {
473 tttk_message_fail(de->contract, TT_DESKTOP_ECANCELED, NULL, True);
474 XtPopdown(de->top_level);
476 else if (answer == 3) {
483 tttk_message_fail(de->contract, TT_DESKTOP_ECANCELED, NULL, True);
484 XtPopdown(de->top_level);
499 load_from_file(DTCM_editor *de) {
501 CmDataList *list = NULL;
502 Dtcm_appointment *appt;
504 list = CmDataListCreate();
505 parse_appt_from_file(de->c->DT_catd, de->file, list, de->p,
506 query_user, de->c, DATAVER_ARCHIVE);
507 if (appt = (Dtcm_appointment *)CmDataListGetData(list, 1)) {
508 dssw_attrs_to_form(de->dssw, appt);
509 rfp_attrs_to_form(de->rfp, appt);
511 for (i = 1; i <= list->count; i++)
512 if (appt = (Dtcm_appointment *)
513 CmDataListGetData(list, i)) {
515 free_appt_struct(&de->orig_appt);
517 de->orig_appt = appt;
519 CmDataListDestroy(list, B_FALSE);
520 de->dsswFlags = de->rfpFlags = 0;
524 de_set_defaults(DTCM_editor *de) {
526 if (de->file && (access(de->file, R_OK) == 0)) {
529 set_dssw_defaults(de->dssw, now(), True);
530 set_rfp_defaults(de->rfp);
531 de->dsswFlags = de->rfpFlags = 0;
534 de->modified = False;
538 de_apply_proc(Widget w, XtPointer client_data, XtPointer data) {
541 DTCM_editor *de = (DTCM_editor *)client_data;
542 Dtcm_appointment *appt;
544 Display *dpy = XtDisplayOfObject(w);
546 appt = allocate_appt_struct(appt_write,
549 load_appt_defaults(appt, de->p);
551 dssw_form_to_appt(de->dssw, appt, de->c->calname, now());
553 rfp_form_to_appt(de->rfp, appt, de->c->calname);
555 /* save the old count of attributes so that when this appointment
556 gets freed, we can prevent the added attribute references from
559 old_attr_count = appt->count;
560 merge_old_values(de->orig_appt, appt);
561 str = parse_attrs_to_string(appt, de->p, attrs_to_string(appt->attrs, appt->count));
562 appt->count = old_attr_count;
563 de->modified = False;
568 /* we need to distinguish between whether the data is being
569 saved as part of application termination, or as part of
570 pressing the "Apply" button. If it's is app termination,
571 we need to call ttmedia_load_reply, and if it is an
572 intermediate save, we are supposed to call ttmedia_Deposit.
573 Hmmph. We also need to be pretty clear about saving it back
574 in the same fashion is was supplied. If it came as part of
575 a buffer, it needs to go back that way. */
578 /* The first case is from application exit */
582 /* if it was a file transfer, we should write out the
583 file, and set the buffer to null. If it came from
584 a buffer, we don't bother to write out the file. */
587 ttmedia_load_reply(de->contract, NULL, 0, True);
590 if (de->init == file_tt) {
591 fp = fopen(de->file, "w");
598 fprintf(fp, "%s", str);
600 ttmedia_load_reply(de->contract, NULL, 0, True);
603 ttmedia_load_reply(de->contract, (unsigned char *) str, strlen(str), True);
609 /* This case is from the "Apply" button. In this case,
610 if the app was started normally (no tt), then we
611 just write out the file. If it was from tt, we then
612 use ttmedia_Deposit to send the data back. */
614 if ((de->init == no_tt) || (de->init == file_tt)) {
615 fp = fopen(de->file, "w");
622 fprintf(fp, "%s", str);
625 if (de->init == file_tt)
626 ttmedia_Deposit(de->contract,
636 ttmedia_Deposit(de->contract,
639 (const unsigned char *)str,
649 free_appt_struct(&appt);
653 de_reset_proc(Widget w, XtPointer client_data, XtPointer data) {
654 DTCM_editor *de = (DTCM_editor *)client_data;
657 de->dsswFlags = de->rfpFlags = 0;
661 display_command_usage() {
662 fprintf(stderr, "\ndtcm_editor Usage: dtcm [filename]\n\n");
667 OKCB (Widget dialog, XtPointer client_data, XtPointer call_data)
669 XtUnmanageChild((Widget) client_data);
673 DieFromToolTalkError(DTCM_editor *de, char *errfmt, Tt_status status)
676 Widget dialog, dialogShell;
677 char *errmsg, *statmsg, *title;
678 XmString xms_errmsg, xms_ok, xms_title;
681 if (! tt_is_err(status)) return;
683 statmsg = tt_status_message(status);
684 errmsg = XtMalloc(strlen(errfmt) + strlen(statmsg) + 2);
685 sprintf(errmsg, errfmt, statmsg);
687 xms_ok = XmStringCreateLocalized(catgets(de->c->DT_catd, 2, 3, "OK"));
688 xms_errmsg = XmStringCreateLocalized(errmsg);
689 xms_title = XmStringCreateLocalized(catgets(de->c->DT_catd, 2, 4,
690 "Calendar : Appointment Editor - Warning"));
693 XtSetArg(args[n], XmNautoUnmanage, False); n++;
694 XtSetArg(args[n], XmNokLabelString, xms_ok); n++;
695 XtSetArg(args[n], XmNdialogTitle, xms_title); n++;
696 XtSetArg(args[n], XmNmessageString, xms_errmsg); n++;
697 XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
698 XtSetArg(args[n], XmNdialogType, XmDIALOG_WARNING); n++;
700 dialog = XmCreateMessageDialog(de->top_level, "IconEditorError", args, n);
701 XtAddCallback(dialog, XmNokCallback, OKCB, (XtPointer) dialog);
702 XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
703 XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
706 * Disable the frame menu from dialog since we don't want the user
707 * to be able to close dialogs with the frame menu
709 dialogShell = XtParent(dialog);
711 XtSetArg(args[n], XmNmwmDecorations, MWM_DECOR_ALL | MWM_DECOR_MENU); n++;
712 XtSetValues(dialogShell, args, n);
713 XtManageChild(dialog);
714 XtRealizeWidget(dialogShell);
716 _DtSimpleError("Dtcm", DtWarning, NULL, errmsg);
719 XmStringFree(xms_ok);
720 XmStringFree(xms_errmsg);
721 XmStringFree(xms_title);
727 * Initialize tooltalk. Can be called multiple times: the first call
728 * initializes tooltalk, subsequent calls are no-ops.
731 * -1 Error. Tooltalk not initialized
732 * 0 Tooltalk already initialized
733 * 1 Tooltalk succussfully intialized
740 XtAppContext context,
744 static int initialized = 0;
750 if (de->c->tt_procid) {
754 ttenv = (char *)getenv("TT_SESSION");
755 if (!ttenv || strlen(ttenv) == 0) {
756 session = tt_X_session(XDisplayString(XtDisplay(shell)));
757 tt_default_session_set(session);
761 de->c->tt_procid = ttdt_open(&ttfd, toolname, "SunSoft", "%I", 1);
762 status = tt_ptr_error(de->c->tt_procid);
763 if (tt_is_err(status)) {
764 de->c->tt_procid = NULL;
769 * Declare our ptype, and register the callback to handle
770 * Edit/Display/Compose requests
772 status = ttmedia_ptype_declare(ptype, 0, load_cb, (void *)de, 1);
774 if (tt_is_err(status)) {
775 fprintf(stderr, "cmtt_init could not declare ptype: %s\n",
776 tt_status_message(status));
780 status = ttmedia_ptype_declare(ptype, 1000, load_cb, (void *)de, 0);
782 if (tt_is_err(status)) {
783 fprintf(stderr, "cmtt_init could not declare ptype: %s\n",
784 tt_status_message(status));
787 ttdt_session_join(0, NULL, shell, de->c, 1);
789 XtAppAddInput(context, ttfd, (XtPointer)XtInputReadMask,
790 tttk_Xt_input_handler, de->c->tt_procid);
792 tttk_Xt_input_handler( 0, 0, 0 );
798 reply_cb(Tt_message m,
801 unsigned char *contents,
805 char *client_procID = tt_message_handler(m);
806 if ( debug && (client_procID != NULL) ) {
807 fprintf(stderr, "DEBUG: reply_cb():client_procID = %s\n", client_procID);
808 fprintf(stderr, "DEBUG: reply_cb():message_op = %s\n", tt_message_op(m));
820 /* For now do nothing
824 case TTDT_GET_STATUS:
834 * Handle Edit, Display and Compose requests
842 unsigned char *contents,
854 CmDataList *list = NULL;
855 Dtcm_appointment *appt;
858 de = (DTCM_editor *)clientdata;
860 de->vtype = strdup(tt_message_arg_type(msg, 0));
862 if (diagnosis != TT_OK) {
863 if (tt_message_status(msg) == TT_WRN_START_MESSAGE) {
865 * Error in start message! we may want to exit
866 * here, but for now let toolkit handle error
871 /* Let toolkit handle the error */
875 de->contract_pats = ttdt_message_accept(msg, contract_cb, clientdata,
878 tt_ptype_undeclare(ptype);
880 if ((status = tt_ptr_error(de->contract_pats)) != TT_OK) {
881 fprintf(stderr, "dtcm: load_cb could not accept message: %s\n",
882 tt_status_message(status));
885 tttk_patterns_destroy(de->contract_pats);
889 de->read_only = False;
894 XtSetSensitive(de->attach_button, True);
898 /* for Display only messages, the "Attach"
899 button makes no sense */
902 XtSetSensitive(de->attach_button, True);
904 XtSetSensitive(de->attach_button, False);
905 de->read_only = True;
907 list = CmDataListCreate();
911 * Save data to a file so we can pass it to parse_appt_from_file
914 strcpy(filename, "/tmp/cmXXXXXX");
916 if ((fp = fopen(filename, "w")) == 0) {
917 tttk_message_fail( msg, TT_DESKTOP_ENODATA, 0, 1 );
921 fwrite(contents, 1, len, fp);
923 parse_appt_from_file(de->c->DT_catd, filename,
924 list, de->p, query_user,
925 de->c, DATAVER_ARCHIVE);
927 de->init = buffer_tt;
931 de->file = strdup(file);
932 parse_appt_from_file(de->c->DT_catd, de->file,
933 list, de->p, query_user,
934 de->c, DATAVER_ARCHIVE);
938 if (appt = (Dtcm_appointment *)CmDataListGetData(list, 1)) {
939 dssw_attrs_to_form(de->dssw, appt);
940 rfp_attrs_to_form(de->rfp, appt);
942 for (i = 1; i <= list->count; i++)
943 if (appt = (Dtcm_appointment *)
944 CmDataListGetData(list, i)) {
946 free_appt_struct(&de->orig_appt);
948 de->orig_appt = appt;
950 CmDataListDestroy(list, B_FALSE);
956 de->modified = False;
957 de->dsswFlags = de->rfpFlags = 0;
959 tt_free((caddr_t)contents);
969 XtPointer client_data,
972 Display *display = XtDisplay(w);
973 DtDndDropCallbackStruct *transfer_info = (DtDndDropCallbackStruct *)call_data;
981 de = (DTCM_editor *)client_data;
983 transfer_info->status = DtDND_SUCCESS;
985 for (i = 0; i < transfer_info->dropData->numItems; i++) {
986 switch(transfer_info->dropData->protocol) {
987 case DtDND_FILENAME_TRANSFER:
988 /* REMIND -- handle multiple filenames */
989 data = transfer_info->dropData->data.files[0];
991 de->file = strdup(data);
994 case DtDND_BUFFER_TRANSFER:
997 * Save data to a file so we can pass it to drag_load_proc().
999 strcpy(filename, "/tmp/cmXXXXXX");
1002 if ((fp = fopen(filename, "w")) == 0) {
1003 transfer_info->status = DtDND_FAILURE;
1007 data = transfer_info->dropData->data.buffers[0].bp;
1008 size = transfer_info->dropData->data.buffers[0].size;
1009 fwrite(data, 1, size, fp);
1012 de->file = strdup(filename);
1018 transfer_info->status = DtDND_FAILURE;
1027 de_register_drop_site(
1030 Boolean registerchildren)
1033 XtCallbackRec transfer_cb_rec[] = { {handle_drop_cb, NULL},
1035 Display *display = XtDisplayOfObject(w);
1037 transfer_cb_rec[0].closure = (XtPointer)de;
1039 DtDndVaDropRegister(w, DtDND_FILENAME_TRANSFER | DtDND_BUFFER_TRANSFER,
1040 XmDROP_COPY | XmDROP_MOVE,
1042 DtNregisterChildren, registerchildren,
1051 main(int argc, char **argv) {
1052 int dssw_loffset, rfp_loffset, start, stop;
1053 Dimension dssw_x, rfp_x;
1056 Boolean btn1_transfer;
1057 Dimension width, longest_dssw_label, longest_rfp_label;
1058 WidgetList children;
1067 de = (DTCM_editor *)ckalloc(sizeof(DTCM_editor));
1071 if (strcasecmp(argv[1], "-h") == 0)
1072 display_command_usage();
1073 else if (argv[1][0] != '-')
1074 de->file = cm_strdup(argv[1]);
1077 XtSetLanguageProc(NULL, NULL, NULL);
1078 _DtEnvControl(DT_ENV_SET); /* set up environment variables */
1080 de->top_level = XtVaAppInitialize(&app,
1081 "Dtcm", NULL, 0, &argc, argv, NULL,
1082 XmNallowShellResize, True,
1083 XmNdeleteResponse, XmDO_NOTHING,
1085 setup_quit_handler(de->top_level, de_quit_handler, (caddr_t)de);
1088 ** First, create a calendar and fill only the stuff we're going to
1091 calendar = (Calendar *)ckalloc(sizeof(Calendar));
1093 de->p = (Props *)ckalloc(sizeof(Props));
1094 de->c->properties = (caddr_t)de->p;
1095 de->c->general = (General*) ckalloc(sizeof(General));
1096 de->c->general->version = DATAVER_ARCHIVE;
1097 de->c->frame = de->top_level;
1098 de->pu = (Props_pu *)ckalloc(sizeof(Props_pu));
1099 de->c->properties_pu = (caddr_t)de->pu;
1102 cal_convert_cmrc(de->p);
1103 if ((start = get_int_prop(de->p, CP_DAYBEGIN)) < 0)
1105 else if (start > 22)
1107 if ((stop = get_int_prop(de->p, CP_DAYEND)) <= start)
1111 set_int_prop(de->p, CP_DAYBEGIN, start);
1112 set_int_prop(de->p, CP_DAYEND, stop);
1113 de->c->calname = cm_strdup(get_char_prop(de->p, CP_DEFAULTCAL));
1114 de->c->DT_catd = catopen(DTCM_CAT, NL_CAT_LOCALE);
1116 /* Open the message catalog for internationalization */
1117 calendar->DT_catd = catopen(DTCM_CAT, NL_CAT_LOCALE);
1119 title = XtNewString(catgets(calendar->DT_catd, 1, 1074,
1120 "Calendar Appointment"));
1121 XtVaSetValues(de->top_level,
1127 ** Okay, now create the form manager and the widgets
1129 de->form = XtVaCreateWidget("form",
1130 xmFormWidgetClass, de->top_level,
1131 XmNautoUnmanage, True,
1135 label_str = XmStringCreateLocalized(catgets(de->c->DT_catd, 1, 846, "Save"));
1136 de->attach_button = XtVaCreateWidget("attach_button",
1137 xmPushButtonGadgetClass, de->form,
1138 XmNlabelString, label_str,
1139 XmNleftAttachment, XmATTACH_POSITION,
1141 XmNrightAttachment, XmATTACH_POSITION,
1142 XmNrightPosition, 2,
1143 XmNbottomAttachment, XmATTACH_FORM,
1144 XmNbottomOffset, 10,
1146 XmStringFree(label_str);
1147 XtAddCallback(de->attach_button, XmNactivateCallback, de_apply_proc, (XtPointer)de);
1149 XtSetSensitive(de->attach_button, False);
1151 label_str = XmStringCreateLocalized(catgets(de->c->DT_catd, 1, 691, "Reset"));
1152 de->reset_button = XtVaCreateWidget("reset_button",
1153 xmPushButtonGadgetClass, de->form,
1154 XmNlabelString, label_str,
1155 XmNleftAttachment, XmATTACH_POSITION,
1157 XmNrightAttachment, XmATTACH_POSITION,
1158 XmNrightPosition, 4,
1159 XmNbottomAttachment, XmATTACH_FORM,
1160 XmNbottomOffset, 10,
1162 XmStringFree(label_str);
1163 XtAddCallback(de->reset_button, XmNactivateCallback, de_reset_proc, de);
1165 create_all_pixmaps(de->pu, de->form);
1168 de->rfp = (RFP *)ckalloc(sizeof(RFP));
1169 build_rfp(de->rfp, de->c, de->form);
1170 XtVaSetValues(de->rfp->rfp_form_mgr,
1171 XmNbottomAttachment, XmATTACH_WIDGET,
1172 XmNbottomWidget, de->attach_button,
1173 XmNbottomOffset, 25,
1174 XmNleftAttachment, XmATTACH_FORM,
1177 XtVaGetValues(de->rfp->rfp_form_mgr,
1178 XmNchildren, &children,
1181 /* We don't want to manage the privacy widgets */
1182 for (i = 0; i < n; i++) {
1183 if ((children[i] == de->rfp->privacy_label) ||
1184 (children[i] == de->rfp->privacy_menu))
1186 widgets[j++] = children[i];
1188 XtManageChildren(widgets, n - 2);
1191 * Add a drag source icon inside the dssw, lower right
1193 xmstr = XmStringCreateLocalized(
1194 catgets(de->c->DT_catd, 1, 627, "Drag Appt"));
1195 de->drag_source = XtVaCreateWidget("drag_source",
1196 dtIconGadgetClass, de->form,
1197 XmNpixmapPosition, XmPIXMAP_TOP,
1198 XmNstringPosition, XmSTRING_BOTTOM,
1199 XmNalignment, XmALIGNMENT_CENTER,
1201 XmNbottomAttachment, XmATTACH_WIDGET,
1202 XmNbottomWidget, de->attach_button,
1203 XmNbottomOffset, 25,
1204 XmNleftAttachment, XmATTACH_WIDGET,
1205 XmNleftWidget, de->rfp->rfp_form_mgr,
1206 XmNrightAttachment, XmATTACH_FORM,
1207 XmNtraversalOn, False,
1209 XmStringFree(xmstr);
1211 XtAddEventHandler(XtParent(de->drag_source), Button1MotionMask, False,
1212 (XtEventHandler)EditApptDragMotionHandler, (XtPointer) de);
1214 XtVaGetValues((Widget)XmGetXmDisplay(XtDisplay(de->form)),
1215 "enableBtn1Transfer", &btn1_transfer,
1218 /* btn1_transfer is a tri-state variable - see 1195846 */
1219 if ((Boolean)btn1_transfer != True)
1220 XtAddEventHandler(XtParent(de->drag_source),
1221 Button2MotionMask, False,
1222 (XtEventHandler)EditApptDragMotionHandler,
1226 if (de->pu->drag_icon_xbm)
1227 XtVaSetValues(de->drag_source,
1228 XmNpixmap, de->pu->drag_icon_xbm,
1232 de->dssw = (DSSW *)ckalloc(sizeof(DSSW));
1233 build_dssw(de->dssw, de->c, de->form, True, True);
1234 XtVaSetValues(de->dssw->dssw_form_mgr,
1235 XmNtopAttachment, XmATTACH_FORM,
1237 XmNbottomAttachment, XmATTACH_WIDGET,
1238 XmNbottomWidget, de->rfp->rfp_form_mgr,
1239 XmNbottomOffset, 15,
1240 XmNleftAttachment, XmATTACH_FORM,
1243 ManageChildren(de->dssw->dssw_form_mgr);
1245 /* set up callback to detect whether the appointment
1246 definition has been modified */
1248 XtAddCallback(de->dssw->start_text, XmNvalueChangedCallback, de_mark_change, de);
1249 XtAddCallback(de->dssw->start_am, XmNvalueChangedCallback, de_mark_change, de);
1250 XtAddCallback(de->dssw->start_pm, XmNvalueChangedCallback, de_mark_change, de);
1251 XtAddCallback(de->dssw->stop_text, XmNvalueChangedCallback, de_mark_change, de);
1252 XtAddCallback(de->dssw->stop_am, XmNvalueChangedCallback, de_mark_change, de);
1253 XtAddCallback(de->dssw->stop_pm, XmNvalueChangedCallback, de_mark_change, de);
1254 XtAddCallback(de->dssw->what_text, XmNvalueChangedCallback, de_mark_change, de);
1255 XtAddCallback(de->rfp->repeat_menu, XmNselectionCallback, de_mark_change, de);
1256 XtAddCallback(de->rfp->for_menu, XmNselectionCallback, de_mark_change, de);
1258 ManageChildren(de->form);
1259 XtManageChild(de->form);
1260 XtRealizeWidget(de->top_level);
1263 ** Do some monkeying to compensate for Motif's pitiful form managers
1264 XtVaGetValues(de->dssw->start_menu, XmNx, &dssw_x,
1265 XmNleftOffset, &dssw_loffset,
1267 XtVaGetValues(de->rfp->repeat_menu, XmNx, &rfp_x,
1268 XmNleftOffset, &rfp_loffset,
1272 XtVaSetValues(de->rfp->rfp_form_mgr,
1273 XmNleftOffset, rfp_loffset + (dssw_x - rfp_x),
1275 else if (rfp_x > dssw_x)
1276 XtVaSetValues(de->dssw->dssw_form_mgr,
1277 XmNleftOffset, dssw_loffset + (rfp_x - dssw_x),
1281 /* Don't need these any more.
1282 XtVaGetValues(de->dssw->date_label, XmNwidth, &longest_dssw_label, NULL);
1284 XtVaGetValues(de->dssw->start_label, XmNwidth, &width, NULL);
1285 if (width > longest_dssw_label)
1286 longest_dssw_label = width;
1288 XtVaGetValues(de->dssw->stop_label, XmNwidth, &width, NULL);
1289 if (width > longest_dssw_label)
1290 longest_dssw_label = width;
1292 XtVaGetValues(de->dssw->what_label, XmNwidth, &width, NULL);
1293 if (width > longest_dssw_label)
1294 longest_dssw_label = width;
1296 XtVaGetValues(de->rfp->frequency_label, XmNwidth, &longest_rfp_label, NULL);
1297 XtVaGetValues(de->rfp->for_label, XmNwidth, &width, NULL);
1298 if (width > longest_rfp_label)
1299 longest_rfp_label = width;
1301 XtVaSetValues(de->dssw->dssw_form_mgr,
1302 XmNleftOffset, longest_rfp_label - longest_dssw_label,
1306 de_set_defaults(de);
1308 de_register_drop_site(de, de->form, True);
1309 de_register_drop_site(de, de->dssw->dssw_form_mgr, False);
1310 de_register_drop_site(de, de->rfp->rfp_form_mgr, False);
1312 XmProcessTraversal(de->dssw->what_text, XmTRAVERSE_CURRENT);
1313 XtVaSetValues(de->form, XmNinitialFocus, de->dssw->what_text, NULL);
1316 status = cmtt_init("AppointmentEditor", de, app, calendar->frame);
1317 if (TT_OK != status) {
1319 errfmt = catgets(calendar->DT_catd, 2, 2,
1320 "Could not connect to ToolTalk:\n%s\n");
1321 DieFromToolTalkError( de, errfmt, status );