Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtcm / dtcm / alarm.c
1 /*******************************************************************************
2 **
3 **  alarm.c
4 **
5 **  $XConsortium: alarm.c /main/4 1995/12/04 14:15:43 rswiston $
6 **
7 **  RESTRICTED CONFIDENTIAL INFORMATION:
8 **
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
15 **  Sun's request.
16 **
17 **  Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
18 **
19 *******************************************************************************/
20
21 /*                                                                      *
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.                                *
26  */
27
28 #ifndef lint
29 static  char sccsid[] = "@(#)alarm.c 1.50 95/07/27 Copyr 1991 Sun Microsystems, Inc.";
30 #endif
31
32 #include <EUSCompat.h>
33 #include <unistd.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <fcntl.h>
37 #include <sys/time.h>
38 #include <Xm/DialogS.h>
39 #include <Xm/Form.h>
40 #include <Xm/PushB.h>
41 #include <Xm/LabelG.h>
42 #include <Xm/SeparatoG.h>
43 #include <Xm/MwmUtil.h>
44 #include <Dt/Wsm.h>
45 #include <Dt/Session.h>
46 #include "calendar.h"
47 #include "alarm.h"
48 #include "misc.h"
49 #include "props_pu.h"
50 #include "timeops.h"
51 #include "util.h"
52
53 #ifdef AIX
54 #include <sys/select.h>
55 #endif
56
57 /*  Structure used on a save session to see if a dt is iconic  */
58 typedef struct
59 {
60    int state;
61    Window icon;
62 } WM_STATE;
63  
64
65
66 extern int debug;
67 extern int submit_mail(
68                 const char * to, const char * subject, const char * body);
69
70 /*******************************************************************************
71 **
72 **  Functions external to alarm.c
73 **
74 *******************************************************************************/
75
76 extern void
77 view_flasher(XtPointer client_data, XtIntervalId *interval_id) {
78     Calendar        *c = (Calendar *)client_data;
79     Atom        wmStateAtom, actualType;
80     int         actualFormat;
81     unsigned long nitems, leftover;
82     WM_STATE *wmState;
83  
84     /*  Getting the WM_STATE property to see if iconified or not */
85     wmStateAtom = XInternAtom(XtDisplay(c->frame), "WM_STATE", False);
86  
87     XGetWindowProperty (XtDisplay(c->frame), XtWindow(c->frame), 
88                         wmStateAtom, 0L,
89                         (long)BUFSIZ, False, wmStateAtom, &actualType,
90                         &actualFormat, &nitems, &leftover,
91                         (unsigned char **) &wmState);
92  
93     if (wmState->state == IconicState) {
94
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);
100         } else {
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);
105         }
106         XFlush(c->xcontext->display);
107     }
108     else {
109         XWindowAttributes       window_attributes;
110
111         XGetWindowAttributes(c->xcontext->display, 
112                                 XtWindowOfObject(c->form), 
113                                 &window_attributes);
114
115         XFillRectangle(c->xcontext->display, 
116                                 XtWindowOfObject(c->form), 
117                                 c->xcontext->invert_gc, 
118                                 0, 0, 
119                                 window_attributes.width, 
120                                 window_attributes.height);
121         XFlush(c->xcontext->display);
122     }
123
124     c->view->flashes -= 1;
125     if (c->view->flashes != 0)
126         XtAppAddTimeOut(c->xcontext->app, 250, view_flasher, c);
127     else {
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. */
131
132         XUnmapWindow(c->xcontext->display, XtWindowOfObject(c->form));
133         XMapWindow(c->xcontext->display, XtWindowOfObject(c->form));
134
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);
140         }
141     }
142 }
143
144 extern void 
145 flash_it(XtPointer client_data, XtIntervalId *interval_id) {
146     int         i, j;
147     Calendar    *c = (Calendar *)client_data;
148
149     if (c->view->flashes == 0) {
150         c->view->flashes = 10;
151         XtAppAddTimeOut(c->xcontext->app, 250, view_flasher, c);
152     }
153
154     /* if the application is busy delivering a flash reminder, 
155        don't deliver another one. */
156 }
157
158 extern void 
159 mail_it(XtPointer client_data, XtIntervalId *interval_id, CSA_reminder_reference *r) {
160         Calendar                *c = (Calendar *)client_data;
161         int                     hr;
162         Lines                   *lines = NULL, *l = NULL;
163         Props                   *p = (Props *)c->properties;
164         Boolean                 pm;
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];
170         char                    *to;
171         CSA_return_code         stat;
172         Tick                    start, stop;
173         char                    *addr_data = NULL;
174
175         appt = allocate_appt_struct(appt_read,
176                                     c->general->version,
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,
183                                     NULL);
184
185         stat = query_appt_struct(c->cal_handle, r->entry, appt);
186
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);
191                 return;
192         }
193
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 */
198                 if (debug)
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;
202         } else {
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);
205                 to = addr_data;
206         }
207
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");
212
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);
216
217         if (showtime_set(appt) && !magic_time(start)) {
218                 hr = hour(start);
219                 pm = (dt == HOUR12 && !adjust_hour(&hr)) ? True : False;
220                 if (dt == HOUR12) {
221                         sprintf(startbuf, "%2d:%02d %s", hr, minute(start),
222                                 pm ? "pm" :
223                                 "am");
224                 } else {
225                         sprintf(startbuf, "%02d%02d", hr, minute(start));
226                 }
227         } else
228                 startbuf[0] = '\0';
229
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);
233                 hr = hour(stop);
234                 pm = (dt == HOUR12 && !adjust_hour(&hr)) ? True : False;
235                 if (dt == HOUR12) {
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"));
239                 } else {
240                         sprintf(stopbuf, "%02d%02d", hr, minute(stop));
241                 }
242         } else
243                 stopbuf[0] = '\0';
244
245         if (l = lines) {
246                 sprintf(whatbuf, "%s\n", l->s);
247                 l = l->next;
248         } else
249                 whatbuf[0] = '\0';
250
251         while(l != NULL) {
252                 strcat(whatbuf, "\t\t");
253                 strcat(whatbuf, l->s);
254                 strcat(whatbuf, "\n");
255                 l = l->next;
256         }
257         if (lines)
258                 destroy_lines(lines);
259
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);
263         } else {
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);
266         }
267
268         if (debug) {
269                 fprintf(stderr, "to = `%s`\n", to);
270                 fprintf(stderr, "subject = `%s`\n", subbuf);
271                 fprintf(stderr, "body = `%s`\n", bodybuf);
272         }
273
274         (void)submit_mail(to, subbuf, bodybuf);
275
276         free_appt_struct(&appt);
277
278         if (addr_data)
279                 free(addr_data);
280 }
281
282 extern void 
283 open_it(XtPointer client_data, XtIntervalId *interval_id, CSA_reminder_reference *r) {
284         Calendar        *c = (Calendar *)client_data;
285         
286         postup_show_proc(c, r);
287 }
288
289 extern void
290 reminder_driver(XtPointer client_data, XtIntervalId *interval_id) {
291         Calendar                *c = (Calendar *)client_data;
292         Tick                    run_tick;
293         int                     i;
294
295         if (c->view->next_alarm_id != *interval_id || !c->view->next_alarm) {
296                 c->view->next_alarm_id = 0;
297                 reset_timer(c);
298                 return;
299         }
300
301
302         /*
303          * do not handle the reminder if the time it's to happen
304          * is earlier than the current time
305          */
306         _csa_iso8601_to_tick(c->view->next_alarm[0].run_time, &run_tick);
307         if (now() >= run_tick) {
308
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]);
318
319                 }
320         }
321
322         c->view->next_alarm_id = 0;
323
324         reset_timer(c);
325 }
326
327 extern void
328 bell_ringer(XtPointer client_data, XtIntervalId *interval_id) {
329         Calendar        *c = (Calendar *)client_data;
330         XBell(c->xcontext->display, 50);
331         c->view->rings -= 1;
332         if (c->view->rings != 0)
333                 XtAppAddTimeOut(c->xcontext->app, 250, bell_ringer, c);
334 }
335
336 extern void
337 ring_it(XtPointer client_data, XtIntervalId *interval_id) {
338         Calendar        *c = (Calendar *)client_data;
339
340     if (c->view->rings == 0) {
341         c->view->rings = 5;
342         XtAppAddTimeOut(c->xcontext->app, 250, bell_ringer, c);
343     }
344
345     /* If the application is busy delivering a ring reminder
346        don't deliver another one. */
347 }
348
349 /*
350  * Close dialog: pop down and destroy the dialog, and free
351  * associated memory.
352  */
353 static void
354 close_cb(Widget w, XtPointer data, XtPointer ignore)
355 {
356         Widget shell = (Widget) data;
357
358         XtPopdown(shell);
359         XtDestroyWidget(shell);
360 }
361
362
363 /*
364 **  Functions to build and popup the postup reminder
365 */
366 extern void
367 postup_show_proc(Calendar *c, CSA_reminder_reference *r) {
368         int                     start_hr, stop_hr;
369         char                    text[BUFSIZ];
370         time_t                  st, sp = 0;
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;
378         XmString                xmstr;
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;
384         char                    *title;
385
386         if (!c->postup)
387                 c->postup = XtAppCreateShell("calendar_postup", "Dtcm",
388                         xmDialogShellWidgetClass, c->xcontext->display,
389                         NULL, 0);
390
391         /*
392         **  Create the Motif objects
393         */
394         title = XtNewString(catgets(c->DT_catd, 1, 839, "Calendar : Reminder"));
395         pu_frame = XtVaCreatePopupShell("pu_frame",
396                 topLevelShellWidgetClass, c->postup,
397                 XmNtitle, title,
398                 XmNmwmFunctions, MWM_FUNC_MOVE | MWM_FUNC_CLOSE,
399                 XmNdeleteResponse,      XmDESTROY,
400                 NULL);
401         XtFree(title);
402
403         pu_base_form = XtVaCreateWidget("pu_base_form",
404                 xmFormWidgetClass, pu_frame,
405                 NULL);
406
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,
412                 XmNleftOffset, 1,
413                 XmNrightOffset, 1,
414                 XmNtopOffset, 1,
415                 NULL);
416
417         pu_image = XtVaCreateWidget("pu_image",
418                 xmLabelGadgetClass, pu_text_form,
419                 XmNleftAttachment, XmATTACH_FORM,
420                 XmNtopAttachment, XmATTACH_FORM,
421                 XmNtopOffset, 5,
422                 XmNlabelType, XmPIXMAP,
423                 XmNlabelPixmap, ((Props_pu *)c->properties_pu)->postup_pixmap,
424                 NULL);
425
426         button_form = XtVaCreateWidget("pu_form",
427                 xmFormWidgetClass, pu_base_form,
428                 XmNbottomAttachment, XmATTACH_FORM,
429                 XmNbottomOffset, 2,
430                 XmNleftOffset, 1,
431                 XmNrightOffset, 1,
432                 XmNleftAttachment, XmATTACH_FORM,
433                 XmNrightAttachment, XmATTACH_FORM,
434                 XmNfractionBase, 3,
435                 NULL);
436
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,
444                 XmNleftPosition,        1,
445                 XmNrightPosition,       2,
446                 XmNbottomOffset,        1,
447                 XmNlabelString,         xmstr,
448                 NULL);
449         XmStringFree(xmstr);
450
451         separator = XtVaCreateWidget("separator",
452                 xmSeparatorGadgetClass,
453                 pu_base_form,
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,
460                 XmNtopOffset, 1,
461                 NULL);
462
463
464         pu_form = XtVaCreateWidget("pu_form",
465                 xmFormWidgetClass, pu_text_form,
466                 XmNtopAttachment, XmATTACH_FORM,
467                 XmNtopOffset, 1,
468                 XmNleftAttachment, XmATTACH_WIDGET,
469                 XmNleftWidget, pu_image,
470                 XmNverticalSpacing, 10,
471                 NULL);
472
473         pu_date = XtVaCreateWidget("pu_date",
474                 xmLabelGadgetClass, pu_form,
475                 XmNleftAttachment, XmATTACH_FORM,
476                 XmNtopAttachment, XmATTACH_FORM,
477                 NULL);
478
479         pu_range = XtVaCreateWidget("pu_range",
480                 xmLabelGadgetClass, pu_form,
481                 XmNleftAttachment, XmATTACH_FORM,
482                 XmNtopAttachment, XmATTACH_WIDGET,
483                 XmNtopWidget, pu_date,
484                 XmNtopOffset, 8,
485                 NULL);
486
487         XtAddCallback(pu_close, XmNactivateCallback, close_cb, pu_frame);
488
489         appt = allocate_appt_struct(appt_read,
490                                     c->general->version,
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,
495                                     NULL);
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);
501                 return;
502         }
503
504         _csa_iso8601_to_tick(appt->time->value->item.date_time_value, &st);
505         if (appt->end_time)
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);
509         last_line = 0;
510         while (l) {
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,
517                         XmNleftOffset, 15,
518                         NULL);
519                 XmStringFree(xmstr);
520
521                 if (last_line)
522                         XtVaSetValues(line, 
523                                 XmNtopAttachment, XmATTACH_WIDGET,
524                                 XmNtopWidget, last_line,
525                                 XmNtopOffset, 8,
526                                 NULL);
527                 else
528                         XtVaSetValues(line, 
529                                 XmNtopAttachment, XmATTACH_FORM,
530                                 XmNtopOffset, 8,
531                                 NULL);
532
533                 last_line = line;
534                 l = l->next;
535         }
536         if (lines)
537                 destroy_lines(lines);
538
539         /*
540         **  Now fill in the correct information
541         */
542         set_date_in_widget(st, pu_date, ord_t, sep_t);
543
544         if (!showtime_set(appt) || magic_time(st)) 
545                 text[0] = '\0';
546         else {
547                 start_hr = hour(st);
548                 if (sp) stop_hr = hour(sp);
549                 if (dis_t == HOUR12) {
550                         start_am = adjust_hour(&start_hr);
551                         if (sp) {
552                                 /* NL_COMMENT
553
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:
558
559                                    ``From 11:00am to 1:00pm''
560
561                                    In the printf conversion string the $n are:
562
563                                         $1      -> start hour
564                                         $2      -> start minute
565                                         $3      -> am or pm
566                                         $4      -> stop hour
567                                         $5      -> stop minute
568                                         $6      -> am or pm
569
570                                 */
571                                 char *am = XtNewString(catgets(c->DT_catd, 
572                                                                1, 4, "am"));
573                                 char *pm = XtNewString(catgets(c->DT_catd, 
574                                                                1, 3, "pm"));
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,
580                                         stop_hr, minute(sp),
581                                         (stop_am) ? am : pm
582                                         );
583                                 XtFree(am);
584                                 XtFree(pm);
585                         } else {
586                                 /* NL_COMMENT
587
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:
593
594                                    ``11:00am''
595
596                                    In the printf conversion string the $n are:
597
598                                         $1      -> start hour
599                                         $2      -> start minute
600                                         $3      -> am or pm
601
602                                 */
603                                 char *meridian = 
604                                   XtNewString ((start_am) ? 
605                                                catgets(c->DT_catd, 1, 4, "am"):
606                                                catgets(c->DT_catd, 1, 3, "pm"));
607                                 
608                                 sprintf(text, catgets(c->DT_catd, 1, 1088,
609                                                         "%1$2d:%2$02d%3$s"), 
610                                         start_hr, minute(st), meridian
611                                         );
612                                 XtFree(meridian);
613                         }
614                 } else {
615                         if (sp) {
616                                 /* NL_COMMENT
617
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:
624
625                                    ``From 0100 to 1600''
626
627                                    In the printf conversion string the $n are:
628
629                                         $1      -> start hour
630                                         $2      -> start minute
631                                         $3      -> stop hour
632                                         $4      -> stop minute
633
634                                 */
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, 
638                                         minute(sp));
639                         } else {
640                                 /* NL_COMMENT
641
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:
649
650                                    ``1600''
651
652                                    In the printf conversion string the $n are:
653
654                                         $1      -> start hour
655                                         $2      -> start minute
656
657                                 */
658                                 sprintf(text, catgets(c->DT_catd, 1, 1090,
659                                                         "%1$02d%2$02d"), 
660                                         start_hr, minute(st));
661                         }
662                 }
663         }
664
665         free_appt_struct(&appt);
666         xmstr = XmStringCreateLocalized(text);
667         XtVaSetValues(pu_range, XmNlabelString, xmstr,
668                 NULL);
669         XmStringFree(xmstr);
670
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));
679 }