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 /*******************************************************************************
27 ** $XConsortium: alarm.c /main/4 1995/12/04 14:15:43 rswiston $
29 ** RESTRICTED CONFIDENTIAL INFORMATION:
31 ** The information in this document is subject to special
32 ** restrictions in a confidential disclosure agreement between
33 ** HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
34 ** document outside HP, IBM, Sun, USL, SCO, or Univel without
35 ** Sun's specific written approval. This document and all copies
36 ** and derivative works thereof must be returned or destroyed at
39 ** Copyright 1993 Sun Microsystems, Inc. All rights reserved.
41 *******************************************************************************/
44 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
45 * (c) Copyright 1993, 1994 International Business Machines Corp. *
46 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
47 * (c) Copyright 1993, 1994 Novell, Inc. *
51 static char sccsid[] = "@(#)alarm.c 1.50 95/07/27 Copyr 1991 Sun Microsystems, Inc.";
54 #include <EUSCompat.h>
60 #include <Xm/DialogS.h>
63 #include <Xm/LabelG.h>
64 #include <Xm/SeparatoG.h>
65 #include <Xm/MwmUtil.h>
67 #include <Dt/Session.h>
76 #include <sys/select.h>
79 /* Structure used on a save session to see if a dt is iconic */
89 extern int submit_mail(
90 const char * to, const char * subject, const char * body);
92 /*******************************************************************************
94 ** Functions external to alarm.c
96 *******************************************************************************/
99 view_flasher(XtPointer client_data, XtIntervalId *interval_id) {
100 Calendar *c = (Calendar *)client_data;
101 Atom wmStateAtom, actualType;
103 unsigned long nitems, leftover;
106 /* Getting the WM_STATE property to see if iconified or not */
107 wmStateAtom = XInternAtom(XtDisplay(c->frame), "WM_STATE", False);
109 XGetWindowProperty (XtDisplay(c->frame), XtWindow(c->frame),
111 (long)BUFSIZ, False, wmStateAtom, &actualType,
112 &actualFormat, &nitems, &leftover,
113 (unsigned char **) &wmState);
115 if (wmState->state == IconicState) {
117 XtVaSetValues(c->frame, XmNiconPixmap, NULL, NULL);
118 if (c->view->flashes % 2) {
119 if (c->icon && c->icon->icon && c->icon->icon_mask)
120 XtVaSetValues(c->frame,
121 XmNiconPixmap, c->icon->icon, NULL);
123 if (c->icon_inverted && c->icon_inverted->icon
124 && c->icon_inverted->icon_mask)
125 XtVaSetValues(c->frame,
126 XmNiconPixmap, c->icon_inverted->icon, NULL);
128 XFlush(c->xcontext->display);
131 XWindowAttributes window_attributes;
133 XGetWindowAttributes(c->xcontext->display,
134 XtWindowOfObject(c->form),
137 XFillRectangle(c->xcontext->display,
138 XtWindowOfObject(c->form),
139 c->xcontext->invert_gc,
141 window_attributes.width,
142 window_attributes.height);
143 XFlush(c->xcontext->display);
146 c->view->flashes -= 1;
147 if (c->view->flashes != 0)
148 XtAppAddTimeOut(c->xcontext->app, 250, view_flasher, c);
150 /* really nasty kludge code to force a complete repaint of
151 the form. It is possible to have damage occur during
152 the flashing feedback, and this can clean it up. */
154 XUnmapWindow(c->xcontext->display, XtWindowOfObject(c->form));
155 XMapWindow(c->xcontext->display, XtWindowOfObject(c->form));
157 /* Make sure the correct icon is restored. */
158 if (wmState->state == IconicState) {
159 if (c->icon && c->icon->icon && c->icon->icon_mask)
160 XtVaSetValues(c->frame,
161 XmNiconPixmap, c->icon->icon, NULL);
167 flash_it(XtPointer client_data, XtIntervalId *interval_id) {
169 Calendar *c = (Calendar *)client_data;
171 if (c->view->flashes == 0) {
172 c->view->flashes = 10;
173 XtAppAddTimeOut(c->xcontext->app, 250, view_flasher, c);
176 /* if the application is busy delivering a flash reminder,
177 don't deliver another one. */
181 mail_it(XtPointer client_data, XtIntervalId *interval_id, CSA_reminder_reference *r) {
182 Calendar *c = (Calendar *)client_data;
184 Lines *lines = NULL, *l = NULL;
185 Props *p = (Props *)c->properties;
187 DisplayType dt = get_int_prop(p, CP_DEFAULTDISP);
188 Dtcm_appointment *appt;
189 char subbuf[BUFSIZ], bodybuf[BUFSIZ];
190 char datebuf[200], startbuf[100], stopbuf[100];
191 char whatbuf[BUFSIZ];
193 CSA_return_code stat;
195 char *addr_data = NULL;
197 appt = allocate_appt_struct(appt_read,
199 CSA_ENTRY_ATTR_START_DATE_I,
200 CSA_ENTRY_ATTR_SUMMARY_I,
201 CSA_ENTRY_ATTR_ORGANIZER_I,
202 CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,
203 CSA_ENTRY_ATTR_END_DATE_I,
204 CSA_ENTRY_ATTR_MAIL_REMINDER_I,
207 stat = query_appt_struct(c->cal_handle, r->entry, appt);
209 backend_err_msg(c->frame, c->calname, stat,
210 ((Props_pu *)c->properties_pu)->xm_error_pixmap);
211 if (stat != CSA_SUCCESS) {
212 free_appt_struct(&appt);
216 /* compose to field */
217 if (appt->mail->value->item.reminder_value->reminder_data.data == NULL ||
218 (appt->mail->value->item.reminder_value->reminder_data.size == 0)) {
219 /* empty recipient */
221 fprintf(stderr, "%s", catgets(c->DT_catd, 1, 1,
222 "dtcm: empty recipient in mail reminder\n"));
223 to = appt->author->value->item.calendar_user_value->user_name;
225 addr_data = calloc(appt->mail->value->item.reminder_value->reminder_data.size + 1, 1);
226 strncpy(addr_data, (char *) appt->mail->value->item.reminder_value->reminder_data.data, appt->mail->value->item.reminder_value->reminder_data.size);
230 /* compose subject field */
231 lines = text_to_lines(appt->what->value->item.string_value, 5);
232 sprintf(subbuf, catgets(c->DT_catd, 1, 2, "Reminder- %s"),
233 (lines) ? lines->s : "\0");
235 /* compose message body */
236 _csa_iso8601_to_tick(appt->time->value->item.date_time_value, &start);
237 format_tick(start, ORDER_MDY, SEPARATOR_SLASH, datebuf);
239 if (showtime_set(appt) && !magic_time(start)) {
241 pm = (dt == HOUR12 && !adjust_hour(&hr)) ? True : False;
243 sprintf(startbuf, "%2d:%02d %s", hr, minute(start),
247 sprintf(startbuf, "%02d%02d", hr, minute(start));
252 if (showtime_set(appt) && !magic_time(start) && appt->end_time) {
253 _csa_iso8601_to_tick(appt->end_time->value->\
254 item.date_time_value, &stop);
256 pm = (dt == HOUR12 && !adjust_hour(&hr)) ? True : False;
258 sprintf(stopbuf, "%2d:%02d %s", hr, minute(stop),
259 pm ? catgets(c->DT_catd, 1, 3, "pm") :
260 catgets(c->DT_catd, 1, 4, "am"));
262 sprintf(stopbuf, "%02d%02d", hr, minute(stop));
268 sprintf(whatbuf, "%s\n", l->s);
274 strcat(whatbuf, "\t\t");
275 strcat(whatbuf, l->s);
276 strcat(whatbuf, "\n");
280 destroy_lines(lines);
282 if (stopbuf[0] != '\0') {
283 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"),
284 datebuf, startbuf, stopbuf, whatbuf);
286 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"),
287 datebuf, startbuf, whatbuf);
291 fprintf(stderr, "to = `%s`\n", to);
292 fprintf(stderr, "subject = `%s`\n", subbuf);
293 fprintf(stderr, "body = `%s`\n", bodybuf);
296 (void)submit_mail(to, subbuf, bodybuf);
298 free_appt_struct(&appt);
305 open_it(XtPointer client_data, XtIntervalId *interval_id, CSA_reminder_reference *r) {
306 Calendar *c = (Calendar *)client_data;
308 postup_show_proc(c, r);
312 reminder_driver(XtPointer client_data, XtIntervalId *interval_id) {
313 Calendar *c = (Calendar *)client_data;
317 if (c->view->next_alarm_id != *interval_id || !c->view->next_alarm) {
318 c->view->next_alarm_id = 0;
325 * do not handle the reminder if the time it's to happen
326 * is earlier than the current time
328 _csa_iso8601_to_tick(c->view->next_alarm[0].run_time, &run_tick);
329 if (now() >= run_tick) {
331 for (i = 0; i < c->view->next_alarm_count; i++) {
332 if (strcmp(c->view->next_alarm[i].attribute_name, CSA_ENTRY_ATTR_AUDIO_REMINDER)==0)
333 ring_it(client_data, interval_id);
334 else if (strcmp(c->view->next_alarm[i].attribute_name, CSA_ENTRY_ATTR_FLASHING_REMINDER)==0)
335 flash_it(client_data, interval_id);
336 else if (strcmp(c->view->next_alarm[i].attribute_name, CSA_ENTRY_ATTR_POPUP_REMINDER)==0)
337 open_it(client_data, interval_id, &c->view->next_alarm[i]);
338 else if (strcmp(c->view->next_alarm[i].attribute_name, CSA_ENTRY_ATTR_MAIL_REMINDER)==0)
339 mail_it(client_data, interval_id, &c->view->next_alarm[i]);
344 c->view->next_alarm_id = 0;
350 bell_ringer(XtPointer client_data, XtIntervalId *interval_id) {
351 Calendar *c = (Calendar *)client_data;
352 XBell(c->xcontext->display, 50);
354 if (c->view->rings != 0)
355 XtAppAddTimeOut(c->xcontext->app, 250, bell_ringer, c);
359 ring_it(XtPointer client_data, XtIntervalId *interval_id) {
360 Calendar *c = (Calendar *)client_data;
362 if (c->view->rings == 0) {
364 XtAppAddTimeOut(c->xcontext->app, 250, bell_ringer, c);
367 /* If the application is busy delivering a ring reminder
368 don't deliver another one. */
372 * Close dialog: pop down and destroy the dialog, and free
376 close_cb(Widget w, XtPointer data, XtPointer ignore)
378 Widget shell = (Widget) data;
381 XtDestroyWidget(shell);
386 ** Functions to build and popup the postup reminder
389 postup_show_proc(Calendar *c, CSA_reminder_reference *r) {
390 int start_hr, stop_hr;
393 Lines *lines, *l = NULL;
394 Props *p = (Props *)c->properties;
395 Widget pu_frame, pu_base_form,
396 pu_text_form, separator,
397 pu_form, button_form, pu_date,
398 pu_range, pu_image, pu_close, line, last_line;
399 Boolean start_am, stop_am;
401 CSA_return_code stat;
402 DisplayType dis_t = get_int_prop(p, CP_DEFAULTDISP);
403 OrderingType ord_t = get_int_prop(p, CP_DATEORDERING);
404 SeparatorType sep_t = get_int_prop(p, CP_DATESEPARATOR);
405 Dtcm_appointment *appt;
409 c->postup = XtAppCreateShell("calendar_postup", "Dtcm",
410 xmDialogShellWidgetClass, c->xcontext->display,
414 ** Create the Motif objects
416 title = XtNewString(catgets(c->DT_catd, 1, 839, "Calendar : Reminder"));
417 pu_frame = XtVaCreatePopupShell("pu_frame",
418 topLevelShellWidgetClass, c->postup,
420 XmNmwmFunctions, MWM_FUNC_MOVE | MWM_FUNC_CLOSE,
421 XmNdeleteResponse, XmDESTROY,
425 pu_base_form = XtVaCreateWidget("pu_base_form",
426 xmFormWidgetClass, pu_frame,
429 pu_text_form = XtVaCreateWidget("pu_test_form",
430 xmFormWidgetClass, pu_base_form,
431 XmNtopAttachment, XmATTACH_FORM,
432 XmNleftAttachment, XmATTACH_FORM,
433 XmNtopAttachment, XmATTACH_FORM,
439 pu_image = XtVaCreateWidget("pu_image",
440 xmLabelGadgetClass, pu_text_form,
441 XmNleftAttachment, XmATTACH_FORM,
442 XmNtopAttachment, XmATTACH_FORM,
444 XmNlabelType, XmPIXMAP,
445 XmNlabelPixmap, ((Props_pu *)c->properties_pu)->postup_pixmap,
448 button_form = XtVaCreateWidget("pu_form",
449 xmFormWidgetClass, pu_base_form,
450 XmNbottomAttachment, XmATTACH_FORM,
454 XmNleftAttachment, XmATTACH_FORM,
455 XmNrightAttachment, XmATTACH_FORM,
459 xmstr = XmStringCreateLocalized(catgets(c->DT_catd, 1, 680, "Close"));
460 pu_close = XtVaCreateManagedWidget("close",
461 xmPushButtonWidgetClass, button_form,
462 XmNtopAttachment, XmATTACH_FORM,
463 XmNbottomAttachment, XmATTACH_FORM,
464 XmNleftAttachment, XmATTACH_POSITION,
465 XmNrightAttachment, XmATTACH_POSITION,
469 XmNlabelString, xmstr,
473 separator = XtVaCreateWidget("separator",
474 xmSeparatorGadgetClass,
476 XmNleftAttachment, XmATTACH_FORM,
477 XmNrightAttachment, XmATTACH_FORM,
478 XmNbottomAttachment, XmATTACH_WIDGET,
479 XmNbottomWidget, button_form,
480 XmNtopAttachment, XmATTACH_WIDGET,
481 XmNtopWidget, pu_text_form,
486 pu_form = XtVaCreateWidget("pu_form",
487 xmFormWidgetClass, pu_text_form,
488 XmNtopAttachment, XmATTACH_FORM,
490 XmNleftAttachment, XmATTACH_WIDGET,
491 XmNleftWidget, pu_image,
492 XmNverticalSpacing, 10,
495 pu_date = XtVaCreateWidget("pu_date",
496 xmLabelGadgetClass, pu_form,
497 XmNleftAttachment, XmATTACH_FORM,
498 XmNtopAttachment, XmATTACH_FORM,
501 pu_range = XtVaCreateWidget("pu_range",
502 xmLabelGadgetClass, pu_form,
503 XmNleftAttachment, XmATTACH_FORM,
504 XmNtopAttachment, XmATTACH_WIDGET,
505 XmNtopWidget, pu_date,
509 XtAddCallback(pu_close, XmNactivateCallback, close_cb, pu_frame);
511 appt = allocate_appt_struct(appt_read,
513 CSA_ENTRY_ATTR_START_DATE_I,
514 CSA_ENTRY_ATTR_END_DATE_I,
515 CSA_ENTRY_ATTR_SUMMARY_I,
516 CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,
518 stat = query_appt_struct(c->cal_handle, r->entry, appt);
519 backend_err_msg(c->frame, c->calname, stat,
520 ((Props_pu *)c->properties_pu)->xm_error_pixmap);
521 if (stat != CSA_SUCCESS) {
522 free_appt_struct(&appt);
526 _csa_iso8601_to_tick(appt->time->value->item.date_time_value, &st);
528 _csa_iso8601_to_tick(appt->end_time->value->\
529 item.date_time_value, &sp);
530 l = lines = text_to_lines(appt->what->value->item.string_value, 5);
533 xmstr = XmStringCreateLocalized(l->s);
534 line = XtVaCreateWidget("text_line",
535 xmLabelGadgetClass, pu_text_form,
536 XmNlabelString, xmstr,
537 XmNleftAttachment, XmATTACH_WIDGET,
538 XmNleftWidget, pu_form,
545 XmNtopAttachment, XmATTACH_WIDGET,
546 XmNtopWidget, last_line,
551 XmNtopAttachment, XmATTACH_FORM,
559 destroy_lines(lines);
562 ** Now fill in the correct information
564 set_date_in_widget(st, pu_date, ord_t, sep_t);
566 if (!showtime_set(appt) || magic_time(st))
570 if (sp) stop_hr = hour(sp);
571 if (dis_t == HOUR12) {
572 start_am = adjust_hour(&start_hr);
576 Message 1087 : This message is used to form
577 the alarm string that appears in the
578 reminder popup. In the C locale it would
579 look something like this:
581 ``From 11:00am to 1:00pm''
583 In the printf conversion string the $n are:
593 char *am = XtNewString(catgets(c->DT_catd,
595 char *pm = XtNewString(catgets(c->DT_catd,
597 stop_am = adjust_hour(&stop_hr);
598 sprintf(text, catgets(c->DT_catd, 1, 1087,
599 "From %1$2d:%2$02d%3$s to %4$2d:%5$02d%6$s"),
600 start_hr, minute(st),
601 (start_am) ? am : pm,
610 Message 1088 : This message is used to form
611 the alarm string that appears in the
612 reminder popup. It is used when an appt
613 does not have and ``end'' time. In the
614 C locale it would look something like this:
618 In the printf conversion string the $n are:
626 XtNewString ((start_am) ?
627 catgets(c->DT_catd, 1, 4, "am"):
628 catgets(c->DT_catd, 1, 3, "pm"));
630 sprintf(text, catgets(c->DT_catd, 1, 1088,
632 start_hr, minute(st), meridian
640 Message 1089 : This message is used to form
641 the alarm string that appears in the
642 reminder popup. This string is used when
643 a user has asked that times be displayed
644 in 24 hour format. In the C locale it
645 would look something like this:
647 ``From 0100 to 1600''
649 In the printf conversion string the $n are:
657 sprintf(text, catgets(c->DT_catd, 1, 1089,
658 "From %1$02d%2$02d to %3$02d%4$02d"),
659 start_hr, minute(st), stop_hr,
664 Message 1090 : This message is used to form
665 the alarm string that appears in the
666 reminder popup. This string is used when
667 an appt does not have an end time and the
668 user has asked that times be displayed
669 in 24 hour format. In the C locale it
670 would look something like this:
674 In the printf conversion string the $n are:
680 sprintf(text, catgets(c->DT_catd, 1, 1090,
682 start_hr, minute(st));
687 free_appt_struct(&appt);
688 xmstr = XmStringCreateLocalized(text);
689 XtVaSetValues(pu_range, XmNlabelString, xmstr,
693 ManageChildren(pu_form);
694 ManageChildren(pu_base_form);
695 ManageChildren(pu_text_form);
696 XtManageChild(pu_base_form);
697 XtVaSetValues(button_form, XmNdefaultButton, pu_close, NULL);
698 XtVaSetValues(button_form, XmNcancelButton, pu_close, NULL);
699 XtPopup(pu_frame, XtGrabNone);
700 DtWsmOccupyAllWorkspaces(c->xcontext->display, XtWindow(pu_frame));