Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtcm / dtcm / dssw.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 **  dssw.c
26 **
27 **  $XConsortium: dssw.c /main/7 1996/10/14 16:06:20 barstow $
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[] = "@(#)dssw.c 1.58 95/08/07 Copyr 1993 Sun Microsystems, Inc.";
52 #endif
53
54 #include <EUSCompat.h>
55 #include <stdlib.h>
56 #include <Xm/Xm.h>
57 #include <Xm/Form.h>
58 #include <Xm/RowColumn.h>
59 #include <Xm/Text.h>
60 #include <Xm/LabelG.h>
61 #include <Xm/ToggleBG.h>
62 #include <Xm/ToggleB.h>
63 #include "dssw.h"
64 #include "misc.h"
65 #include "getdate.h"
66 #include "props_pu.h"
67 #include "util.h"
68 #ifdef SVR4
69 #include <sys/param.h>
70 #endif /* SVR4 */
71
72 extern Dimension ComputeMaxWidth(Widget, Widget, Widget, Widget);
73
74
75 /*******************************************************************************
76 **
77 **  Static functions visible to dssw.c only
78 **
79 *******************************************************************************/
80 static void
81 dssw_get_non_times(DSSW *dssw, time_t t) {
82         char            *str;
83         Props           *p = (Props *)dssw->cal->properties;
84         OrderingType    ot = get_int_prop(p, CP_DATEORDERING);
85         SeparatorType   st = get_int_prop(p, CP_DATESEPARATOR);
86
87         cm_strcpy(dssw->date_val,
88                 get_date_from_widget(t, dssw->date_text, ot, st));
89
90         str = XmTextGetString(dssw->what_text);
91         strcpy(dssw->what_val, str);
92         XtFree(str);
93 }
94
95 static void
96 dssw_set_non_times(DSSW *dssw, time_t t) {
97         Props           *p = (Props *)dssw->cal->properties;
98         OrderingType    ot = get_int_prop(p, CP_DATEORDERING);
99         SeparatorType   st = get_int_prop(p, CP_DATESEPARATOR);
100
101         set_date_in_widget(t, dssw->date_text, ot, st);
102         XmTextSetString(dssw->what_text, dssw->what_val);
103 }
104
105 /*
106 **  Callback from start time and stop time to set text fields accordingly
107 */
108 static void
109 dssw_set_start_hour(Widget w, XtPointer client_data, XtPointer cbs) {
110         int             start_hrs, stop_hrs, dur, start_mins, stop_mins;
111         long            user_data;
112         DSSW            *dssw = (DSSW *)client_data;
113         Props           *p = (Props *)dssw->cal->properties;
114         DisplayType     dt = get_int_prop(p, CP_DEFAULTDISP);
115
116         XtVaGetValues(w, XmNuserData, &user_data, NULL);
117
118         if (user_data == NO_TIME) {
119                 sprintf(dssw->start_val.val, "\0");
120                 sprintf(dssw->stop_val.val, "\0");
121                 dssw->start_val.block = dssw->stop_val.block = TIME_AM;
122         } else if (user_data == ALL_DAY) {
123                 if (dt == HOUR12) {
124                         sprintf(dssw->start_val.val, "12:00");
125                         sprintf(dssw->stop_val.val, "11:59");
126                 } else {
127                         sprintf(dssw->start_val.val, "0000");
128                         sprintf(dssw->stop_val.val, "2359");
129                 }
130                 dssw->start_val.block = TIME_AM;
131                 dssw->stop_val.block = TIME_PM;
132         } else {
133                 start_hrs = user_data / hrsec;
134                 dur = get_int_prop(p, CP_APPTDURATION) * minsec;
135                 stop_hrs = (user_data + dur) / hrsec;
136                 start_mins = (user_data - (start_hrs * hrsec)) / minsec;
137                 stop_mins = ((user_data + dur) - (stop_hrs * hrsec)) / minsec;
138                 stop_hrs = stop_hrs % 24;
139
140                 if (dt == HOUR12) {
141                         dssw->start_val.block =
142                                 (adjust_hour(&start_hrs)) ? TIME_AM : TIME_PM;
143                         dssw->stop_val.block =
144                                 (adjust_hour(&stop_hrs)) ? TIME_AM : TIME_PM;
145                         sprintf(dssw->start_val.val, "%2d:%02d",
146                                 start_hrs, start_mins);
147                         sprintf(dssw->stop_val.val, "%2d:%02d",
148                                 stop_hrs, stop_mins);
149                 } else {
150                         dssw->start_val.block =
151                                 (start_hrs > 12) ? TIME_PM : TIME_AM;
152                         dssw->stop_val.block =
153                                 (stop_hrs > 12) ? TIME_PM : TIME_AM;
154                         sprintf(dssw->start_val.val, "%02d%02d",
155                                 start_hrs, start_mins);
156                         sprintf(dssw->stop_val.val, "%02d%02d",
157                                 stop_hrs, stop_mins);
158                 }
159         }
160         set_dssw_times(dssw);
161 }
162
163 static void
164 dssw_set_stop_hour(Widget w, XtPointer client_data, XtPointer cbs) {
165         long            user_data;
166         int             hrs, mins;
167         DSSW            *dssw = (DSSW *)client_data;
168         Props           *p = (Props *)dssw->cal->properties;
169         DisplayType     dt = get_int_prop(p, CP_DEFAULTDISP);
170
171         get_dssw_times(dssw);
172         XtVaGetValues(w, XmNuserData, &user_data, NULL);
173
174         if (user_data == NO_TIME) {
175                 sprintf(dssw->stop_val.val, "\0");
176                 dssw->stop_val.block = TIME_AM;
177         } else {
178                 hrs = user_data / hrsec;
179                 mins = (user_data - (hrs * hrsec)) / minsec;
180
181                 if (dt == HOUR12) {
182                         dssw->stop_val.block =
183                                 (adjust_hour(&hrs)) ? TIME_AM : TIME_PM;
184                         sprintf(dssw->stop_val.val, "%2d:%02d", hrs, mins);
185                 } else {
186                         dssw->stop_val.block = (hrs > 12) ? TIME_PM : TIME_AM;
187                         sprintf(dssw->stop_val.val, "%02d%02d", hrs, mins);
188                 }
189         }
190         set_dssw_times(dssw);
191 }
192
193 /*******************************************************************************
194 **
195 **  External functions
196 **
197 *******************************************************************************/
198
199 extern void
200 set_dssw_menus(DSSW *dssw, Props *p) {
201
202         set_time_submenu(dssw->dssw_form_mgr, dssw->start_menu, p, 
203                          dssw_set_start_hour, (XtPointer)dssw, 
204                          dssw->show_notime_selection, dssw->show_allday_selection,
205                          &dssw->start_menu_widget_list, &dssw->start_menu_widget_count);
206
207         set_time_submenu(dssw->dssw_form_mgr, dssw->stop_menu, p, 
208                          dssw_set_stop_hour, (XtPointer)dssw, dssw->show_notime_selection, False,
209                          &dssw->stop_menu_widget_list, &dssw->stop_menu_widget_count);
210
211         set_dssw_defaults(dssw, calendar->view->date, True);
212
213 }
214
215 #define GAP     5
216
217 extern void
218 build_dssw(
219         DSSW            *dssw, 
220         Calendar        *c, 
221         Widget           parent, 
222         Boolean          show_notime, 
223         Boolean          show_allday)
224 {
225         Props           *p;
226         DisplayType      dt;
227         Arg              args[20];
228         int              n;
229         Dimension       max_left_label_width;
230         Widget          child[2];
231         XmString        label_str;
232         Dimension       highest, widest;
233         Widget          prev, curr;
234         Dimension       _toLabel, _toText, _toMenu, _toRC;
235
236         dssw->cal = c;
237         dssw->parent = parent;
238         p = (Props *)c->properties;
239
240         dt = get_int_prop(p, CP_DEFAULTDISP);
241
242         dssw->show_notime_selection = show_notime;
243         dssw->show_allday_selection = show_allday;
244
245         /*
246         **  One form manager for the widget
247         */
248         dssw->dssw_form_mgr = XtVaCreateWidget("dssw_form_mgr",
249                 xmFormWidgetClass,      parent,
250                 XmNautoUnmanage,        False,
251                 NULL);
252
253         label_str = XmStringCreateLocalized(catgets(c->DT_catd, 1, 828, "Date:"));
254         dssw->date_label = XtVaCreateWidget("date_label",
255                 xmLabelGadgetClass,     dssw->dssw_form_mgr,
256                 XmNlabelString,         label_str,
257                 NULL);
258         XmStringFree(label_str);
259
260         label_str = XmStringCreateLocalized(catgets(c->DT_catd, 1, 829, "Start:"));
261         dssw->start_label = XtVaCreateWidget("start_label",
262                 xmLabelGadgetClass,     dssw->dssw_form_mgr,
263                 XmNlabelString,         label_str,
264                 NULL);
265         XmStringFree(label_str);
266
267         label_str = XmStringCreateLocalized(catgets(c->DT_catd, 1, 832, "End:"));
268         dssw->stop_label = XtVaCreateWidget("stop_label",
269                 xmLabelGadgetClass,     dssw->dssw_form_mgr,
270                 XmNlabelString,         label_str,
271                 NULL);
272         XmStringFree(label_str);
273
274         label_str = XmStringCreateLocalized(catgets(c->DT_catd, 1, 835, "What:"));
275         dssw->what_label = XtVaCreateWidget("what_label",
276                 xmLabelGadgetClass,     dssw->dssw_form_mgr,
277                 XmNlabelString,         label_str,
278                 NULL);
279         XmStringFree(label_str);
280  
281         dssw->date_text = XtVaCreateWidget("date_text",
282                 xmTextWidgetClass,      dssw->dssw_form_mgr,
283                 XmNeditMode,            XmSINGLE_LINE_EDIT,
284                 XmNmaxLength,           DATE_LEN - 1,
285                 NULL);
286  
287         /*
288         **  Radio button behavior for AM/PM selection for start time
289         */
290         dssw->start_text = XtVaCreateWidget("start_text",
291                 xmTextWidgetClass,      dssw->dssw_form_mgr,
292                 XmNeditMode,            XmSINGLE_LINE_EDIT,
293                 XmNmaxLength,           START_STOP_LEN - 1,
294                 NULL);
295
296         dssw->start_menu = create_start_stop_time_menu(dssw->dssw_form_mgr,
297                 NULL, dssw_set_start_hour, (XtPointer)dssw, p, show_notime, 
298                 show_allday, &dssw->start_menu_widget_list, 
299                 &dssw->start_menu_widget_count);
300
301         XtVaSetValues(dssw->start_menu,
302                 XmNnavigationType,      XmTAB_GROUP,
303                 NULL);
304
305         dssw->start_ampm_rc_mgr = XtVaCreateWidget("start_ampm_rc_mgr",
306                 xmRowColumnWidgetClass, dssw->dssw_form_mgr,
307                 XmNpacking,             XmPACK_COLUMN,
308                 XmNorientation,         XmHORIZONTAL,
309                 XmNradioBehavior,       True,
310                 XmNisHomogeneous,       True,
311                 XmNentryClass,          xmToggleButtonGadgetClass,
312                 NULL);
313
314         label_str = XmStringCreateLocalized(catgets(c->DT_catd, 1, 830, "AM"));
315         child[0] = dssw->start_am = XtVaCreateWidget("start_am",
316                 xmToggleButtonGadgetClass, dssw->start_ampm_rc_mgr,
317                 XmNlabelString,         label_str,
318                 XmNsensitive,           (dt == HOUR12) ? True : False,
319                 NULL);      
320         XmStringFree(label_str);
321
322         label_str = XmStringCreateLocalized(catgets(c->DT_catd, 1, 831, "PM"));
323         child[1] = dssw->start_pm = XtVaCreateWidget("start_pm",
324                 xmToggleButtonGadgetClass, dssw->start_ampm_rc_mgr,
325                 XmNlabelString,         label_str,
326                 XmNsensitive,           (dt == HOUR12) ? True : False,
327                 NULL);      
328         XmStringFree(label_str);
329
330         XtManageChildren(child, 2);
331
332         /*
333         **  Last and near the end, the stop stuff
334         **  Radio button behavior for AM/PM selection for stop time
335         */
336         dssw->stop_text = XtVaCreateWidget("stop_text",
337                 xmTextWidgetClass,      dssw->dssw_form_mgr,
338                 XmNeditMode,            XmSINGLE_LINE_EDIT,
339                 XmNmaxLength,           START_STOP_LEN - 1,
340                 NULL);
341
342         dssw->stop_menu = create_start_stop_time_menu(dssw->dssw_form_mgr,
343                 NULL, dssw_set_stop_hour, (XtPointer)dssw, p, show_notime, 
344                 False, &dssw->stop_menu_widget_list, 
345                 &dssw->stop_menu_widget_count);
346
347         XtVaSetValues(dssw->stop_menu,
348                 XmNnavigationType,      XmTAB_GROUP,
349                 NULL);
350
351         dssw->stop_ampm_rc_mgr = XtVaCreateWidget("stop_ampm_rc_mgr",
352                 xmRowColumnWidgetClass, dssw->dssw_form_mgr,
353                 XmNpacking,             XmPACK_COLUMN,
354                 XmNorientation,         XmHORIZONTAL,
355                 XmNradioBehavior,       True,
356                 XmNisHomogeneous,       True,
357                 XmNentryClass,          xmToggleButtonGadgetClass,
358                 NULL);
359
360         label_str = XmStringCreateLocalized(catgets(c->DT_catd, 1, 833, "AM"));
361         child[0] = dssw->stop_am = XtVaCreateWidget("stop_am",
362                 xmToggleButtonGadgetClass, dssw->stop_ampm_rc_mgr,
363                 XmNlabelString,         label_str,
364                 XmNsensitive,           (dt == HOUR12) ? True : False,
365                 NULL);      
366         XmStringFree(label_str);
367
368         label_str = XmStringCreateLocalized(catgets(c->DT_catd, 1, 834, "PM"));
369         child[1] = dssw->stop_pm = XtVaCreateWidget("stop_pm",
370                 xmToggleButtonGadgetClass, dssw->stop_ampm_rc_mgr,
371                 XmNlabelString,         label_str,
372                 XmNsensitive,           (dt == HOUR12) ? True : False,
373                 NULL);      
374         XmStringFree(label_str);
375
376         XtManageChildren(child, 2);
377
378
379         /*
380         **  Finally the what text field
381         */
382         n = 0;
383         XtSetArg(args[n], XmNeditMode,          XmMULTI_LINE_EDIT), n++;
384 /*      XtSetArg(args[n], XmNscrollVertical,    True), n++;  */
385         XtSetArg(args[n], XmNscrollHorizontal,  False), n++; 
386         XtSetArg(args[n], XmNscrollingPolicy,   XmAUTOMATIC), n++; 
387         XtSetArg(args[n], XmNscrollBarDisplayPolicy, XmAS_NEEDED), n++;
388         XtSetArg(args[n], XmNrows,              3), n++;
389         XtSetArg(args[n], XmNmaxLength,         WHAT_LEN - 1), n++;
390
391         dssw->what_text = XmCreateScrolledText(dssw->dssw_form_mgr, 
392                                                "what_text", args, n);
393
394         dssw->what_scrollwindow = XtParent(dssw->what_text);
395         XtManageChild(dssw->what_text);
396
397         /*
398          * Do a layout
399          */
400         _i18n_WidestWidget( 4, &prev, &max_left_label_width,
401                 dssw->date_label, dssw->start_label, dssw->stop_label,
402                 dssw->what_label );
403         _toText = max_left_label_width + 2 * GAP;
404
405         /*
406          * dssw->date_label, dssw->date_text
407          */
408         _i18n_WidestWidget( 1, &curr, &widest, dssw->date_label );
409         _toLabel = _toText - GAP - widest;
410         _i18n_HighestWidgetAdjust( 2, &curr, &highest, dssw->date_label,
411                                         dssw->date_text );
412         XtVaSetValues( curr,
413                         XmNtopAttachment, XmATTACH_FORM,
414                         XmNtopOffset, GAP,
415                         NULL );
416         XtVaSetValues( dssw->date_label,
417                         XmNleftAttachment, XmATTACH_FORM,
418                         XmNleftOffset, _toLabel,
419                         NULL );
420         XtVaSetValues( dssw->date_text,
421                         XmNleftAttachment, XmATTACH_FORM,
422                         XmNleftOffset, _toText,
423                         XmNrightAttachment, XmATTACH_FORM,
424                         NULL );
425         prev = curr;
426
427         /*
428          * dssw->start_label, dssw->start_text, dssw->start_menu,
429          * dssw->start_ampm_rc_mgr
430          */
431         _i18n_WidestWidget( 1, &curr, &widest, dssw->start_label );
432         _toLabel = _toText - GAP - widest;
433         _i18n_WidestWidget( 1, &curr, &widest, dssw->start_text );
434         _toMenu = _toText + widest + GAP;
435         _i18n_WidestWidget( 1, &curr, &widest, dssw->start_menu );
436         _toRC = _toMenu + widest + GAP;
437         _i18n_HighestWidgetAdjust( 4, &curr, &highest, dssw->start_label,
438                 dssw->start_text, dssw->start_menu, dssw->start_ampm_rc_mgr );
439         XtVaSetValues( curr,
440                         XmNtopAttachment, XmATTACH_WIDGET,
441                         XmNtopWidget, prev,
442                         XmNtopOffset, GAP,
443                         NULL );
444         XtVaSetValues( dssw->start_label,
445                         XmNleftAttachment, XmATTACH_FORM,
446                         XmNleftOffset, _toLabel,
447                         NULL );
448         XtVaSetValues( dssw->start_text,
449                         XmNleftAttachment, XmATTACH_FORM,
450                         XmNleftOffset, _toText,
451                         NULL );
452         XtVaSetValues( dssw->start_menu,
453                         XmNleftAttachment, XmATTACH_FORM,
454                         XmNleftOffset, _toMenu,
455                         NULL );
456         XtVaSetValues( dssw->start_ampm_rc_mgr,
457                         XmNleftAttachment, XmATTACH_FORM,
458                         XmNleftOffset, _toRC,
459                         NULL );
460         prev = curr;
461
462         /*
463          * dssw->stop_label, dssw->stop_text, dssw->stop_menu,
464          * dssw->stop_ampm_rc_mgr
465          */
466         _i18n_WidestWidget( 1, &curr, &widest, dssw->stop_label );
467         _toLabel = _toText - GAP - widest;
468         _i18n_WidestWidget( 1, &curr, &widest, dssw->stop_text );
469         _toMenu = _toText + widest + GAP;
470         _i18n_WidestWidget( 1, &curr, &widest, dssw->stop_menu );
471         _toRC = _toMenu + widest + GAP;
472         _i18n_HighestWidgetAdjust( 4, &curr, &highest, dssw->stop_label,
473                 dssw->stop_text, dssw->stop_menu, dssw->stop_ampm_rc_mgr );
474         XtVaSetValues( curr,
475                         XmNtopAttachment, XmATTACH_WIDGET,
476                         XmNtopWidget, prev,
477                         XmNtopOffset, GAP,
478                         NULL );
479         XtVaSetValues( dssw->stop_label,
480                         XmNleftAttachment, XmATTACH_FORM,
481                         XmNleftOffset, _toLabel,
482                         NULL );
483         XtVaSetValues( dssw->stop_text,
484                         XmNleftAttachment, XmATTACH_FORM,
485                         XmNleftOffset, _toText,
486                         NULL );
487         XtVaSetValues( dssw->stop_menu,
488                         XmNleftAttachment, XmATTACH_FORM,
489                         XmNleftOffset, _toMenu,
490                         NULL );
491         XtVaSetValues( dssw->stop_ampm_rc_mgr,
492                         XmNleftAttachment, XmATTACH_FORM,
493                         XmNleftOffset, _toRC,
494                         NULL );
495         prev = curr;
496
497         /*
498          * dssw->what_label, dssw->what_scrollwindow
499          */
500         _i18n_WidestWidget( 1, &curr, &widest, dssw->what_label );
501         _toLabel = _toText - GAP - widest;
502         XtVaSetValues( dssw->what_label,
503                         XmNtopAttachment, XmATTACH_WIDGET,
504                         XmNtopWidget, prev,
505                         XmNtopOffset, GAP,
506                         XmNleftAttachment, XmATTACH_FORM,
507                         XmNleftOffset, _toLabel,
508                         NULL );
509         XtVaSetValues( dssw->what_scrollwindow,
510                         XmNtopAttachment, XmATTACH_WIDGET,
511                         XmNtopWidget, prev,
512                         XmNtopOffset, GAP,
513                         XmNleftAttachment, XmATTACH_FORM,
514                         XmNleftOffset, _toText,
515                         XmNrightAttachment, XmATTACH_FORM,
516                         XmNbottomAttachment, XmATTACH_FORM,
517                         NULL );
518 }
519
520 /*
521 **  This function will consume form values and stuff them into an appointment.
522 */
523 extern Boolean
524 dssw_form_to_appt(DSSW *dssw, Dtcm_appointment *a, char *name, Tick t)
525 {
526   return dssw_form_flags_to_appt(dssw, a, name, t, (int *)NULL);
527 }
528
529 extern Boolean
530 dssw_form_flags_to_appt(DSSW *dssw, Dtcm_appointment *a, char *name, Tick t, int *flagsP)
531 {
532         time_t          start_tick, stop_tick;
533         char            ampm_buf[BUFSIZ], buf[BUFSIZ];
534         Props           *p = (Props *)dssw->cal->properties;
535         Props_pu        *pu = (Props_pu *)dssw->cal->properties_pu;
536         DisplayType     dt = get_int_prop(p, CP_DEFAULTDISP);
537         int             flags = 0;
538
539         if (flagsP == (int *)NULL)
540           flagsP = &flags;
541
542         /*
543         **  If neither start nor end times exist, then the start time is set
544         **  to 3:41am (magic time) and the end time to 3:41 plus one minute.
545         */
546         get_dssw_vals(dssw, t);
547         if (blank_buf(dssw->date_val)) {
548                 editor_err_msg(dssw->parent, name, MISSING_DATE,
549                                pu->xm_error_pixmap);
550                 return False;
551         }
552
553         if (!blank_buf(dssw->start_val.val)) {
554                 if (!valid_time(p, dssw->start_val.val)) {
555                         if (a->type->value->item.sint32_value == CSA_TYPE_TODO)
556                                 editor_err_msg(dssw->parent, name, 
557                                                INVALID_TIME_DUE,
558                                                pu->xm_error_pixmap);
559                         else
560                                 editor_err_msg(dssw->parent, name, 
561                                                INVALID_START,
562                                                pu->xm_error_pixmap);
563                         return False;
564                 }
565
566                 if (dt == HOUR12) {
567                         /* am and pm should not be translated.  They are only
568                          * used in the date parsing code and never shown to
569                          * the user.
570                          */
571                         if (dssw->start_val.block == TIME_AM)
572                                 sprintf(ampm_buf, "am");
573                         else
574                                 sprintf(ampm_buf, "pm");
575                 } else
576                         ampm_buf[0] = '\0';
577
578                 sprintf(buf, "%s %s%s",
579                         dssw->date_val, dssw->start_val.val, ampm_buf); 
580
581                 if (!blank_buf(dssw->stop_val.val)
582                         && !valid_time(p, dssw->stop_val.val)) {
583                         editor_err_msg(dssw->parent, name, INVALID_STOP,
584                                 pu->xm_error_pixmap);
585                         return False;
586                 }
587         } else if (!blank_buf(dssw->stop_val.val)) {
588                 editor_err_msg(dssw->parent, name, MISSING_START,
589                         pu->xm_error_pixmap);
590                 return False;
591         } else
592                 sprintf(buf, "%s 3:41am", dssw->date_val);
593
594         start_tick = cm_getdate(buf, NULL);
595         if(start_tick < 0) {
596                 editor_err_msg(dssw->parent, name, INVALID_DATE,
597                         pu->xm_error_pixmap);
598                 return False;
599         }
600
601         if (blank_buf(dssw->what_val) && blank_buf(dssw->start_val.val)
602                 && blank_buf(dssw->stop_val.val)) {
603                 editor_err_msg(dssw->parent, name, INVALID_NOTIME_APPT,
604                         pu->xm_error_pixmap);
605                 return False;
606         }
607
608         a->time->value->item.date_time_value = (char *) malloc(BUFSIZ);
609         _csa_tick_to_iso8601(start_tick, a->time->value->item.date_time_value);
610         a->what->value->item.string_value = (char *)cm_strdup(dssw->what_val);
611         a->show_time->value->item.sint32_value = True;
612
613         if (!blank_buf(dssw->stop_val.val)) {
614                 if (dt == HOUR12) {
615                         /* am and pm should not be translated.  They are only
616                          * used in the date parsing code and never shown to
617                          * the user.
618                          */
619                         if (dssw->stop_val.block == TIME_AM)
620                                 sprintf(ampm_buf, "am");
621                         else
622                                 sprintf(ampm_buf, "pm");
623                 } else
624                         ampm_buf[0] = '\0';
625
626                 sprintf(buf, "%s %s%s", dssw->date_val,
627                         dssw->stop_val.val, ampm_buf); 
628                 if ((stop_tick = cm_getdate(buf, NULL)) <= 0) {
629                         editor_err_msg(dssw->parent, name, INVALID_DATE,
630                                        pu->xm_error_pixmap);
631                         return False;
632                 }
633                 if (stop_tick < start_tick) {
634                     if (*flagsP == 0)
635                     {
636                         char *title = XtNewString(catgets(calendar->DT_catd, 1, 248,
637                                         "Calendar : Schedule Appointment"));
638                         char *ident1 = XtNewString(catgets(calendar->DT_catd, 1,
639                                         923, "Cancel"));
640                         char *ident2 = XtNewString(catgets(calendar->DT_catd, 1,
641                                         250, "Next Day"));
642                         sprintf(buf, "%s", catgets(calendar->DT_catd, 1, 247,
643                                 "This appointment has an end time earlier than\nits begin time.  Do you want to\nschedule it into the next day?"));
644                         *flagsP = dialog_popup(dssw->parent,
645                                 DIALOG_TITLE, title,
646                                 DIALOG_TEXT, buf,
647                                 BUTTON_IDENT, -1, ident1,
648                                 BUTTON_IDENT, DSSW_NEXT_DAY, ident2,
649                                 DIALOG_IMAGE, pu->xm_question_pixmap,
650                                 NULL);
651                         XtFree(ident2);
652                         XtFree(ident1);
653                         XtFree(title);
654                     }
655                     switch (*flagsP) {
656                     case DSSW_NEXT_DAY:
657                         stop_tick += daysec;
658                         break;
659
660                     default:
661                         *flagsP = 0;
662                         return False;
663                     }
664                 }
665
666                 a->end_time->value->item.date_time_value = (char *) malloc(BUFSIZ);
667                 _csa_tick_to_iso8601(stop_tick, a->end_time->value->item.date_time_value);
668         } else if (blank_buf(dssw->start_val.val)) {
669                 a->end_time->value->item.date_time_value = (char *) malloc(BUFSIZ);
670                 _csa_tick_to_iso8601(start_tick + minsec, a->end_time->value->item.date_time_value);
671                 a->show_time->value->item.sint32_value = False;
672         } else {
673                 free(a->end_time->value);
674                 a->end_time->value = NULL;
675         }
676
677         return True;
678 }
679 /*
680 **  This function will consume form values and stuff them into an appointment.
681 */
682 extern Boolean
683 dssw_form_to_todo(DSSW *dssw, Dtcm_appointment *a, char *name, Tick t)
684 {
685         time_t          start_tick, stop_tick;
686         char            ampm_buf[BUFSIZ], buf[BUFSIZ];
687         Props           *p = (Props *)dssw->cal->properties;
688         Props_pu        *pu = (Props_pu *)dssw->cal->properties_pu;
689         DisplayType     dt = get_int_prop(p, CP_DEFAULTDISP);
690
691         get_dssw_vals(dssw, t);
692         /*
693          * Todo does not have end time.  So to distinguish between this
694          * and the editor, zero this out.
695          */
696         sprintf(dssw->stop_val.val, "\0");
697         if (blank_buf(dssw->date_val)) {
698                 editor_err_msg(dssw->parent, name, MISSING_DATE,
699                                pu->xm_error_pixmap);
700                 return False;
701         }
702
703         if (!blank_buf(dssw->start_val.val)) {
704                 if (!valid_time(p, dssw->start_val.val)) {
705                         editor_err_msg(dssw->parent, name, INVALID_TIME,
706                                 pu->xm_error_pixmap);
707                         return False;
708                 }
709
710                 if (dt == HOUR12) {
711                         if (dssw->start_val.block == TIME_AM)
712                                 sprintf(ampm_buf, "am");
713                         else
714                                 sprintf(ampm_buf, "pm");
715                 } else
716                         ampm_buf[0] = '\0';
717
718                 sprintf(buf, "%s %s%s",
719                         dssw->date_val, dssw->start_val.val, ampm_buf); 
720
721                 /* 
722                  * No check here for stop time.
723                  */
724         } else {
725                 editor_err_msg(dssw->parent, name, MISSING_TIME,
726                         pu->xm_error_pixmap);
727                 return False;
728         }
729
730         start_tick = cm_getdate(buf, NULL);
731         if(start_tick < 0) {
732                 editor_err_msg(dssw->parent, name, INVALID_DATE,
733                         pu->xm_error_pixmap);
734                 return False;
735         }
736
737         a->time->value->item.date_time_value = (char *) malloc(BUFSIZ);
738         _csa_tick_to_iso8601(start_tick, a->time->value->item.date_time_value);
739         a->what->value->item.string_value = (char *)cm_strdup(dssw->what_val);
740         a->show_time->value->item.sint32_value = True;
741
742         free(a->end_time->value);
743         a->end_time->value = NULL;
744
745         return True;
746 }
747
748 /*
749 **  The next two functions will take appointment values and stuff them into
750 **  a form.
751 */
752 extern Boolean
753 dssw_appt_to_form(DSSW *dssw, CSA_entry_handle entry) {
754         Boolean                 ret_val;
755         CSA_return_code         stat;
756         Dtcm_appointment        *appt;
757
758         appt = allocate_appt_struct(appt_read,
759                                     dssw->cal->general->version,
760                                     CSA_ENTRY_ATTR_START_DATE_I,
761                                     CSA_ENTRY_ATTR_SUMMARY_I,
762                                     CSA_ENTRY_ATTR_END_DATE_I,
763                                     CSA_X_DT_ENTRY_ATTR_SHOWTIME_I,
764                                     NULL);
765         stat = query_appt_struct(dssw->cal->cal_handle, entry, appt);
766         backend_err_msg(dssw->cal->frame, dssw->cal->view->current_calendar,
767                 stat, ((Props_pu *)dssw->cal->properties_pu)->xm_error_pixmap);
768         if (stat != CSA_SUCCESS) {
769                 free_appt_struct(&appt);
770                 return False;
771         }
772
773         ret_val = dssw_attrs_to_form(dssw, appt);
774         free_appt_struct(&appt);
775
776         return ret_val;
777 }
778
779 extern Boolean
780 dssw_attrs_to_form(DSSW *dssw, Dtcm_appointment *appt) {
781         int             start_hr, stop_hr;
782         char            *what;
783         time_t          tick, end_tick = 0;
784         Boolean         showtime;
785         Props           *p = (Props *)dssw->cal->properties;
786         DisplayType     dt = get_int_prop(p, CP_DEFAULTDISP);
787
788         _csa_iso8601_to_tick(appt->time->value->item.date_time_value, &tick);
789         showtime = showtime_set(appt);
790         if (appt->end_time)
791                 _csa_iso8601_to_tick(appt->end_time->value->item.\
792                         date_time_value, &end_tick);
793         what = appt->what->value->item.string_value;
794
795         /*
796         **  Set the date, start, stop, and what fields
797         */
798         if (!showtime || magic_time(tick)) {
799                 dssw->start_val.val[0] = '\0';
800                 dssw->stop_val.val[0] = '\0';
801         } else {
802                 if ((start_hr = hour(tick)) < 12)
803                         dssw->start_val.block = TIME_AM;
804                 else
805                         dssw->start_val.block = TIME_PM;
806
807                 if (dt == HOUR12) {
808                         if (start_hr == 0)
809                                 start_hr = 12;
810                         else if (start_hr > 12)
811                                 start_hr -= 12;
812                         sprintf(dssw->start_val.val, "%2d:%02d", start_hr,
813                                 minute(tick));
814                 } else
815                         sprintf(dssw->start_val.val, "%02d%02d", start_hr,
816                                 minute(tick));
817
818                 if (end_tick) {
819                         if ((stop_hr = hour(end_tick)) < 12)
820                                 dssw->stop_val.block = TIME_AM;
821                         else
822                                 dssw->stop_val.block = TIME_PM;
823
824                         if (dt == HOUR12) {
825                                 if (stop_hr == 0)
826                                         stop_hr = 12;
827                                 else if (stop_hr > 12)
828                                         stop_hr -= 12;
829                                 sprintf(dssw->stop_val.val, "%2d:%02d", stop_hr,
830                                         minute(end_tick));
831                         } else
832                                 sprintf(dssw->stop_val.val, "%02d%02d", stop_hr,
833                                         minute(end_tick));
834                 } else {
835                         /* no end time */
836                         sprintf(dssw->stop_val.val, "\0");
837                         dssw->stop_val.block = TIME_AM;
838                 }
839         }
840
841         /* limit the size of the text pulled out of the appointment. */
842
843         if (what) {
844                 strncpy(dssw->what_val, what, WHAT_LEN - 1);
845                 dssw->what_val[WHAT_LEN-1] = NULL;
846         }
847
848         set_dssw_vals(dssw, tick);
849
850         return True;
851 }
852
853 extern void
854 get_dssw_times(DSSW *dssw) {
855         char            *str;
856
857         str = XmTextGetString(dssw->start_text);
858         strcpy(dssw->start_val.val, str);
859         XtFree(str);
860         dssw->start_val.block =
861                 XmToggleButtonGetState(dssw->start_am) ? TIME_AM : TIME_PM;
862
863         str = XmTextGetString(dssw->stop_text);
864         strcpy(dssw->stop_val.val, str);
865         XtFree(str);
866         dssw->stop_val.block =
867                 XmToggleButtonGetState(dssw->stop_am) ? TIME_AM : TIME_PM;
868 }
869
870 extern void
871 get_dssw_vals(DSSW *dssw, Tick t) {
872         dssw_get_non_times(dssw, t);
873         get_dssw_times(dssw);
874 }
875
876 extern void
877 set_dssw_times(DSSW *dssw) {
878         XmString        xmstr;
879         Props           *p = (Props *)dssw->cal->properties;
880         DisplayType     dt = get_int_prop(p, CP_DEFAULTDISP);
881
882         XtVaSetValues(dssw->start_text, XmNvalue, dssw->start_val.val,
883                 NULL);
884         XtVaSetValues(dssw->stop_text, XmNvalue, dssw->stop_val.val,
885                 NULL);
886
887         xmstr = XmStringCreateLocalized(dssw->start_val.val);
888         XtVaSetValues(XmOptionButtonGadget(dssw->start_menu),
889                 XmNlabelString, xmstr,
890                 NULL);
891         XmStringFree(xmstr);
892         xmstr = XmStringCreateLocalized(dssw->stop_val.val);
893         XtVaSetValues(XmOptionButtonGadget(dssw->stop_menu),
894                 XmNlabelString, xmstr,
895                 NULL);
896         XmStringFree(xmstr);
897
898         if (dt == HOUR12) {
899                 if (dssw->start_val.block == TIME_AM)
900                         XmToggleButtonSetState(dssw->start_am, True, True);
901                 else
902                         XmToggleButtonSetState(dssw->start_pm, True, True);
903                 if (dssw->stop_val.block == TIME_AM)
904                         XmToggleButtonSetState(dssw->stop_am, True, True);
905                 else
906                         XmToggleButtonSetState(dssw->stop_pm, True, True);
907         }
908 }
909
910 extern void
911 load_dssw_times(DSSW *dssw, Tick start, Tick stop, Boolean set_no_time) {
912         char            buf[10];
913         Props           *p = (Props *)dssw->cal->properties;
914         DisplayType     dt;
915
916         /*
917          * If start and stop times were specified, do the right thing to the
918          * dssw widget
919          */
920         dt = get_int_prop(p, CP_DEFAULTDISP);
921
922         if (set_no_time == True){
923                 strcpy(dssw->start_val.val, " ");
924                 strcpy(dssw->stop_val.val, " ");
925                 return;
926         }
927
928         if (start > 0) {
929                 format_time(start, dt, buf);
930                 if (dt == HOUR12) {
931                         strncpy(dssw->start_val.val, buf, 5);
932                         dssw->start_val.val[5] = '\0';
933                         dssw->start_val.block = (buf[5] == 'a') ?
934                                 TIME_AM : TIME_PM;
935                 } else {
936                         strcpy(dssw->start_val.val, buf);
937                         dssw->start_val.block = TIME_AM;
938                 }
939         }
940         if (stop > 0) {
941                 format_time(stop, dt, buf);
942                 if (dt == HOUR12) {
943                         strncpy(dssw->stop_val.val, buf, 5);
944                         dssw->stop_val.val[5] = '\0';
945                         dssw->stop_val.block = (buf[5] == 'a') ?
946                                 TIME_AM : TIME_PM;
947                 } else {
948                         strcpy(dssw->stop_val.val, buf);
949                         dssw->stop_val.block = TIME_AM;
950                 }
951         }
952 }
953
954 extern void
955 set_dssw_vals(DSSW *dssw, Tick t) {
956         dssw_set_non_times(dssw, t);
957         set_dssw_times(dssw);
958 }
959
960 extern void
961 set_dssw_defaults(DSSW *dssw, Tick t, Boolean set_times) {
962         int                     appt_beg, appt_end, beg_hr, end_hr;
963         Props                   *p = (Props *)dssw->cal->properties;
964         DisplayType             dt;
965         Time_scope_menu_op      dur_scope;
966
967         if (set_times) {
968                 dt = get_int_prop(p, CP_DEFAULTDISP);
969                 appt_beg = get_int_prop(p, CP_APPTBEGIN);
970                 beg_hr = appt_beg / minsec;
971                 appt_end = get_int_prop(p, CP_APPTDURATION) + appt_beg;
972                 end_hr = appt_end / minsec;
973                 end_hr = end_hr % 24;
974
975                 if (dt == HOUR12) {
976                         dssw->start_val.block = (adjust_hour(&beg_hr)) ?
977                                 TIME_AM : TIME_PM;
978                         dssw->stop_val.block =  (adjust_hour(&end_hr)) ?
979                                 TIME_AM : TIME_PM;
980                         sprintf(dssw->start_val.val, "%2d:%02d",
981                                 beg_hr, appt_beg % minsec);
982                         sprintf(dssw->stop_val.val, "%2d:%02d",
983                                 end_hr, appt_end % minsec);
984                 } else {
985                         sprintf(dssw->start_val.val, "%02d%02d",
986                                 beg_hr, appt_beg % minsec);
987                         sprintf(dssw->stop_val.val, "%02d%02d",
988                                 end_hr, appt_end % minsec);
989                         dssw->start_val.block = dssw->stop_val.block = TIME_AM;
990                 }
991         }
992         dssw->what_val[0] = '\0';
993
994         set_dssw_vals(dssw, t);
995 }