1 /*******************************************************************************
5 ** $XConsortium: alarm.c /main/4 1995/12/04 14:15:43 rswiston $
7 ** RESTRICTED CONFIDENTIAL INFORMATION:
9 ** The information in this document is subject to special
10 ** restrictions in a confidential disclosure agreement between
11 ** HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
12 ** document outside HP, IBM, Sun, USL, SCO, or Univel without
13 ** Sun's specific written approval. This document and all copies
14 ** and derivative works thereof must be returned or destroyed at
17 ** Copyright 1993 Sun Microsystems, Inc. All rights reserved.
19 *******************************************************************************/
22 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
23 * (c) Copyright 1993, 1994 International Business Machines Corp. *
24 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
25 * (c) Copyright 1993, 1994 Novell, Inc. *
29 static char sccsid[] = "@(#)alarm.c 1.50 95/07/27 Copyr 1991 Sun Microsystems, Inc.";
32 #include <EUSCompat.h>
38 #include <Xm/DialogS.h>
41 #include <Xm/LabelG.h>
42 #include <Xm/SeparatoG.h>
43 #include <Xm/MwmUtil.h>
45 #include <Dt/Session.h>
54 #include <sys/select.h>
57 /* Structure used on a save session to see if a dt is iconic */
67 extern int submit_mail(
68 const char * to, const char * subject, const char * body);
70 /*******************************************************************************
72 ** Functions external to alarm.c
74 *******************************************************************************/
77 view_flasher(XtPointer client_data, XtIntervalId *interval_id) {
78 Calendar *c = (Calendar *)client_data;
79 Atom wmStateAtom, actualType;
81 unsigned long nitems, leftover;
84 /* Getting the WM_STATE property to see if iconified or not */
85 wmStateAtom = XInternAtom(XtDisplay(c->frame), "WM_STATE", False);
87 XGetWindowProperty (XtDisplay(c->frame), XtWindow(c->frame),
89 (long)BUFSIZ, False, wmStateAtom, &actualType,
90 &actualFormat, &nitems, &leftover,
91 (unsigned char **) &wmState);
93 if (wmState->state == IconicState) {
95 XtVaSetValues(c->frame, XmNiconPixmap, NULL, NULL);
96 if (c->view->flashes % 2) {
97 if (c->icon && c->icon->icon && c->icon->icon_mask)
98 XtVaSetValues(c->frame,
99 XmNiconPixmap, c->icon->icon, NULL);
101 if (c->icon_inverted && c->icon_inverted->icon
102 && c->icon_inverted->icon_mask)
103 XtVaSetValues(c->frame,
104 XmNiconPixmap, c->icon_inverted->icon, NULL);
106 XFlush(c->xcontext->display);
109 XWindowAttributes window_attributes;
111 XGetWindowAttributes(c->xcontext->display,
112 XtWindowOfObject(c->form),
115 XFillRectangle(c->xcontext->display,
116 XtWindowOfObject(c->form),
117 c->xcontext->invert_gc,
119 window_attributes.width,
120 window_attributes.height);
121 XFlush(c->xcontext->display);
124 c->view->flashes -= 1;
125 if (c->view->flashes != 0)
126 XtAppAddTimeOut(c->xcontext->app, 250, view_flasher, c);
128 /* really nasty kludge code to force a complete repaint of
129 the form. It is possible to have damage occur during
130 the flashing feedback, and this can clean it up. */
132 XUnmapWindow(c->xcontext->display, XtWindowOfObject(c->form));
133 XMapWindow(c->xcontext->display, XtWindowOfObject(c->form));
135 /* Make sure the correct icon is restored. */
136 if (wmState->state == IconicState) {
137 if (c->icon && c->icon->icon && c->icon->icon_mask)
138 XtVaSetValues(c->frame,
139 XmNiconPixmap, c->icon->icon, NULL);
145 flash_it(XtPointer client_data, XtIntervalId *interval_id) {
147 Calendar *c = (Calendar *)client_data;
149 if (c->view->flashes == 0) {
150 c->view->flashes = 10;
151 XtAppAddTimeOut(c->xcontext->app, 250, view_flasher, c);
154 /* if the application is busy delivering a flash reminder,
155 don't deliver another one. */
159 mail_it(XtPointer client_data, XtIntervalId *interval_id, CSA_reminder_reference *r) {
160 Calendar *c = (Calendar *)client_data;
162 Lines *lines = NULL, *l = NULL;
163 Props *p = (Props *)c->properties;
165 DisplayType dt = get_int_prop(p, CP_DEFAULTDISP);
166 Dtcm_appointment *appt;
167 char subbuf[BUFSIZ], bodybuf[BUFSIZ];
168 char datebuf[200], startbuf[100], stopbuf[100];
169 char whatbuf[BUFSIZ];
171 CSA_return_code stat;
173 char *addr_data = NULL;
175 appt = allocate_appt_struct(appt_read,
177 CSA_ENTRY_ATTR_START_DATE_I,
178 CSA_ENTRY_ATTR_SUMMARY_I,
179 CSA_ENTRY_ATTR_ORGANIZER_I,
180 CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,
181 CSA_ENTRY_ATTR_END_DATE_I,
182 CSA_ENTRY_ATTR_MAIL_REMINDER_I,
185 stat = query_appt_struct(c->cal_handle, r->entry, appt);
187 backend_err_msg(c->frame, c->calname, stat,
188 ((Props_pu *)c->properties_pu)->xm_error_pixmap);
189 if (stat != CSA_SUCCESS) {
190 free_appt_struct(&appt);
194 /* compose to field */
195 if (appt->mail->value->item.reminder_value->reminder_data.data == NULL ||
196 (appt->mail->value->item.reminder_value->reminder_data.size == 0)) {
197 /* empty recipient */
199 fprintf(stderr, catgets(c->DT_catd, 1, 1,
200 "dtcm: empty recipient in mail reminder\n"));
201 to = appt->author->value->item.calendar_user_value->user_name;
203 addr_data = calloc(appt->mail->value->item.reminder_value->reminder_data.size + 1, 1);
204 strncpy(addr_data, (char *) appt->mail->value->item.reminder_value->reminder_data.data, appt->mail->value->item.reminder_value->reminder_data.size);
208 /* compose subject field */
209 lines = text_to_lines(appt->what->value->item.string_value, 5);
210 sprintf(subbuf, catgets(c->DT_catd, 1, 2, "Reminder- %s"),
211 (lines) ? lines->s : "\0");
213 /* compose message body */
214 _csa_iso8601_to_tick(appt->time->value->item.date_time_value, &start);
215 format_tick(start, ORDER_MDY, SEPARATOR_SLASH, datebuf);
217 if (showtime_set(appt) && !magic_time(start)) {
219 pm = (dt == HOUR12 && !adjust_hour(&hr)) ? True : False;
221 sprintf(startbuf, "%2d:%02d %s", hr, minute(start),
225 sprintf(startbuf, "%02d%02d", hr, minute(start));
230 if (showtime_set(appt) && !magic_time(start) && appt->end_time) {
231 _csa_iso8601_to_tick(appt->end_time->value->\
232 item.date_time_value, &stop);
234 pm = (dt == HOUR12 && !adjust_hour(&hr)) ? True : False;
236 sprintf(stopbuf, "%2d:%02d %s", hr, minute(stop),
237 pm ? catgets(c->DT_catd, 1, 3, "pm") :
238 catgets(c->DT_catd, 1, 4, "am"));
240 sprintf(stopbuf, "%02d%02d", hr, minute(stop));
246 sprintf(whatbuf, "%s\n", l->s);
252 strcat(whatbuf, "\t\t");
253 strcat(whatbuf, l->s);
254 strcat(whatbuf, "\n");
258 destroy_lines(lines);
260 if (stopbuf[0] != '\0') {
261 sprintf(bodybuf, catgets(c->DT_catd, 1, 7, "\n\n\t** Calendar Appointment **\n\n\tDate:\t%s\n\tStart:\t%s\n\tEnd:\t%s\n\tWhat:\t%s"),
262 datebuf, startbuf, stopbuf, whatbuf);
264 sprintf(bodybuf, catgets(c->DT_catd, 1, 1100, "\n\n\t** Calendar To Do Item **\n\n\tDue Date:\t%s\n\tTime Due:\t%s\n\tWhat:\t\t%s"),
265 datebuf, startbuf, whatbuf);
269 fprintf(stderr, "to = `%s`\n", to);
270 fprintf(stderr, "subject = `%s`\n", subbuf);
271 fprintf(stderr, "body = `%s`\n", bodybuf);
274 (void)submit_mail(to, subbuf, bodybuf);
276 free_appt_struct(&appt);
283 open_it(XtPointer client_data, XtIntervalId *interval_id, CSA_reminder_reference *r) {
284 Calendar *c = (Calendar *)client_data;
286 postup_show_proc(c, r);
290 reminder_driver(XtPointer client_data, XtIntervalId *interval_id) {
291 Calendar *c = (Calendar *)client_data;
295 if (c->view->next_alarm_id != *interval_id || !c->view->next_alarm) {
296 c->view->next_alarm_id = 0;
303 * do not handle the reminder if the time it's to happen
304 * is earlier than the current time
306 _csa_iso8601_to_tick(c->view->next_alarm[0].run_time, &run_tick);
307 if (now() >= run_tick) {
309 for (i = 0; i < c->view->next_alarm_count; i++) {
310 if (strcmp(c->view->next_alarm[i].attribute_name, CSA_ENTRY_ATTR_AUDIO_REMINDER)==0)
311 ring_it(client_data, interval_id);
312 else if (strcmp(c->view->next_alarm[i].attribute_name, CSA_ENTRY_ATTR_FLASHING_REMINDER)==0)
313 flash_it(client_data, interval_id);
314 else if (strcmp(c->view->next_alarm[i].attribute_name, CSA_ENTRY_ATTR_POPUP_REMINDER)==0)
315 open_it(client_data, interval_id, &c->view->next_alarm[i]);
316 else if (strcmp(c->view->next_alarm[i].attribute_name, CSA_ENTRY_ATTR_MAIL_REMINDER)==0)
317 mail_it(client_data, interval_id, &c->view->next_alarm[i]);
322 c->view->next_alarm_id = 0;
328 bell_ringer(XtPointer client_data, XtIntervalId *interval_id) {
329 Calendar *c = (Calendar *)client_data;
330 XBell(c->xcontext->display, 50);
332 if (c->view->rings != 0)
333 XtAppAddTimeOut(c->xcontext->app, 250, bell_ringer, c);
337 ring_it(XtPointer client_data, XtIntervalId *interval_id) {
338 Calendar *c = (Calendar *)client_data;
340 if (c->view->rings == 0) {
342 XtAppAddTimeOut(c->xcontext->app, 250, bell_ringer, c);
345 /* If the application is busy delivering a ring reminder
346 don't deliver another one. */
350 * Close dialog: pop down and destroy the dialog, and free
354 close_cb(Widget w, XtPointer data, XtPointer ignore)
356 Widget shell = (Widget) data;
359 XtDestroyWidget(shell);
364 ** Functions to build and popup the postup reminder
367 postup_show_proc(Calendar *c, CSA_reminder_reference *r) {
368 int start_hr, stop_hr;
371 Lines *lines, *l = NULL;
372 Props *p = (Props *)c->properties;
373 Widget pu_frame, pu_base_form,
374 pu_text_form, separator,
375 pu_form, button_form, pu_date,
376 pu_range, pu_image, pu_close, line, last_line;
377 Boolean start_am, stop_am;
379 CSA_return_code stat;
380 DisplayType dis_t = get_int_prop(p, CP_DEFAULTDISP);
381 OrderingType ord_t = get_int_prop(p, CP_DATEORDERING);
382 SeparatorType sep_t = get_int_prop(p, CP_DATESEPARATOR);
383 Dtcm_appointment *appt;
387 c->postup = XtAppCreateShell("calendar_postup", "Dtcm",
388 xmDialogShellWidgetClass, c->xcontext->display,
392 ** Create the Motif objects
394 title = XtNewString(catgets(c->DT_catd, 1, 839, "Calendar : Reminder"));
395 pu_frame = XtVaCreatePopupShell("pu_frame",
396 topLevelShellWidgetClass, c->postup,
398 XmNmwmFunctions, MWM_FUNC_MOVE | MWM_FUNC_CLOSE,
399 XmNdeleteResponse, XmDESTROY,
403 pu_base_form = XtVaCreateWidget("pu_base_form",
404 xmFormWidgetClass, pu_frame,
407 pu_text_form = XtVaCreateWidget("pu_test_form",
408 xmFormWidgetClass, pu_base_form,
409 XmNtopAttachment, XmATTACH_FORM,
410 XmNleftAttachment, XmATTACH_FORM,
411 XmNtopAttachment, XmATTACH_FORM,
417 pu_image = XtVaCreateWidget("pu_image",
418 xmLabelGadgetClass, pu_text_form,
419 XmNleftAttachment, XmATTACH_FORM,
420 XmNtopAttachment, XmATTACH_FORM,
422 XmNlabelType, XmPIXMAP,
423 XmNlabelPixmap, ((Props_pu *)c->properties_pu)->postup_pixmap,
426 button_form = XtVaCreateWidget("pu_form",
427 xmFormWidgetClass, pu_base_form,
428 XmNbottomAttachment, XmATTACH_FORM,
432 XmNleftAttachment, XmATTACH_FORM,
433 XmNrightAttachment, XmATTACH_FORM,
437 xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 680, "Close"));
438 pu_close = XtVaCreateManagedWidget("close",
439 xmPushButtonWidgetClass, button_form,
440 XmNtopAttachment, XmATTACH_FORM,
441 XmNbottomAttachment, XmATTACH_FORM,
442 XmNleftAttachment, XmATTACH_POSITION,
443 XmNrightAttachment, XmATTACH_POSITION,
447 XmNlabelString, xmstr,
451 separator = XtVaCreateWidget("separator",
452 xmSeparatorGadgetClass,
454 XmNleftAttachment, XmATTACH_FORM,
455 XmNrightAttachment, XmATTACH_FORM,
456 XmNbottomAttachment, XmATTACH_WIDGET,
457 XmNbottomWidget, button_form,
458 XmNtopAttachment, XmATTACH_WIDGET,
459 XmNtopWidget, pu_text_form,
464 pu_form = XtVaCreateWidget("pu_form",
465 xmFormWidgetClass, pu_text_form,
466 XmNtopAttachment, XmATTACH_FORM,
468 XmNleftAttachment, XmATTACH_WIDGET,
469 XmNleftWidget, pu_image,
470 XmNverticalSpacing, 10,
473 pu_date = XtVaCreateWidget("pu_date",
474 xmLabelGadgetClass, pu_form,
475 XmNleftAttachment, XmATTACH_FORM,
476 XmNtopAttachment, XmATTACH_FORM,
479 pu_range = XtVaCreateWidget("pu_range",
480 xmLabelGadgetClass, pu_form,
481 XmNleftAttachment, XmATTACH_FORM,
482 XmNtopAttachment, XmATTACH_WIDGET,
483 XmNtopWidget, pu_date,
487 XtAddCallback(pu_close, XmNactivateCallback, close_cb, pu_frame);
489 appt = allocate_appt_struct(appt_read,
491 CSA_ENTRY_ATTR_START_DATE_I,
492 CSA_ENTRY_ATTR_END_DATE_I,
493 CSA_ENTRY_ATTR_SUMMARY_I,
494 CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,
496 stat = query_appt_struct(c->cal_handle, r->entry, appt);
497 backend_err_msg(c->frame, c->calname, stat,
498 ((Props_pu *)c->properties_pu)->xm_error_pixmap);
499 if (stat != CSA_SUCCESS) {
500 free_appt_struct(&appt);
504 _csa_iso8601_to_tick(appt->time->value->item.date_time_value, &st);
506 _csa_iso8601_to_tick(appt->end_time->value->\
507 item.date_time_value, &sp);
508 l = lines = text_to_lines(appt->what->value->item.string_value, 5);
511 xmstr = XmStringCreateLocalized(l->s);
512 line = XtVaCreateWidget("text_line",
513 xmLabelGadgetClass, pu_text_form,
514 XmNlabelString, xmstr,
515 XmNleftAttachment, XmATTACH_WIDGET,
516 XmNleftWidget, pu_form,
523 XmNtopAttachment, XmATTACH_WIDGET,
524 XmNtopWidget, last_line,
529 XmNtopAttachment, XmATTACH_FORM,
537 destroy_lines(lines);
540 ** Now fill in the correct information
542 set_date_in_widget(st, pu_date, ord_t, sep_t);
544 if (!showtime_set(appt) || magic_time(st))
548 if (sp) stop_hr = hour(sp);
549 if (dis_t == HOUR12) {
550 start_am = adjust_hour(&start_hr);
554 Message 1087 : This message is used to form
555 the alarm string that appears in the
556 reminder popup. In the C locale it would
557 look something like this:
559 ``From 11:00am to 1:00pm''
561 In the printf conversion string the $n are:
571 char *am = XtNewString(catgets(c->DT_catd,
573 char *pm = XtNewString(catgets(c->DT_catd,
575 stop_am = adjust_hour(&stop_hr);
576 sprintf(text, catgets(c->DT_catd, 1, 1087,
577 "From %1$2d:%2$02d%3$s to %4$2d:%5$02d%6$s"),
578 start_hr, minute(st),
579 (start_am) ? am : pm,
588 Message 1088 : This message is used to form
589 the alarm string that appears in the
590 reminder popup. It is used when an appt
591 does not have and ``end'' time. In the
592 C locale it would look something like this:
596 In the printf conversion string the $n are:
604 XtNewString ((start_am) ?
605 catgets(c->DT_catd, 1, 4, "am"):
606 catgets(c->DT_catd, 1, 3, "pm"));
608 sprintf(text, catgets(c->DT_catd, 1, 1088,
610 start_hr, minute(st), meridian
618 Message 1089 : This message is used to form
619 the alarm string that appears in the
620 reminder popup. This string is used when
621 a user has asked that times be displayed
622 in 24 hour format. In the C locale it
623 would look something like this:
625 ``From 0100 to 1600''
627 In the printf conversion string the $n are:
635 sprintf(text, catgets(c->DT_catd, 1, 1089,
636 "From %1$02d%2$02d to %3$02d%4$02d"),
637 start_hr, minute(st), stop_hr,
642 Message 1090 : This message is used to form
643 the alarm string that appears in the
644 reminder popup. This string is used when
645 an appt does not have an end time and the
646 user has asked that times be displayed
647 in 24 hour format. In the C locale it
648 would look something like this:
652 In the printf conversion string the $n are:
658 sprintf(text, catgets(c->DT_catd, 1, 1090,
660 start_hr, minute(st));
665 free_appt_struct(&appt);
666 xmstr = XmStringCreateLocalized(text);
667 XtVaSetValues(pu_range, XmNlabelString, xmstr,
671 ManageChildren(pu_form);
672 ManageChildren(pu_base_form);
673 ManageChildren(pu_text_form);
674 XtManageChild(pu_base_form);
675 XtVaSetValues(button_form, XmNdefaultButton, pu_close, NULL);
676 XtVaSetValues(button_form, XmNcancelButton, pu_close, NULL);
677 XtPopup(pu_frame, XtGrabNone);
678 DtWsmOccupyAllWorkspaces(c->xcontext->display, XtWindow(pu_frame));