dtcm: Resolve CID 87562
[oweals/cde.git] / cde / programs / dtcm / dtcm / alarm.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
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)
10  * any later version.
11  *
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
16  * details.
17  *
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
22  */
23 /*******************************************************************************
24 **
25 **  alarm.c
26 **
27 **  $XConsortium: alarm.c /main/4 1995/12/04 14:15:43 rswiston $
28 **
29 **  RESTRICTED CONFIDENTIAL INFORMATION:
30 **
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
37 **  Sun's request.
38 **
39 **  Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
40 **
41 *******************************************************************************/
42
43 /*                                                                      *
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.                                *
48  */
49
50 #ifndef lint
51 static  char sccsid[] = "@(#)alarm.c 1.50 95/07/27 Copyr 1991 Sun Microsystems, Inc.";
52 #endif
53
54 #include <EUSCompat.h>
55 #include <unistd.h>
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <fcntl.h>
59 #include <sys/time.h>
60 #include <Xm/DialogS.h>
61 #include <Xm/Form.h>
62 #include <Xm/PushB.h>
63 #include <Xm/LabelG.h>
64 #include <Xm/SeparatoG.h>
65 #include <Xm/MwmUtil.h>
66 #include <Dt/Wsm.h>
67 #include <Dt/Session.h>
68 #include "calendar.h"
69 #include "alarm.h"
70 #include "misc.h"
71 #include "props_pu.h"
72 #include "timeops.h"
73 #include "util.h"
74
75 #ifdef AIX
76 #include <sys/select.h>
77 #endif
78
79 /*  Structure used on a save session to see if a dt is iconic  */
80 typedef struct
81 {
82    int state;
83    Window icon;
84 } WM_STATE;
85  
86
87
88 extern int debug;
89 extern int submit_mail(
90                 const char * to, const char * subject, const char * body);
91
92 /*******************************************************************************
93 **
94 **  Functions external to alarm.c
95 **
96 *******************************************************************************/
97
98 extern void
99 view_flasher(XtPointer client_data, XtIntervalId *interval_id) {
100     Calendar        *c = (Calendar *)client_data;
101     Atom        wmStateAtom, actualType;
102     int         actualFormat;
103     unsigned long nitems, leftover;
104     WM_STATE *wmState;
105  
106     /*  Getting the WM_STATE property to see if iconified or not */
107     wmStateAtom = XInternAtom(XtDisplay(c->frame), "WM_STATE", False);
108  
109     XGetWindowProperty (XtDisplay(c->frame), XtWindow(c->frame), 
110                         wmStateAtom, 0L,
111                         (long)BUFSIZ, False, wmStateAtom, &actualType,
112                         &actualFormat, &nitems, &leftover,
113                         (unsigned char **) &wmState);
114  
115     if (wmState->state == IconicState) {
116
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);
122         } else {
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);
127         }
128         XFlush(c->xcontext->display);
129     }
130     else {
131         XWindowAttributes       window_attributes;
132
133         XGetWindowAttributes(c->xcontext->display, 
134                                 XtWindowOfObject(c->form), 
135                                 &window_attributes);
136
137         XFillRectangle(c->xcontext->display, 
138                                 XtWindowOfObject(c->form), 
139                                 c->xcontext->invert_gc, 
140                                 0, 0, 
141                                 window_attributes.width, 
142                                 window_attributes.height);
143         XFlush(c->xcontext->display);
144     }
145
146     c->view->flashes -= 1;
147     if (c->view->flashes != 0)
148         XtAppAddTimeOut(c->xcontext->app, 250, view_flasher, c);
149     else {
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. */
153
154         XUnmapWindow(c->xcontext->display, XtWindowOfObject(c->form));
155         XMapWindow(c->xcontext->display, XtWindowOfObject(c->form));
156
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);
162         }
163     }
164 }
165
166 extern void 
167 flash_it(XtPointer client_data, XtIntervalId *interval_id) {
168     int         i, j;
169     Calendar    *c = (Calendar *)client_data;
170
171     if (c->view->flashes == 0) {
172         c->view->flashes = 10;
173         XtAppAddTimeOut(c->xcontext->app, 250, view_flasher, c);
174     }
175
176     /* if the application is busy delivering a flash reminder, 
177        don't deliver another one. */
178 }
179
180 extern void 
181 mail_it(XtPointer client_data, XtIntervalId *interval_id, CSA_reminder_reference *r) {
182         Calendar                *c = (Calendar *)client_data;
183         int                     hr;
184         Lines                   *lines = NULL, *l = NULL;
185         Props                   *p = (Props *)c->properties;
186         Boolean                 pm;
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];
192         char                    *to;
193         CSA_return_code         stat;
194         Tick                    start, stop;
195         char                    *addr_data = NULL;
196
197         appt = allocate_appt_struct(appt_read,
198                                     c->general->version,
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,
205                                     NULL);
206
207         stat = query_appt_struct(c->cal_handle, r->entry, appt);
208
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);
213                 return;
214         }
215
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 */
220                 if (debug)
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;
224         } else {
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);
227                 to = addr_data;
228         }
229
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");
234
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);
238
239         if (showtime_set(appt) && !magic_time(start)) {
240                 hr = hour(start);
241                 pm = (dt == HOUR12 && !adjust_hour(&hr)) ? True : False;
242                 if (dt == HOUR12) {
243                         sprintf(startbuf, "%2d:%02d %s", hr, minute(start),
244                                 pm ? "pm" :
245                                 "am");
246                 } else {
247                         sprintf(startbuf, "%02d%02d", hr, minute(start));
248                 }
249         } else
250                 startbuf[0] = '\0';
251
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);
255                 hr = hour(stop);
256                 pm = (dt == HOUR12 && !adjust_hour(&hr)) ? True : False;
257                 if (dt == HOUR12) {
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"));
261                 } else {
262                         sprintf(stopbuf, "%02d%02d", hr, minute(stop));
263                 }
264         } else
265                 stopbuf[0] = '\0';
266
267         if (l = lines) {
268                 sprintf(whatbuf, "%s\n", l->s);
269                 l = l->next;
270         } else
271                 whatbuf[0] = '\0';
272
273         while(l != NULL) {
274                 strcat(whatbuf, "\t\t");
275                 strcat(whatbuf, l->s);
276                 strcat(whatbuf, "\n");
277                 l = l->next;
278         }
279         if (lines)
280                 destroy_lines(lines);
281
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);
285         } else {
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);
288         }
289
290         if (debug) {
291                 fprintf(stderr, "to = `%s`\n", to);
292                 fprintf(stderr, "subject = `%s`\n", subbuf);
293                 fprintf(stderr, "body = `%s`\n", bodybuf);
294         }
295
296         (void)submit_mail(to, subbuf, bodybuf);
297
298         free_appt_struct(&appt);
299
300         if (addr_data)
301                 free(addr_data);
302 }
303
304 extern void 
305 open_it(XtPointer client_data, XtIntervalId *interval_id, CSA_reminder_reference *r) {
306         Calendar        *c = (Calendar *)client_data;
307         
308         postup_show_proc(c, r);
309 }
310
311 extern void
312 reminder_driver(XtPointer client_data, XtIntervalId *interval_id) {
313         Calendar                *c = (Calendar *)client_data;
314         Tick                    run_tick;
315         int                     i;
316
317         if (c->view->next_alarm_id != *interval_id || !c->view->next_alarm) {
318                 c->view->next_alarm_id = 0;
319                 reset_timer(c);
320                 return;
321         }
322
323
324         /*
325          * do not handle the reminder if the time it's to happen
326          * is earlier than the current time
327          */
328         _csa_iso8601_to_tick(c->view->next_alarm[0].run_time, &run_tick);
329         if (now() >= run_tick) {
330
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]);
340
341                 }
342         }
343
344         c->view->next_alarm_id = 0;
345
346         reset_timer(c);
347 }
348
349 extern void
350 bell_ringer(XtPointer client_data, XtIntervalId *interval_id) {
351         Calendar        *c = (Calendar *)client_data;
352         XBell(c->xcontext->display, 50);
353         c->view->rings -= 1;
354         if (c->view->rings != 0)
355                 XtAppAddTimeOut(c->xcontext->app, 250, bell_ringer, c);
356 }
357
358 extern void
359 ring_it(XtPointer client_data, XtIntervalId *interval_id) {
360         Calendar        *c = (Calendar *)client_data;
361
362     if (c->view->rings == 0) {
363         c->view->rings = 5;
364         XtAppAddTimeOut(c->xcontext->app, 250, bell_ringer, c);
365     }
366
367     /* If the application is busy delivering a ring reminder
368        don't deliver another one. */
369 }
370
371 /*
372  * Close dialog: pop down and destroy the dialog, and free
373  * associated memory.
374  */
375 static void
376 close_cb(Widget w, XtPointer data, XtPointer ignore)
377 {
378         Widget shell = (Widget) data;
379
380         XtPopdown(shell);
381         XtDestroyWidget(shell);
382 }
383
384
385 /*
386 **  Functions to build and popup the postup reminder
387 */
388 extern void
389 postup_show_proc(Calendar *c, CSA_reminder_reference *r) {
390         int                     start_hr, stop_hr;
391         char                    text[BUFSIZ];
392         time_t                  st, sp = 0;
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;
400         XmString                xmstr;
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;
406         char                    *title;
407
408         if (!c->postup)
409                 c->postup = XtAppCreateShell("calendar_postup", "Dtcm",
410                         xmDialogShellWidgetClass, c->xcontext->display,
411                         NULL, 0);
412
413         /*
414         **  Create the Motif objects
415         */
416         title = XtNewString(catgets(c->DT_catd, 1, 839, "Calendar : Reminder"));
417         pu_frame = XtVaCreatePopupShell("pu_frame",
418                 topLevelShellWidgetClass, c->postup,
419                 XmNtitle, title,
420                 XmNmwmFunctions, MWM_FUNC_MOVE | MWM_FUNC_CLOSE,
421                 XmNdeleteResponse,      XmDESTROY,
422                 NULL);
423         XtFree(title);
424
425         pu_base_form = XtVaCreateWidget("pu_base_form",
426                 xmFormWidgetClass, pu_frame,
427                 NULL);
428
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,
434                 XmNleftOffset, 1,
435                 XmNrightOffset, 1,
436                 XmNtopOffset, 1,
437                 NULL);
438
439         pu_image = XtVaCreateWidget("pu_image",
440                 xmLabelGadgetClass, pu_text_form,
441                 XmNleftAttachment, XmATTACH_FORM,
442                 XmNtopAttachment, XmATTACH_FORM,
443                 XmNtopOffset, 5,
444                 XmNlabelType, XmPIXMAP,
445                 XmNlabelPixmap, ((Props_pu *)c->properties_pu)->postup_pixmap,
446                 NULL);
447
448         button_form = XtVaCreateWidget("pu_form",
449                 xmFormWidgetClass, pu_base_form,
450                 XmNbottomAttachment, XmATTACH_FORM,
451                 XmNbottomOffset, 2,
452                 XmNleftOffset, 1,
453                 XmNrightOffset, 1,
454                 XmNleftAttachment, XmATTACH_FORM,
455                 XmNrightAttachment, XmATTACH_FORM,
456                 XmNfractionBase, 3,
457                 NULL);
458
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,
466                 XmNleftPosition,        1,
467                 XmNrightPosition,       2,
468                 XmNbottomOffset,        1,
469                 XmNlabelString,         xmstr,
470                 NULL);
471         XmStringFree(xmstr);
472
473         separator = XtVaCreateWidget("separator",
474                 xmSeparatorGadgetClass,
475                 pu_base_form,
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,
482                 XmNtopOffset, 1,
483                 NULL);
484
485
486         pu_form = XtVaCreateWidget("pu_form",
487                 xmFormWidgetClass, pu_text_form,
488                 XmNtopAttachment, XmATTACH_FORM,
489                 XmNtopOffset, 1,
490                 XmNleftAttachment, XmATTACH_WIDGET,
491                 XmNleftWidget, pu_image,
492                 XmNverticalSpacing, 10,
493                 NULL);
494
495         pu_date = XtVaCreateWidget("pu_date",
496                 xmLabelGadgetClass, pu_form,
497                 XmNleftAttachment, XmATTACH_FORM,
498                 XmNtopAttachment, XmATTACH_FORM,
499                 NULL);
500
501         pu_range = XtVaCreateWidget("pu_range",
502                 xmLabelGadgetClass, pu_form,
503                 XmNleftAttachment, XmATTACH_FORM,
504                 XmNtopAttachment, XmATTACH_WIDGET,
505                 XmNtopWidget, pu_date,
506                 XmNtopOffset, 8,
507                 NULL);
508
509         XtAddCallback(pu_close, XmNactivateCallback, close_cb, pu_frame);
510
511         appt = allocate_appt_struct(appt_read,
512                                     c->general->version,
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,
517                                     NULL);
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);
523                 return;
524         }
525
526         _csa_iso8601_to_tick(appt->time->value->item.date_time_value, &st);
527         if (appt->end_time)
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);
531         last_line = 0;
532         while (l) {
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,
539                         XmNleftOffset, 15,
540                         NULL);
541                 XmStringFree(xmstr);
542
543                 if (last_line)
544                         XtVaSetValues(line, 
545                                 XmNtopAttachment, XmATTACH_WIDGET,
546                                 XmNtopWidget, last_line,
547                                 XmNtopOffset, 8,
548                                 NULL);
549                 else
550                         XtVaSetValues(line, 
551                                 XmNtopAttachment, XmATTACH_FORM,
552                                 XmNtopOffset, 8,
553                                 NULL);
554
555                 last_line = line;
556                 l = l->next;
557         }
558         if (lines)
559                 destroy_lines(lines);
560
561         /*
562         **  Now fill in the correct information
563         */
564         set_date_in_widget(st, pu_date, ord_t, sep_t);
565
566         if (!showtime_set(appt) || magic_time(st)) 
567                 text[0] = '\0';
568         else {
569                 start_hr = hour(st);
570                 if (sp) stop_hr = hour(sp);
571                 if (dis_t == HOUR12) {
572                         start_am = adjust_hour(&start_hr);
573                         if (sp) {
574                                 /* NL_COMMENT
575
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:
580
581                                    ``From 11:00am to 1:00pm''
582
583                                    In the printf conversion string the $n are:
584
585                                         $1      -> start hour
586                                         $2      -> start minute
587                                         $3      -> am or pm
588                                         $4      -> stop hour
589                                         $5      -> stop minute
590                                         $6      -> am or pm
591
592                                 */
593                                 char *am = XtNewString(catgets(c->DT_catd, 
594                                                                1, 4, "am"));
595                                 char *pm = XtNewString(catgets(c->DT_catd, 
596                                                                1, 3, "pm"));
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,
602                                         stop_hr, minute(sp),
603                                         (stop_am) ? am : pm
604                                         );
605                                 XtFree(am);
606                                 XtFree(pm);
607                         } else {
608                                 /* NL_COMMENT
609
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:
615
616                                    ``11:00am''
617
618                                    In the printf conversion string the $n are:
619
620                                         $1      -> start hour
621                                         $2      -> start minute
622                                         $3      -> am or pm
623
624                                 */
625                                 char *meridian = 
626                                   XtNewString ((start_am) ? 
627                                                catgets(c->DT_catd, 1, 4, "am"):
628                                                catgets(c->DT_catd, 1, 3, "pm"));
629                                 
630                                 sprintf(text, catgets(c->DT_catd, 1, 1088,
631                                                         "%1$2d:%2$02d%3$s"), 
632                                         start_hr, minute(st), meridian
633                                         );
634                                 XtFree(meridian);
635                         }
636                 } else {
637                         if (sp) {
638                                 /* NL_COMMENT
639
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:
646
647                                    ``From 0100 to 1600''
648
649                                    In the printf conversion string the $n are:
650
651                                         $1      -> start hour
652                                         $2      -> start minute
653                                         $3      -> stop hour
654                                         $4      -> stop minute
655
656                                 */
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, 
660                                         minute(sp));
661                         } else {
662                                 /* NL_COMMENT
663
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:
671
672                                    ``1600''
673
674                                    In the printf conversion string the $n are:
675
676                                         $1      -> start hour
677                                         $2      -> start minute
678
679                                 */
680                                 sprintf(text, catgets(c->DT_catd, 1, 1090,
681                                                         "%1$02d%2$02d"), 
682                                         start_hr, minute(st));
683                         }
684                 }
685         }
686
687         free_appt_struct(&appt);
688         xmstr = XmStringCreateLocalized(text);
689         XtVaSetValues(pu_range, XmNlabelString, xmstr,
690                 NULL);
691         XmStringFree(xmstr);
692
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));
701 }