1 /*----------------------------------------------------------------------------
2 --
3 --  Module:           XmUbTimeBox
4 --
5 --  Project:          XmUb - Ulle's Motif widgets
6 --  System:
7 --    Subsystem:      <>
8 --    Function block: <>
9 --
10 --  Description:
11 --    This is the implementation of the widget.
12 --
13 --  Filename:         XmUbTimeB.c
14 --
15 --  Authors:          Roger Larsson, Ulrika Bornetun
16 --  Creation date:    1993-09-12
17 --
18 --
19 --  (C) Copyright Ulrika Bornetun, Roger Larsson (1995)
20 --      All rights reserved
21 --
22 --  Permission to use, copy, modify, and distribute this software and its
23 --  documentation for any purpose and without fee is hereby granted,
24 --  provided that the above copyright notice appear in all copies. Ulrika
25 --  Bornetun and Roger Larsson make no representations about the usability
26 --  of this software for any purpose. It is provided "as is" without express
27 --  or implied warranty.
28 ----------------------------------------------------------------------------*/
29 
30 /* SCCS module identifier. */
31 static char SCCSID[] = "@(#) Module: XmUbTimeB.c, Version: 1.1, Date: 95/02/18 15:10:15";
32 
33 
34 /*----------------------------------------------------------------------------
35 --  Include files
36 ----------------------------------------------------------------------------*/
37 
38 #include <stdio.h>
39 #include <string.h>
40 #include <X11/Intrinsic.h>
41 #include <X11/StringDefs.h>
42 #include <Xm/XmP.h>
43 
44 #if XmVersion > 1001
45 #include <Xm/AtomMgr.h>
46 #include <Xm/DragDrop.h>
47 #endif
48 
49 #include <Xm/CascadeB.h>
50 #include <Xm/Form.h>
51 #include <Xm/PushB.h>
52 #include <Xm/RowColumn.h>
53 #include <Xm/Separator.h>
54 #include <Xm/Text.h>
55 #include <Xm/Protocols.h>
56 
57 #include "XmUbMonthD.h"
58 #include "XmUbTimeSl.h"
59 
60 /* Rogge's tools. */
61 #include "TimDate.h"
62 
63 /* Private widget header file. */
64 #include "XmUbTimeBP.h"
65 
66 /* Drag and drop. */
67 #if XmVersion > 1001
68 #include "XmUbDragDrop.h"
69 #endif
70 
71 /*----------------------------------------------------------------------------
72 --  Macro definitions
73 ----------------------------------------------------------------------------*/
74 
75 #ifdef MAX
76 #undef MAX
77 #endif
78 
79 #ifdef MIN
80 #undef MIN
81 #endif
82 
83 #define MAX( x, y )  ( ( x ) > ( y ) ? ( x ) : ( y ) )
84 #define MIN( x, y )  ( ( x ) < ( y ) ? ( x ) : ( y ) )
85 
86 #define DATE_FIELD_COLUMNS      10
87 #define TIME_FIELD_COLUMNS       8
88 #define TIME_STRING_BUFFER_LEN  25
89 #define TEXT_BUFFER_LENGTH      20
90 
91 /* Resource converters. */
92 #define XmRwidgetFormatType      "TimeBoxWidgetFormatType"
93 #define XmRmenuPositionType      "TimeBoxMenuPositionType"
94 
95 
96 /* Constants. */
97 #define MAX_NO_DEFAULT_MENU_ITEMS  15
98 #define MAX_PATTERN_LENGTH         30
99 
100 
101 /* General error codes. */
102 #define XmUbTB_CHILD_ERROR     -1
103 
104 /*----------------------------------------------------------------------------
105 --  Type declarations
106 ----------------------------------------------------------------------------*/
107 
108 typedef struct {
109 
110   Dimension  width;
111   Dimension  height;
112   Position   x;
113   Position   y;
114 
115 } KidDimensionRec;
116 
117 /*----------------------------------------------------------------------------
118 --  Global definitions
119 ----------------------------------------------------------------------------*/
120 
121 /* Flag is set when the application context dependent things have been done. */
122 static Boolean  context_dependent_done = False;
123 
124 static Atom protocol_atom;
125 static Atom delete_atom;
126 
127 /* Internal Motif functions (how do we know about this....?) */
128 extern void
129   _XmBackgroundColorDefault();
130 extern void
131   _XmForegroundColorDefault();
132 
133 /* Default scanning strings for date/time completion. */
134 static char default_day_marker[]    = "dD";
135 static char default_hour_marker[]   = "hH";
136 static char default_minute_marker[] = "mM";
137 static char default_month_marker[]  = "mM";
138 static char default_week_marker[]   = "wW";
139 static char default_year_marker[]   = "yY";
140 
141 /* Default string for default action when completion failed. */
142 static char default_completion_failed_string[] = "??";
143 
144 /* Default dialog titles. */
145 static char default_date_selection_title[] = "Select a date";
146 static char default_time_selection_title[] = "Select a time";
147 
148 /* Default dialog labels. */
149 static char default_ok_string[]     = "Ok";
150 static char default_cancel_string[] = "Cancel";
151 static char default_year_string[]   = "Year";
152 static char default_month_string[]  = "Month";
153 static char default_week_string[]   = "W";
154 
155 /* The time box resource list. */
156 static XtResource resources[] = {
157   {
158     XmNactivateCallback,
159     XmCCallback,
160     XmRCallback, sizeof( XtCallbackList ),
161     XtOffset( XmUbTimeBoxWidget, tbox.activate_callback ),
162     XmRCallback,
163     NULL
164   },
165   {
166     XmNvalueChangedCallback,
167     XmCCallback,
168     XmRCallback, sizeof( XtCallbackList ),
169     XtOffset( XmUbTimeBoxWidget, tbox.value_changed_callback ),
170     XmRCallback,
171     NULL
172   },
173   {
174     XmUbNtboxPopupSelectionCallback,
175     XmCCallback,
176     XmRCallback, sizeof( XtCallbackList ),
177     XtOffset( XmUbTimeBoxWidget, tbox.popup_selection_callback ),
178     XmRCallback,
179     NULL
180   },
181   {
182     XmNcancelLabelString,
183     XmCCancelLabelString,
184     XmRXmString, sizeof( XmString ),
185     XtOffset( XmUbTimeBoxWidget, tbox.cancel_label ),
186     XtRImmediate,
187     (XtPointer) NULL
188   },
189   {
190     XmNmarginHeight,
191     XmCMarginHeight,
192     XtRDimension, sizeof( Dimension ),
193     XtOffset( XmUbTimeBoxWidget, tbox.margin_height ),
194     XtRImmediate,
195     (XtPointer) 0
196   },
197   {
198     XmNmarginWidth,
199     XmCMarginWidth,
200     XtRDimension, sizeof( Dimension ),
201     XtOffset( XmUbTimeBoxWidget, tbox.margin_width ),
202     XtRImmediate,
203     (XtPointer) 0
204   },
205   {
206     XmNokLabelString,
207     XmCOkLabelString,
208     XmRXmString, sizeof( XmString ),
209     XtOffset( XmUbTimeBoxWidget, tbox.ok_label ),
210     XtRImmediate,
211     (XtPointer) NULL
212   },
213   {
214     XmNorientation,
215     XmCOrientation,
216     XmROrientation, sizeof( unsigned char ),
217     XtOffset( XmUbTimeBoxWidget, tbox.orientation ),
218     XtRImmediate,
219     (XtPointer) XmHORIZONTAL
220   },
221   {
222     XmUbNtboxCodeDay,
223     XmUbCTboxCodeDay,
224     XmRString, sizeof( char* ),
225     XtOffset( XmUbTimeBoxWidget, tbox.day_marker ),
226     XtRImmediate,
227     (XtPointer) NULL
228   },
229   {
230     XmUbNtboxCodeHour,
231     XmUbCTboxCodeHour,
232     XmRString, sizeof( char* ),
233     XtOffset( XmUbTimeBoxWidget, tbox.hour_marker ),
234     XtRImmediate,
235     (XtPointer) NULL
236   },
237   {
238     XmUbNtboxCodeMinute,
239     XmUbCTboxCodeMinute,
240     XmRString, sizeof( char* ),
241     XtOffset( XmUbTimeBoxWidget, tbox.minute_marker ),
242     XtRImmediate,
243     (XtPointer) NULL
244   },
245   {
246     XmUbNtboxCodeMonth,
247     XmUbCTboxCodeMonth,
248     XmRString, sizeof( char* ),
249     XtOffset( XmUbTimeBoxWidget, tbox.month_marker ),
250     XtRImmediate,
251     (XtPointer) NULL
252   },
253   {
254     XmUbNtboxCodeWeek,
255     XmUbCTboxCodeWeek,
256     XmRString, sizeof( char* ),
257     XtOffset( XmUbTimeBoxWidget, tbox.week_marker ),
258     XtRImmediate,
259     (XtPointer) NULL
260   },
261   {
262     XmUbNtboxCodeYear,
263     XmUbCTboxCodeYear,
264     XmRString, sizeof( char* ),
265     XtOffset( XmUbTimeBoxWidget, tbox.year_marker ),
266     XtRImmediate,
267     (XtPointer) NULL
268   },
269   {
270     XmUbNtboxCompletionCallback,
271     XmCCallback,
272     XmRCallback, sizeof( XtCallbackList ),
273     XtOffset( XmUbTimeBoxWidget, tbox.completion_callback ),
274     XmRCallback,
275     NULL
276   },
277   {
278     XmUbNtboxComponentTogether,
279     XmUbCTboxComponentTogether,
280     XtRBoolean, sizeof( Boolean ),
281     XtOffset( XmUbTimeBoxWidget, tbox.component_together ),
282     XtRImmediate,
283     (XtPointer) True
284   },
285   {
286     XmUbNtboxDateSelectionTitle,
287     XmUbCTboxDateSelectionTitle,
288     XtRString, sizeof( String ),
289     XtOffset( XmUbTimeBoxWidget, tbox.date_selection_title ),
290     XtRImmediate,
291     (XtPointer) NULL
292   },
293   {
294     XmUbNtboxDestroyDialogs,
295     XmUbCTboxDestroyDialogs,
296     XtRBoolean, sizeof( Boolean ),
297     XtOffset( XmUbTimeBoxWidget, tbox.destroy_dialogs ),
298     XtRImmediate,
299     (XtPointer) True
300   },
301   {
302     XmUbNtboxFieldSpacing,
303     XmCSpacing,
304     XtRDimension, sizeof( Dimension ),
305     XtOffset( XmUbTimeBoxWidget, tbox.field_spacing ),
306     XtRImmediate,
307     (XtPointer) 2
308   },
309   {
310     XmUbNtboxFormat,
311     XmUbCTboxFormat,
312     XmRwidgetFormatType, sizeof( widgetFormatType ),
313     XtOffset( XmUbTimeBoxWidget, tbox.widget_format ),
314     XtRImmediate,
315     (XtPointer) XmUbTB_FORMAT_DTDT
316   },
317   {
318     XmUbNtboxMenuEnabled,
319     XmUbCTboxMenuEnabled,
320     XtRBoolean, sizeof( Boolean ),
321     XtOffset( XmUbTimeBoxWidget, tbox.menu_enabled ),
322     XtRImmediate,
323     (XtPointer) True
324   },
325   {
326     XmUbNtboxMenuItems,
327     XmUbCTboxMenuItems,
328     XtRPointer, sizeof( XmUbMenuItemRef ),
329     XtOffset( XmUbTimeBoxWidget, tbox.menu_items ),
330     XtRImmediate,
331     (XtPointer) NULL
332   },
333   {
334     XmUbNtboxMenuLabel,
335     XmUbCTboxMenuLabel,
336     XmRXmString, sizeof( XmString ),
337     XtOffset( XmUbTimeBoxWidget, tbox.menu_label ),
338     XtRImmediate,
339     (XtPointer) NULL
340   },
341   {
342     XmUbNtboxMenuPixmap,
343     XmUbCTboxMenuPixmap,
344     XmRPrimForegroundPixmap, sizeof( Pixmap ),
345     XtOffset( XmUbTimeBoxWidget, tbox.menu_pixmap ),
346     XtRImmediate,
347     (XtPointer) XmUNSPECIFIED_PIXMAP
348   },
349   {
350     XmUbNtboxMenuPosition,
351     XmUbCTboxMenuPosition,
352     XmRmenuPositionType, sizeof( menuPositionType ),
353     XtOffset( XmUbTimeBoxWidget, tbox.menu_position ),
354     XtRImmediate,
355     (XtPointer) XmUbPOSITION_FIRST
356   },
357   {
358     XmUbNtboxMenuSpacing,
359     XmCSpacing,
360     XtRDimension, sizeof( Dimension ),
361     XtOffset( XmUbTimeBoxWidget, tbox.menu_spacing ),
362     XtRImmediate,
363     (XtPointer) 4
364   },
365   {
366     XmUbNtboxMonthLabel,
367     XmUbCTboxMonthLabel,
368     XmRXmString, sizeof( XmString ),
369     XtOffset( XmUbTimeBoxWidget, tbox.month_label ),
370     XtRImmediate,
371     (XtPointer) NULL
372   },
373   {
374     XmUbNtboxNumItems,
375     XmUbCTboxNumItems,
376     XmRInt, sizeof( int ),
377     XtOffset( XmUbTimeBoxWidget, tbox.num_menu_items ),
378     XtRImmediate,
379     (XtPointer) 0
380   },
381   {
382     XmUbNtboxRangeSpacing,
383     XmCSpacing,
384     XtRDimension, sizeof( Dimension ),
385     XtOffset( XmUbTimeBoxWidget, tbox.range_spacing ),
386     XtRImmediate,
387     (XtPointer) 10
388   },
389   {
390     XmUbNtboxTimeSelectionTitle,
391     XmUbCTboxTimeSelectionTitle,
392     XtRString, sizeof( String ),
393     XtOffset( XmUbTimeBoxWidget, tbox.time_selection_title ),
394     XtRImmediate,
395     (XtPointer) NULL
396   },
397   {
398     XmUbNtboxWeekLabel,
399     XmUbCTboxWeekLabel,
400     XmRXmString, sizeof( XmString ),
401     XtOffset( XmUbTimeBoxWidget, tbox.week_label ),
402     XtRImmediate,
403     (XtPointer) NULL
404   },
405   {
406     XmUbNtboxYearLabel,
407     XmUbCTboxYearLabel,
408     XmRXmString, sizeof( XmString ),
409     XtOffset( XmUbTimeBoxWidget, tbox.year_label ),
410     XtRImmediate,
411     (XtPointer) NULL
412   },
413 
414 };  /* resources */
415 
416 /*----------------------------------------------------------------------------
417 --  Function prototypes
418 ----------------------------------------------------------------------------*/
419 
420 /* Class methods. */
421 static void
422   ClassInitialize();
423 
424 static void
425   ChangeManaged( Widget  widget );
426 
427 static void
428   DeleteChild( Widget  widget );
429 
430 static void
431   Destroy( Widget   widget );
432 
433 static XtGeometryResult
434   GeometryManager( Widget            widget,
435                    XtWidgetGeometry  *request,
436                    XtWidgetGeometry  *reply );
437 
438 static void
439   GetValuesHook( Widget    w,
440                  ArgList   args,
441                  Cardinal  *num_args );
442 
443 static void
444   Initialize( Widget     treq,
445               Widget     tnew,
446               ArgList    args,
447               Cardinal   *num_args );
448 
449 static void
450   InsertChild( Widget  widget );
451 
452 static void
453   PopupDateSelection( Widget  widget );
454 
455 static void
456   PopupTimeSelection( Widget  widget );
457 
458 static XtGeometryResult
459   QueryGeometry( Widget             widget,
460                  XtWidgetGeometry  *proposed,
461                  XtWidgetGeometry  *answer );
462 
463 static void
464   Resize( Widget    widget );
465 
466 static Boolean
467   SetValues( Widget     current,
468              Widget     request,
469              Widget     new,
470              ArgList    args,
471              Cardinal   *num_args );
472 
473 /* Internal functions. */
474 
475 static void
476   ActivateCB( Widget               tw,
477               XmUbTimeBoxWidget    tbox,
478               XmAnyCallbackStruct  *call_data );
479 
480 static void
481   AddDateHour( XmUbTimeBoxWidget  tbox,
482                int                hours );
483 
484 static void
485   AddDateMonth( XmUbTimeBoxWidget  tbox,
486                 int                months,
487                 int                sub_days );
488 
489 static void
490   AddDateWeek( XmUbTimeBoxWidget  tbox,
491                int                weeks,
492                int                sub_days );
493 
494 static void
495   CallDialogPopupCallback( XmUbTimeBoxWidget  tbox,
496                            Widget             child,
497                            int                reason );
498 
499 /* If not in the child list, returns XmUbTB_CHILD_ERROR. */
500 static int
501   ChildIndex( XmUbTimeBoxWidget  tbox,
502               Widget             child );
503 
504 static TIM_TIME_REF
505   CombineDateAndTime( TIM_TIME_REF  date,
506                       TIM_TIME_REF  time );
507 
508 /* User must free returned string. */
509 static char
510   *CompleteDateString( XmUbTimeBoxWidget  tbox,
511                        char               *str );
512 
513 static XmUbTimeBoxStatus
514   CompleteEndDate( XmUbTimeBoxWidget  tbox );
515 
516 /* True means time field has been updated. */
517 static Boolean
518   CompleteEndDateKeyword( XmUbTimeBoxWidget  tbox,
519                           char               *str );
520 
521 static XmUbTimeBoxStatus
522   CompleteEndTime( XmUbTimeBoxWidget  tbox );
523 
524 /* True means time field has been updated. */
525 static Boolean
526   CompleteEndTimeKeyword( XmUbTimeBoxWidget  tbox,
527                           char               *str );
528 
529 static XmUbTimeBoxStatus
530   CompleteStartDate( XmUbTimeBoxWidget  tbox );
531 
532 static XmUbTimeBoxStatus
533   CompleteStartTime( XmUbTimeBoxWidget  tbox );
534 
535 static char
536   *CompleteTimeString( XmUbTimeBoxWidget  tbox,
537                        char               *str );
538 
539 static void
540   ConvertToDateString( XmUbTimeBoxWidget  tbox,
541                        time_t             time,
542                        char               *buffer,
543                        int                buf_len );
544 
545 static void
546   ConvertToMenuPosition( XrmValue   *args,
547                          Cardinal   *num_args,
548                          XrmValue   *from,
549                          XrmValue   *to );
550 
551 static void
552   ConvertToTimeString( XmUbTimeBoxWidget  tbox,
553                        time_t             time,
554                        char               *buffer,
555                        int                buf_len );
556 
557 static void
558   ConvertToWidgetFormat( XrmValue   *args,
559                          Cardinal   *num_args,
560                          XrmValue   *from,
561                          XrmValue   *to );
562 
563 static void
564   CreateInternalWidgets( XmUbTimeBoxWidget  tbox );
565 
566 static Widget
567   CreateDateField( XmUbTimeBoxWidget  tbox,
568                    char               *name );
569 
570 static void
571   CreateDateSelectionPopup( XmUbTimeBoxWidget  tbox );
572 
573 static void
574   CreateMenu( XmUbTimeBoxWidget  tbox,
575               String             base_name );
576 
577 static void
578   CreateMenuItems( XmUbTimeBoxWidget  tbox,
579                    Widget             parent,
580                    XmUbMenuItemRef    items,
581                    int                num_items );
582 
583 static Widget
584   CreateTimeField( XmUbTimeBoxWidget  tbox,
585                    char               *name );
586 
587 static void
588   CreateTimeSelectionPopup( XmUbTimeBoxWidget  tbox );
589 
590 static void
591   DateCompletionCB( Widget                      tw,
592                     XmUbTimeBoxWidget           tbox,
593                     XmTextVerifyCallbackStruct  *call_data );
594 
595 #if XmVersion > 1001
596 static void
597   DateDropCB( Widget                    w,
598               XtPointer                 client_data,
599               XmDropProcCallbackStruct  *call_data );
600 #endif
601 
602 static void
603   DateSelectedInDialogCB( Widget                          md,
604                           XmUbTimeBoxWidget               tbox,
605                           XmUbMonthDisplayCallbackStruct  *call_data );
606 
607 static void
608   FillInStartOfMonth( XmUbTimeBoxWidget  tbox );
609 
610 static void
611   FillInStartOfWeek( XmUbTimeBoxWidget  tbox );
612 
613 /* Fills in the width and height fields in the kids dimension recs. */
614 static void
615   GetChildPrefSizes( XmUbTimeBoxWidget  tbox,
616                      Widget             initiator,
617                      XtWidgetGeometry   *request,
618                      KidDimensionRec    sizes[] );
619 
620 XmUbTimeBoxStatus
621   GetChildString( XmUbTimeBoxWidget  tbox,
622                   int                child,
623                   char               **str );
624 
625 XmUbTimeBoxStatus
626   GetStartDateTime( XmUbTimeBoxWidget  tbox,
627                     Boolean            use_defaults,
628                     TIM_TIME_REF       *date_time );
629 
630 static void
631   InitializeItem( int             index,
632                   XmUbMenuItem    items[],
633                   XmUbItem        item,
634                   String          label,
635                   XtCallbackProc  proc,
636                   XtPointer       client_data );
637 
638 static void
639   InitializeDefaultMenu( XmUbTimeBoxWidget  tbox,
640                          XmUbMenuItem       items[],
641                          int                *num_items_created );
642 
643 /* The sizes array  must have been processed by GetChildPrefSizes and
644    PrepareLayout before DoLayout is called. */
645 static void
646   DoLayout( XmUbTimeBoxWidget  tbox,
647             Widget             initiator,
648             XtWidgetGeometry   *request,
649             KidDimensionRec    sizes[] );
650 
651 static void
652   KidsPreferredGeometry( Widget            kid,
653                          Widget            initiator,
654                          XtWidgetGeometry  *request,
655                          XtWidgetGeometry  *desired );
656 
657 static void
658   MenuItemActivatedCB( Widget               pb,
659                        XtCallbackProc       action,
660                        XmAnyCallbackStruct  *call_data );
661 
662 Widget
663   MonthDisplayId( XmUbTimeBoxWidget  tbox );
664 
665 static void
666   PopdownDateSelectionDialogCB( Widget               md,
667                                 XmUbTimeBoxWidget    tbox,
668                                 XmAnyCallbackStruct  *call_data );
669 
670 static void
671   PopdownTimeSelectionDialogCB( Widget               tw,
672                                 XmUbTimeBoxWidget    tbox,
673                                 XmAnyCallbackStruct  *call_data );
674 
675 static void
676   PopupDateSelectionAction( Widget    w,
677                             XEvent    *event,
678                             String    *params,
679                             Cardinal  num_params );
680 
681 static void
682   PopupTimeSelectionAction( Widget    w,
683                             XEvent    *event,
684                             String    *params,
685                             Cardinal  num_params );
686 
687 /* Fills in the x and y fields in the kids dimension recs. */
688 /* The width and height fields must be set beforehand. */
689 static void
690   PrepareLayout( XmUbTimeBoxWidget  tbox,
691                  KidDimensionRec    sizes[],
692                  Dimension          *own_width,
693                  Dimension          *own_height );
694 
695 /* ResizeIfNeeded fills in the sizes array. Does not have to be initialized. */
696 static Boolean
697   ResizeIfNeeded( XmUbTimeBoxWidget  tbox,
698                   KidDimensionRec    sizes[] );
699 
700 static void
701   SelectAllTextCB( Widget               tw,
702                    XmUbTimeBoxWidget    tbox,
703                    XmAnyCallbackStruct  *call_data );
704 
705 XmUbTimeBoxStatus
706   SetChildString( XmUbTimeBoxWidget  tbox,
707                   int                child,
708                   char               *str );
709 
710 static void
711   TimeCompletionCB( Widget                      tw,
712                     XmUbTimeBoxWidget           tbox,
713                     XmTextVerifyCallbackStruct  *call_data );
714 
715 /* If TimeCompletionFailed returns True, the problem has been repaired and
716    the calling callback should restart, otherwise it should return. */
717 static Boolean
718   TimeCompletionCallback( Widget               tw,
719 			  int                  child_index,
720 			  XmUbTimeBoxWidget    tbox,
721 			  XmAnyCallbackStruct  *call_data,
722 			  XmUbTimeBoxStatus    reason );
723 
724 static void
725   TimeSelectedInDialogCB( Widget               tw,
726                           XmUbTimeBoxWidget    tbox,
727                           XmAnyCallbackStruct  *call_data );
728 
729 #if XmVersion > 1001
730 static void
731   TransferDateField( Widget         w,
732                      XtPointer      closure,
733                      Atom           *seltype,
734                      Atom           *type,
735                      XtPointer      value,
736                      unsigned long  *length,
737                      int            format );
738 #endif
739 
740 Widget
741   TimeSliderId( XmUbTimeBoxWidget  tbox );
742 
743 static void
744   ValueChangedCB( Widget               tw,
745                   XmUbTimeBoxWidget    tbox,
746                   XmAnyCallbackStruct  *call_data );
747 
748 static void
749   WarningNoResourceChange( XmUbTimeBoxWidget  tbox,
750                            String             resource );
751 
752 /*----------------------------------------------------------------------------
753 --  The action definitions need the declared functions.
754 ----------------------------------------------------------------------------*/
755 
756 /* Time field widget translation list. */
757 static char timeTextTranslationTable[] =
758   "<Btn1Up>(2):     popup-time-selection() \n\
759    <Btn1Down>:      grab-focus()";
760 
761 /* Date field widget translation list. */
762 static char dateTextTranslationTable[] =
763   "<Btn1Up>(2):     popup-date-selection() \n\
764    <Btn1Down>:      grab-focus()";
765 
766 static XtTranslations  dateTextTranslations;
767 static XtTranslations  timeTextTranslations;
768 
769 /* Action list. */
770 static XtActionsRec actionsList[] =
771 {
772   { "popup-time-selection", (XtActionProc) PopupTimeSelectionAction },
773   { "popup-date-selection", (XtActionProc) PopupDateSelectionAction },
774 };
775 
776 
777 /*----------------------------------------------------------------------------
778 --  Initialization of the class record.
779 ----------------------------------------------------------------------------*/
780 
781 /* This initialization has to be done after the methods have been declared. */
782 XmUbTimeBoxClassRec xmUbTimeBoxClassRec = {
783 
784   { /* Core class fields. */
785     /* superclass */                    (WidgetClass) &xmManagerClassRec,
786     /* class_name */                    "XmUbTimeBox",
787     /* widget_size */                   sizeof( XmUbTimeBoxRec ),
788     /* class_initialize */              ClassInitialize,
789     /* class_part_initialize */         NULL,
790     /* class_inited */                  False,
791     /* initialize */                    Initialize,
792     /* initialize_hook */               NULL,
793     /* realize */                       XtInheritRealize,
794     /* actions */                       actionsList,
795     /* num_actions */                   XtNumber( actionsList ),
796     /* resources */                     resources,
797     /* num_resources */                 XtNumber( resources ),
798     /* xrm_class */                     NULLQUARK,
799     /* compress_motion */               True,
800     /* compress_exposure */             True,
801     /* compress_enterleave */           True,
802     /* visible_interest */              False,
803     /* destroy */                       Destroy,
804     /* resize */                        Resize,
805     /* expose */                        NULL,
806     /* set_values */                    SetValues,
807     /* set_values_hook */               NULL,
808     /* set_values_almost */             XtInheritSetValuesAlmost,
809     /* get_values_hook */               GetValuesHook,
810     /* accept_focus */                  NULL,
811     /* version */                       XtVersion,
812     /* callback_private */              NULL,
813     /* tm_table */                      NULL,
814     /* query_geometry */                QueryGeometry,
815     /* display_accelerator */           XtInheritDisplayAccelerator,
816     /* extension */                     NULL
817   },
818   { /* Composite class part. */
819     /* geometry_manager */              GeometryManager,
820     /* change_managed */                ChangeManaged,
821     /* insert_child */                  InsertChild,
822     /* delete_child */                  DeleteChild,
823     /* extension */                     NULL
824   },
825   { /* Constraint class fields. */
826     /* subresources */                  NULL,
827     /* subresource_count */             0,
828     /* constraint_size */               sizeof( XmUbTimeBoxConstraintsRec ),
829     /* initialize */                    NULL,
830     /* destroy */                       NULL,
831     /* set_values */                    NULL,
832     /* extension */                     NULL
833   },
834   { /* XmManager class part. */
835     /* translations */                  NULL,
836     /* get_resources */                 NULL,
837     /* num_get_resources */             0,
838     /* get_constraint_resources */      NULL,
839     /* num_get_constraint_resources */  0,
840     /* extension */                     NULL
841   },
842   { /* Time box class part. */
843     /* popup_time_selection */          PopupTimeSelection,
844     /* popup_date_selection */          PopupDateSelection,
845     /* extension */                     NULL
846   },
847 
848 };
849 
850 
851 
852 /* Class record pointer. */
853 WidgetClass
854   xmUbTimeBoxWidgetClass = (WidgetClass) &xmUbTimeBoxClassRec;
855 
856 
857 
858 /*----------------------------------------------------------------------------
859 --  Functions
860 ----------------------------------------------------------------------------*/
861 
862 static void
ActivateCB(Widget tw,XmUbTimeBoxWidget tbox,XmAnyCallbackStruct * call_data)863   ActivateCB( Widget               tw,
864               XmUbTimeBoxWidget    tbox,
865               XmAnyCallbackStruct  *call_data )
866 {
867   /* Variables. */
868   XmUbTimeBoxCallbackStruct  cb;
869 
870   /* Code. */
871 
872   if( tbox -> tbox.activate_callback == NULL )
873     return;
874 
875   /* Set up callback structure. */
876 
877   cb.reason      = XmCR_ACTIVATE;
878   cb.event       = call_data -> event;
879   cb.child_index = ChildIndex( tbox, tw );
880   cb.child       = tw;
881 
882   XtCallCallbackList( (Widget) tbox, tbox -> tbox.activate_callback,
883                       (XtPointer) &cb );
884 
885 
886   return;
887 
888 } /* ActivateCB */
889 
890 
891 /*----------------------------------------------------------------------*/
892 
893 static void
AddDateHour(XmUbTimeBoxWidget tbox,int hours)894   AddDateHour( XmUbTimeBoxWidget  tbox,
895                int                hours )
896 {
897   /* Variables. */
898   TIM_TIME_REF  curr_time;
899 
900   /* Code. */
901 
902   /* Get start time. */
903   /* Must get OK back since we defaults are enabled. */
904   (void) GetStartDateTime( tbox, True, &curr_time );
905 
906   /* Add the specified number of hours. */
907   TimAddHours( &curr_time, hours );
908 
909   /* Format the time and display it. */
910   (void) XmUbTimeBoxSetEndDate( (Widget) tbox, curr_time );
911   (void) XmUbTimeBoxSetEndTime( (Widget) tbox, curr_time );
912 
913 
914   return;
915 
916 } /* AddDateHour */
917 
918 
919 /*----------------------------------------------------------------------*/
920 
921 static void
AddDateMonth(XmUbTimeBoxWidget tbox,int months,int sub_days)922   AddDateMonth( XmUbTimeBoxWidget  tbox,
923                 int                months,
924                 int                sub_days )
925 {
926   /* Variables. */
927   TIM_TIME_REF  curr_time;
928 
929   /* Code. */
930 
931   /* Get start time. */
932   /* Must get OK back since we defaults are enabled. */
933   (void) GetStartDateTime( tbox, True, &curr_time );
934 
935   /* Add the specified number of weeks. */
936   TimAddMonths( &curr_time, months );
937 
938   /* Subtract days if specified. */
939   if( sub_days > 0 )
940     TimAddDays( &curr_time, - ( sub_days ) );
941 
942   /* Format the time and display it. */
943   (void) XmUbTimeBoxSetEndDate( (Widget) tbox, curr_time );
944   (void) XmUbTimeBoxSetEndTime( (Widget) tbox, curr_time );
945 
946 
947   return;
948 
949 } /* AddDateMonth */
950 
951 
952 /*----------------------------------------------------------------------*/
953 
954 static void
AddDateWeek(XmUbTimeBoxWidget tbox,int weeks,int sub_days)955   AddDateWeek( XmUbTimeBoxWidget  tbox,
956                int                weeks,
957                int                sub_days )
958 {
959   /* Variables. */
960   TIM_TIME_REF  curr_time;
961 
962   /* Code. */
963 
964   /* Get start time. */
965   /* Must get OK back since we defaults are enabled. */
966   (void) GetStartDateTime( tbox, True, &curr_time );
967 
968   /* Add the specified number of weeks. */
969   TimAddDays( &curr_time, ( 7 * weeks - sub_days ) );
970 
971   /* Format the time and display it. */
972   (void) XmUbTimeBoxSetEndDate( (Widget) tbox, curr_time );
973   (void) XmUbTimeBoxSetEndTime( (Widget) tbox, curr_time );
974 
975 
976   return;
977 
978 } /* AddDateWeek */
979 
980 
981 /*----------------------------------------------------------------------*/
982 
983 static void
CallDialogPopupCallback(XmUbTimeBoxWidget tbox,Widget child,int reason)984   CallDialogPopupCallback( XmUbTimeBoxWidget  tbox,
985                            Widget             child,
986                            int                reason )
987 {
988   /* Variables. */
989   XmUbTimeBoxCallbackStruct  cb;
990 
991   /* Code. */
992 
993   if( tbox -> tbox.popup_selection_callback == NULL )
994     return;
995 
996   /* Set up callback structure. */
997 
998   cb.reason      = reason;
999   cb.event       = NULL;
1000   cb.child_index = ChildIndex( tbox, child );
1001   cb.child       = child;
1002 
1003   XtCallCallbackList( (Widget) tbox,
1004                       tbox -> tbox.popup_selection_callback,
1005                       (XtPointer) &cb );
1006 
1007 
1008   return;
1009 
1010 } /* CallDialogPopupCallback */
1011 
1012 
1013 /*----------------------------------------------------------------------*/
1014 
1015 static void
ChangeManaged(Widget widget)1016   ChangeManaged( Widget  widget )
1017 {
1018   /* Variables. */
1019   Boolean            layout_done;
1020   KidDimensionRec    kids_sizes[ NO_INTERNAL_CHILDREN ];
1021   XmUbTimeBoxWidget  tbox;
1022 
1023 
1024   /* Code. */
1025 
1026   tbox = (XmUbTimeBoxWidget) widget;
1027 
1028   /* ResizeIfNeeded checks the size of all children and resizes the widget. */
1029   layout_done = ResizeIfNeeded( tbox, kids_sizes );
1030 
1031   /* Do the layout. */
1032   if( !layout_done )
1033     DoLayout( tbox, NULL, NULL, kids_sizes );
1034 
1035 
1036   return;
1037 
1038 } /* ChangeManaged */
1039 
1040 
1041 /*----------------------------------------------------------------------*/
1042 
1043 static int
ChildIndex(XmUbTimeBoxWidget tbox,Widget child)1044   ChildIndex( XmUbTimeBoxWidget  tbox,
1045               Widget             child )
1046 {
1047   /* Variables. */
1048   int  index;
1049 
1050   /* Code. */
1051 
1052   for( index = 0; index < NO_INTERNAL_CHILDREN; index ++ ){
1053 
1054     if( tbox -> tbox.internal_children[ index ] == child )
1055       return index;
1056 
1057   } /* for */
1058 
1059 
1060   /* Specified child not found. */
1061   return XmUbTB_CHILD_ERROR;
1062 
1063 } /* ChildIndex */
1064 
1065 
1066 /*----------------------------------------------------------------------*/
1067 
1068 static void
ClassInitialize()1069   ClassInitialize()
1070 {
1071 
1072   /* Variables. */
1073 
1074   /* Code. */
1075 
1076   /* Register type converters. */
1077   XtAddConverter( XmRString, XmRwidgetFormatType,
1078                   ConvertToWidgetFormat, NULL, 0 );
1079   XtAddConverter( XmRString, XmRmenuPositionType,
1080                   ConvertToMenuPosition, NULL, 0 );
1081 
1082 
1083   /* Initialize class-wide flag. */
1084   context_dependent_done = False;
1085 
1086   /* Parse translations tables. */
1087   dateTextTranslations = XtParseTranslationTable(
1088     (String) dateTextTranslationTable );
1089   timeTextTranslations = XtParseTranslationTable(
1090     (String) timeTextTranslationTable );
1091 
1092 
1093   return;
1094 
1095 } /* ClassInitialize */
1096 
1097 
1098 /*----------------------------------------------------------------------*/
1099 
1100 static TIM_TIME_REF
CombineDateAndTime(TIM_TIME_REF date,TIM_TIME_REF time)1101   CombineDateAndTime( TIM_TIME_REF  date,
1102                       TIM_TIME_REF  time )
1103 {
1104   /* Variables. */
1105   TIM_TIME_REF  combined_time;
1106 
1107   /* Code. */
1108 
1109   combined_time = TimMakeTime( TimIndexOfYear( date ),
1110                                TimIndexOfMonth( date ),
1111                                TimIndexOfDay( date ),
1112                                TimHour( time ),
1113                                TimMinute( time ),
1114                                TimSecond( time ) );
1115 
1116   return( combined_time );
1117 
1118 } /* CombineDateAndTime */
1119 
1120 
1121 /*----------------------------------------------------------------------*/
1122 
1123 static char
CompleteDateString(XmUbTimeBoxWidget tbox,char * str)1124   *CompleteDateString( XmUbTimeBoxWidget  tbox,
1125                        char               *str )
1126 {
1127   /* Variables. */
1128   char             buffer[ TIME_STRING_BUFFER_LEN ];
1129   TIM_TIME_REF     conv_time;
1130   char             *return_str;
1131   TIM_STATUS_TYPE  status;
1132 
1133   /* Code. */
1134 
1135   /* For empty string, we have no completion. */
1136   if( ( str == NULL ) || ( strlen( str ) == 0 ) )
1137     return( NULL );
1138 
1139   /* Initialize. */
1140   buffer[ 0 ] = '\0';
1141 
1142   /* Try to parse the string with time completion. */
1143   status = TimMakeDateFromString( &conv_time, str );
1144 
1145   if( status != TIM_OK )
1146     return( NULL );
1147 
1148   /* Convert the time back to a string. */
1149   ConvertToDateString( tbox, conv_time, buffer, TIME_STRING_BUFFER_LEN - 1 );
1150 
1151   if( strlen( buffer ) == 0 )
1152     return( NULL );
1153 
1154   return_str = XtMalloc( strlen( buffer ) + 1 );
1155   strcpy( return_str, buffer );
1156 
1157 
1158   return( return_str );
1159 
1160 } /* CompleteDateString */
1161 
1162 
1163 /*----------------------------------------------------------------------*/
1164 
1165 static XmUbTimeBoxStatus
CompleteEndDate(XmUbTimeBoxWidget tbox)1166   CompleteEndDate( XmUbTimeBoxWidget  tbox )
1167 {
1168   /* Variables. */
1169   char               *completed_str;
1170   Boolean            done;
1171   XmUbTimeBoxStatus  status;
1172   char               *str;
1173 
1174   /* Code. */
1175 
1176   /* Extract the date string. */
1177   status = XmUbTimeBoxGetEndDateString( (Widget) tbox, &str );
1178   if( status != TBOX_OK )
1179     return( status );
1180 
1181   /* Try to complete as keyword. */
1182   done = CompleteEndDateKeyword( tbox, str );
1183   if( !done ){
1184 
1185     /* If not successful, try numeric completion. */
1186     completed_str = CompleteDateString( tbox, str );
1187 
1188     if( completed_str == NULL )
1189       status = TBOX_NO_COMPLETION;
1190 
1191     else {
1192       status = XmUbTimeBoxSetEndDateString( (Widget) tbox, completed_str );
1193       XtFree( completed_str );
1194     }
1195 
1196   }
1197 
1198   /* Cleanup. */
1199   if( str != NULL )
1200     XtFree( str );
1201 
1202 
1203   return( status );
1204 
1205 } /* CompleteEndDate */
1206 
1207 
1208 /*----------------------------------------------------------------------*/
1209 
1210 static Boolean
CompleteEndDateKeyword(XmUbTimeBoxWidget tbox,char * str)1211   CompleteEndDateKeyword( XmUbTimeBoxWidget  tbox,
1212                           char               *str )
1213 {
1214 #define COMPLETE_END_DATE_NOOP        0
1215 #define COMPLETE_END_DATE_ADD_WEEKS   1
1216 #define COMPLETE_END_DATE_ADD_MONTHS  2
1217 #define COMPLETE_END_DATE_ADD_DAYS    3
1218 #define COMPLETE_END_DATE_ADD_YEARS   4
1219 
1220   /* Variables. */
1221   TIM_TIME_REF       conv_time;
1222   int                days, months, weeks, years;
1223   char               keyword[ 20 ];
1224   int                matches;
1225   char               pattern[ MAX_PATTERN_LENGTH ];
1226   int                operation = COMPLETE_END_DATE_NOOP;
1227   XmUbTimeBoxStatus  status;
1228 
1229   /* Code. */
1230 
1231   /* For empty string, we have no completion. */
1232   if( ( str == NULL ) || ( strlen( str ) == 0 ) )
1233     return( False );
1234 
1235   /* Try different completion schemes. */
1236   sprintf( pattern, "+%s[%s]", "%d%", tbox -> tbox.week_marker );
1237   matches = sscanf( str, pattern, &weeks, keyword );
1238   if( matches == 2 ){
1239 
1240     if( weeks < 0 )
1241       return( False );
1242 
1243     operation = COMPLETE_END_DATE_ADD_WEEKS;
1244   }
1245 
1246   if( operation == COMPLETE_END_DATE_NOOP ){
1247     sprintf( pattern, "+%s[%s]", "%d%", tbox -> tbox.month_marker );
1248     matches = sscanf( str, pattern, &months, keyword );
1249     if( matches == 2 ){
1250 
1251       if( months < 0 )
1252         return( False );
1253 
1254       operation = COMPLETE_END_DATE_ADD_MONTHS;
1255     }
1256   }
1257 
1258   if( operation == COMPLETE_END_DATE_NOOP ){
1259     sprintf( pattern, "+%s[%s]", "%d%", tbox -> tbox.day_marker );
1260     matches = sscanf( str, pattern, &days, keyword );
1261     if( matches == 2 ){
1262 
1263       if( days < 0 )
1264         return( False );
1265 
1266       operation = COMPLETE_END_DATE_ADD_DAYS;
1267     }
1268   }
1269 
1270   if( operation == COMPLETE_END_DATE_NOOP ){
1271     sprintf( pattern, "+%s[%s]", "%d%", tbox -> tbox.year_marker );
1272     matches = sscanf( str, pattern, &years, keyword );
1273     if( matches == 2 ){
1274 
1275       if( days < 0 )
1276         return( False );
1277 
1278       operation = COMPLETE_END_DATE_ADD_YEARS;
1279     }
1280   }
1281 
1282   /* No keyword means add days. */
1283   if( operation == COMPLETE_END_DATE_NOOP ){
1284     matches = sscanf( str, "+%d", &days );
1285     if( matches == 1 ){
1286 
1287       if( days < 0 )
1288         return( False );
1289 
1290       operation = COMPLETE_END_DATE_ADD_DAYS;
1291     }
1292   }
1293 
1294   if( operation == COMPLETE_END_DATE_NOOP )
1295     return( False );
1296 
1297 
1298   /* We must have a date to start from. */
1299   status = XmUbTimeBoxGetStartDate( (Widget) tbox, &conv_time );
1300   if( status != TBOX_OK )
1301     return( False );
1302 
1303   /* We have a valid start date. Complete the desired operation. */
1304   switch( operation ){
1305 
1306     case COMPLETE_END_DATE_ADD_WEEKS:
1307       TimAddDays( &conv_time, 7 * weeks );
1308       break;
1309 
1310     case COMPLETE_END_DATE_ADD_MONTHS:
1311       TimAddMonths( &conv_time, months );
1312       break;
1313 
1314     case COMPLETE_END_DATE_ADD_DAYS:
1315       TimAddDays( &conv_time, days );
1316       break;
1317 
1318     case COMPLETE_END_DATE_ADD_YEARS:
1319       TimAddYears( &conv_time, years );
1320       break;
1321 
1322     default:
1323       return( False );
1324   }
1325 
1326 
1327   /* Set the new time, both date and time. */
1328   (void) XmUbTimeBoxSetEndDate( (Widget) tbox, conv_time );
1329   (void) XmUbTimeBoxSetEndTime( (Widget) tbox, conv_time );
1330 
1331 
1332   return( True );
1333 
1334 #undef COMPLETE_END_DATE_NOOP
1335 #undef COMPLETE_END_DATE_ADD_WEEKS
1336 #undef COMPLETE_END_DATE_ADD_MONTHS
1337 #undef COMPLETE_END_DATE_ADD_DAYS
1338 #undef COMPLETE_END_DATE_ADD_YEARS
1339 } /* CompleteEndDateKeyword */
1340 
1341 
1342 /*----------------------------------------------------------------------*/
1343 
1344 static XmUbTimeBoxStatus
CompleteEndTime(XmUbTimeBoxWidget tbox)1345   CompleteEndTime( XmUbTimeBoxWidget  tbox )
1346 {
1347   /* Variables. */
1348   char               *completed_str;
1349   Boolean            done;
1350   char               *str;
1351   XmUbTimeBoxStatus  status;
1352 
1353   /* Code. */
1354 
1355   /* Extract the time string. */
1356   status = XmUbTimeBoxGetEndTimeString( (Widget) tbox, &str );
1357   if( status != TBOX_OK )
1358     return( status );
1359 
1360   /* Try to complete as keyword. */
1361   done = CompleteEndTimeKeyword( tbox, str );
1362 
1363   if( !done ){
1364 
1365     /* If not successful, try numeric completion. */
1366     completed_str = CompleteTimeString( tbox, str );
1367 
1368     if( completed_str == NULL )
1369       status = TBOX_NO_COMPLETION;
1370 
1371     else {
1372       status = XmUbTimeBoxSetEndTimeString( (Widget) tbox, completed_str );
1373       XtFree( completed_str );
1374     }
1375 
1376   }
1377 
1378   /* Cleanup. */
1379   if( str != NULL )
1380     XtFree( str );
1381 
1382 
1383   return( status );
1384 
1385 } /* CompleteEndTime */
1386 
1387 
1388 /*----------------------------------------------------------------------*/
1389 
1390 static Boolean
CompleteEndTimeKeyword(XmUbTimeBoxWidget tbox,char * str)1391   CompleteEndTimeKeyword( XmUbTimeBoxWidget  tbox,
1392                           char               *str )
1393 {
1394 #define COMPLETE_END_TIME_NOOP         0
1395 #define COMPLETE_END_TIME_ADD_HOURS    1
1396 #define COMPLETE_END_TIME_ADD_MINUTES  2
1397 
1398   /* Variables. */
1399   TIM_TIME_REF  conv_time;
1400   int           hours, minutes;
1401   char          keyword[ 20 ];
1402   int           matches;
1403   int           operation = COMPLETE_END_TIME_NOOP;
1404   char          pattern[ MAX_PATTERN_LENGTH ];
1405   XmUbTimeBoxStatus  status;
1406 
1407   /* Code. */
1408 
1409   /* For empty string, we have no completion. */
1410   if( ( str == NULL ) || ( strlen( str ) == 0 ) )
1411     return( False );
1412 
1413   /* Try different completion schemes. */
1414   sprintf( pattern, "+%s[%s]", "%d%", tbox -> tbox.hour_marker );
1415   matches = sscanf( str, pattern, &hours, keyword );
1416   if( matches == 2 ){
1417 
1418     if( hours < 0 )
1419       return( False );
1420 
1421     operation = COMPLETE_END_TIME_ADD_HOURS;
1422   }
1423 
1424   if( operation == COMPLETE_END_TIME_NOOP ){
1425     sprintf( pattern, "+%s[%s]", "%d%", tbox -> tbox.minute_marker );
1426     matches = sscanf( str, pattern, &minutes, keyword );
1427     if( matches == 2 ){
1428 
1429       if( minutes < 0 )
1430         return( False );
1431 
1432       operation = COMPLETE_END_TIME_ADD_MINUTES;
1433     }
1434   }
1435 
1436   /* No keyword means add hours. */
1437   if( operation == COMPLETE_END_TIME_NOOP ){
1438     matches = sscanf( str, "+%d", &hours );
1439     if( matches == 1 ){
1440 
1441       if( hours < 0 )
1442         return( False );
1443 
1444       operation = COMPLETE_END_TIME_ADD_HOURS;
1445     }
1446   }
1447 
1448   if( operation == COMPLETE_END_TIME_NOOP )
1449     return( False );
1450 
1451 
1452   /* We must have a time to start from. */
1453   status = XmUbTimeBoxGetStartTime( (Widget) tbox, &conv_time );
1454   if( status != TBOX_OK )
1455     return( False );
1456 
1457   /* We have a valid start time. Complete the desired operation. */
1458   switch( operation ){
1459 
1460     case COMPLETE_END_TIME_ADD_HOURS:
1461       TimAddHours( &conv_time, hours );
1462       break;
1463 
1464     case COMPLETE_END_TIME_ADD_MINUTES:
1465       TimAddMinutes( &conv_time, minutes );
1466       break;
1467 
1468     default:
1469       return( False );
1470   }
1471 
1472   /* Set the new time, both date and time. */
1473   (void) XmUbTimeBoxSetEndTime( (Widget) tbox, conv_time );
1474 
1475 
1476   return( True );
1477 
1478 #undef COMPLETE_END_TIME_NOOP
1479 #undef COMPLETE_END_TIME_ADD_HOURS
1480 #undef COMPLETE_END_TIME_ADD_MINUTES
1481 } /* CompleteEndTimeKeyword */
1482 
1483 
1484 /*----------------------------------------------------------------------*/
1485 
1486 static XmUbTimeBoxStatus
CompleteStartDate(XmUbTimeBoxWidget tbox)1487   CompleteStartDate( XmUbTimeBoxWidget  tbox )
1488 {
1489   /* Variables. */
1490   char               *completed_str;
1491   XmUbTimeBoxStatus  status;
1492   char               *str;
1493 
1494   /* Code. */
1495 
1496   /* Extract the date string. */
1497   status = XmUbTimeBoxGetStartDateString( (Widget) tbox, &str );
1498   if( status != TBOX_OK )
1499     return( status );
1500 
1501   completed_str = CompleteDateString( tbox, str );
1502 
1503   if( completed_str == NULL )
1504     status = TBOX_NO_COMPLETION;
1505 
1506   else {
1507     status = XmUbTimeBoxSetStartDateString( (Widget) tbox, completed_str );
1508     XtFree( completed_str );
1509   }
1510 
1511   /* Cleanup. */
1512   if( str != NULL )
1513     XtFree( str );
1514 
1515 
1516   return( status );
1517 
1518 } /* CompleteStartDate */
1519 
1520 
1521 /*----------------------------------------------------------------------*/
1522 
1523 static XmUbTimeBoxStatus
CompleteStartTime(XmUbTimeBoxWidget tbox)1524   CompleteStartTime( XmUbTimeBoxWidget  tbox )
1525 {
1526   /* Variables. */
1527   char               *completed_str;
1528   XmUbTimeBoxStatus  status;
1529   char               *str;
1530 
1531   /* Code. */
1532 
1533   /* Extract the time string. */
1534   status = XmUbTimeBoxGetStartTimeString( (Widget) tbox, &str );
1535   if( status != TBOX_OK )
1536     return( status );
1537 
1538   completed_str = CompleteTimeString( tbox, str );
1539 
1540   if( completed_str == NULL )
1541     status = TBOX_NO_COMPLETION;
1542 
1543   else {
1544     status = XmUbTimeBoxSetStartTimeString( (Widget) tbox, completed_str );
1545     XtFree( completed_str );
1546   }
1547 
1548   /* Cleanup. */
1549   if( str != NULL )
1550     XtFree( str );
1551 
1552 
1553   return( status );
1554 
1555 } /* CompleteStartTime */
1556 
1557 
1558 /*----------------------------------------------------------------------*/
1559 
1560 static char
CompleteTimeString(XmUbTimeBoxWidget tbox,char * str)1561   *CompleteTimeString( XmUbTimeBoxWidget  tbox,
1562                        char               *str )
1563 {
1564   /* Variables. */
1565   char             buffer[ TIME_STRING_BUFFER_LEN ];
1566   TIM_TIME_REF     conv_time;
1567   int              hours;
1568   int              matches;
1569   char             *return_str;
1570   TIM_STATUS_TYPE  status;
1571 
1572   /* Code. */
1573 
1574   /* For empty string, we have no completion. */
1575   if( ( str == NULL ) || ( strlen( str ) == 0 ) )
1576     return( NULL );
1577 
1578   /* Initialize. */
1579   buffer[ 0 ] = '\0';
1580 
1581   /* Try to parse the string with time completion. */
1582   status = TimMakeTimeFromString( &conv_time, str );
1583 
1584   if( status != TIM_OK ){
1585 
1586     /* Allow expansion of hours. Not yet in time package. */
1587     matches = sscanf( str, "%d", &hours );
1588     if( matches == 1 )
1589       conv_time = TimMakeTime( TIM_NOW, TIM_NOW, TIM_NOW, hours, 0, 0 );
1590     else
1591       return( NULL );
1592   }
1593 
1594   /* Convert the time back to a string. */
1595   ConvertToTimeString( tbox, conv_time, buffer, TIME_STRING_BUFFER_LEN - 1 );
1596 
1597   if( strlen( buffer ) == 0 )
1598     return( NULL );
1599 
1600   return_str = XtMalloc( strlen( buffer ) + 1 );
1601   strcpy( return_str, buffer );
1602 
1603 
1604   return( return_str );
1605 
1606 } /* CompleteTimeString */
1607 
1608 
1609 /*----------------------------------------------------------------------*/
1610 
1611 static void
ConvertToDateString(XmUbTimeBoxWidget tbox,time_t time,char * buffer,int buf_len)1612   ConvertToDateString( XmUbTimeBoxWidget  tbox,
1613                        time_t             time,
1614                        char               *buffer,
1615                        int                buf_len )
1616 {
1617 
1618   /* Code. */
1619 
1620   TimFormatDate( time, buffer, buf_len );
1621 
1622 
1623   return;
1624 
1625 } /* ConvertToDateString */
1626 
1627 
1628 /*----------------------------------------------------------------------*/
1629 
1630 static void
ConvertToMenuPosition(XrmValue * args,Cardinal * num_args,XrmValue * from,XrmValue * to)1631   ConvertToMenuPosition( XrmValue   *args,
1632                          Cardinal   *num_args,
1633                          XrmValue   *from,
1634                          XrmValue   *to )
1635 {
1636 
1637   /* Variables. */
1638   static menuPositionType  conv_menu_position;
1639 
1640 
1641   /* Code. */
1642 
1643   if( *num_args != 0 )
1644     XtWarningMsg( "wrongParameters", "ConvertToMenuPosition",
1645       "XtToolkitError", "Conversion needs no extra arguments",
1646       (String *) NULL, (Cardinal *) NULL );
1647 
1648   if( strcmp( (char *) from -> addr, "POSITION_FIRST" ) == 0 )
1649     conv_menu_position = XmUbPOSITION_FIRST;
1650 
1651   else if( strcmp( (char *) from -> addr, "POSITION_LAST" ) == 0 )
1652     conv_menu_position = XmUbPOSITION_LAST;
1653 
1654   else {
1655     XtWarningMsg( "wrongParameters", "ConvertToMenuPosition",
1656       "XtToolkitError", "Cannot convert to type menuPositionType",
1657       (String *) NULL, (Cardinal *) 0 );
1658     conv_menu_position = XmUbPOSITION_FIRST;
1659   }
1660 
1661   ( *to ).size = sizeof( menuPositionType );
1662   ( *to ).addr = (XtPointer) &conv_menu_position;
1663 
1664 
1665   return;
1666 
1667 } /* ConvertToMenuPosition */
1668 
1669 
1670 /*----------------------------------------------------------------------*/
1671 
1672 static void
ConvertToTimeString(XmUbTimeBoxWidget tbox,time_t time,char * buffer,int buf_len)1673   ConvertToTimeString( XmUbTimeBoxWidget  tbox,
1674                        time_t             time,
1675                        char               *buffer,
1676                        int                buf_len )
1677 {
1678 
1679   /* Code. */
1680 
1681   TimFormatTime( time, buffer, buf_len );
1682 
1683 
1684   return;
1685 
1686 } /* ConvertToTimeString */
1687 
1688 
1689 /*----------------------------------------------------------------------*/
1690 
1691 static void
ConvertToWidgetFormat(XrmValue * args,Cardinal * num_args,XrmValue * from,XrmValue * to)1692   ConvertToWidgetFormat( XrmValue   *args,
1693                          Cardinal   *num_args,
1694                          XrmValue   *from,
1695                          XrmValue   *to )
1696 {
1697 
1698   /* Variables. */
1699   static widgetFormatType  conv_widget_format;
1700 
1701 
1702   /* Code. */
1703 
1704   if( *num_args != 0 )
1705     XtWarningMsg( "wrongParameters", "ConvertToWidgetFormat",
1706       "XtToolkitError", "Conversion needs no extra arguments",
1707       (String *) NULL, (Cardinal *) NULL );
1708 
1709   if( strcmp( (char *) from -> addr, "TB_FORMAT_D" ) == 0 )
1710     conv_widget_format = XmUbTB_FORMAT_D;
1711 
1712   else if( strcmp( (char *) from -> addr, "TB_FORMAT_T" ) == 0 )
1713     conv_widget_format = XmUbTB_FORMAT_T;
1714 
1715   else if( strcmp( (char *) from -> addr, "TB_FORMAT_DT" ) == 0 )
1716     conv_widget_format = XmUbTB_FORMAT_DT;
1717 
1718   else if( strcmp( (char *) from -> addr, "TB_FORMAT_DD" ) == 0 )
1719     conv_widget_format = XmUbTB_FORMAT_DD;
1720 
1721   else if( strcmp( (char *) from -> addr, "TB_FORMAT_DTDT" ) == 0 )
1722     conv_widget_format = XmUbTB_FORMAT_DTDT;
1723 
1724   else if( strcmp( (char *) from -> addr, "TB_FORMAT_DTT" ) == 0 )
1725     conv_widget_format = XmUbTB_FORMAT_DTT;
1726 
1727   else if( strcmp( (char *) from -> addr, "TB_FORMAT_TT" ) == 0 )
1728     conv_widget_format = XmUbTB_FORMAT_TT;
1729 
1730 
1731   else {
1732     XtWarningMsg( "wrongParameters", "ConvertToWidgetFormat",
1733       "XtToolkitError", "Cannot convert to type widgetFormatType",
1734       (String *) NULL, (Cardinal *) 0 );
1735     conv_widget_format = XmUbTB_FORMAT_DTDT;
1736   }
1737 
1738   ( *to ).size = sizeof( widgetFormatType );
1739   ( *to ).addr = (XtPointer) &conv_widget_format;
1740 
1741 
1742   return;
1743 
1744 } /* ConvertToWidgetFormat */
1745 
1746 
1747 /*----------------------------------------------------------------------*/
1748 
1749 static void
CreateInternalWidgets(XmUbTimeBoxWidget tbox)1750   CreateInternalWidgets( XmUbTimeBoxWidget  tbox )
1751 {
1752 
1753   /* Variables. */
1754   char    *name;
1755   String  wname;
1756 
1757   /* Code. */
1758 
1759   /* Get the name of the "parent" widget. */
1760   wname = XtName( (Widget)tbox );
1761 
1762   name = XtMalloc( strlen( wname ) + 3 );
1763 
1764   /* Create the menu. */
1765   if( tbox -> tbox.menu_enabled )
1766     CreateMenu( tbox, wname );
1767 
1768   /* First date field. */
1769   if( ( tbox -> tbox.widget_format == XmUbTB_FORMAT_D )    ||
1770       ( tbox -> tbox.widget_format == XmUbTB_FORMAT_DT )   ||
1771       ( tbox -> tbox.widget_format == XmUbTB_FORMAT_DD )   ||
1772       ( tbox -> tbox.widget_format == XmUbTB_FORMAT_DTDT ) ||
1773       ( tbox -> tbox.widget_format == XmUbTB_FORMAT_DTT ) ){
1774 
1775     sprintf( name, "%sFd", wname );
1776 
1777     tbox -> tbox.internal_children[ XmUbTB_CHILD_START_DATE ] =
1778       CreateDateField( tbox, name );
1779 
1780     XtManageChild( tbox -> tbox.internal_children[ XmUbTB_CHILD_START_DATE ] );
1781   }
1782 
1783   /* First time field. */
1784   if( ( tbox -> tbox.widget_format == XmUbTB_FORMAT_T )    ||
1785       ( tbox -> tbox.widget_format == XmUbTB_FORMAT_DT )   ||
1786       ( tbox -> tbox.widget_format == XmUbTB_FORMAT_TT )   ||
1787       ( tbox -> tbox.widget_format == XmUbTB_FORMAT_DTDT ) ||
1788       ( tbox -> tbox.widget_format == XmUbTB_FORMAT_DTT ) ){
1789 
1790     sprintf( name, "%sFt", wname );
1791 
1792     tbox -> tbox.internal_children[ XmUbTB_CHILD_START_TIME ] =
1793       CreateTimeField( tbox, name );
1794 
1795     XtManageChild( tbox -> tbox.internal_children[ XmUbTB_CHILD_START_TIME ] );
1796   }
1797 
1798 
1799   /* Second date field. */
1800   if( ( tbox -> tbox.widget_format == XmUbTB_FORMAT_DD )   ||
1801       ( tbox -> tbox.widget_format == XmUbTB_FORMAT_DTDT ) ) {
1802 
1803     sprintf( name, "%sSd", wname );
1804 
1805     tbox -> tbox.internal_children[ XmUbTB_CHILD_END_DATE ] =
1806       CreateDateField( tbox, name );
1807 
1808     XtManageChild( tbox -> tbox.internal_children[ XmUbTB_CHILD_END_DATE ] );
1809   }
1810 
1811   /* Second time field. */
1812   if( ( tbox -> tbox.widget_format == XmUbTB_FORMAT_TT )   ||
1813       ( tbox -> tbox.widget_format == XmUbTB_FORMAT_DTDT ) ||
1814       ( tbox -> tbox.widget_format == XmUbTB_FORMAT_DTT ) ){
1815 
1816     sprintf( name, "%sSt", wname );
1817 
1818     tbox -> tbox.internal_children[ XmUbTB_CHILD_END_TIME ] =
1819       CreateTimeField( tbox, name );
1820 
1821     XtManageChild( tbox -> tbox.internal_children[ XmUbTB_CHILD_END_TIME ] );
1822   }
1823 
1824   /* Cleanup. */
1825   XtFree( name );
1826 
1827 
1828 
1829   return;
1830 
1831 } /* CreateInternalWidgets */
1832 
1833 
1834 /*----------------------------------------------------------------------*/
1835 
1836 static Widget
CreateDateField(XmUbTimeBoxWidget tbox,char * name)1837   CreateDateField( XmUbTimeBoxWidget  tbox,
1838                    char               *name )
1839 {
1840 
1841   /* Variables. */
1842   Arg           args[ 5 ];
1843   short         columns;
1844   Atom          compound_text_atom;
1845   Atom          date_transfer_atom;
1846   Cardinal      n;
1847   Atom          targets[ 2 ];
1848   char          text_buffer[ TEXT_BUFFER_LENGTH ];
1849   TIM_TIME_REF  time;
1850   Widget        w;
1851 
1852   /* Code. */
1853 
1854   /* Find out how long the longest text in the time field is. */
1855   /* Assume that Dec. 31 yields the longest text. */
1856   time = TimMakeTime( 1970, 12, 31, 23, 59, 59 );
1857   TimFormatDate( time, text_buffer, TEXT_BUFFER_LENGTH - 1 );
1858   columns = (short) ( strlen( text_buffer ) + 1 );
1859 
1860   n = 0;
1861   XtSetArg( args[ n ], XmNeditMode, XmSINGLE_LINE_EDIT ); n++;
1862   XtSetArg( args[ n ], XmNcolumns, columns ); n++;
1863   XtSetArg( args[ n ], XmNtraversalOn, True ); n++;
1864 
1865   w = XmCreateText( (Widget) tbox, name, args, n );
1866 
1867   /* We want to be able to pop up our own date selection dialog. */
1868   XtOverrideTranslations( w, dateTextTranslations );
1869 
1870   /* We want the completion callback when losing focus. */
1871   XtAddCallback( w, XmNlosingFocusCallback,
1872                  (XtCallbackProc) DateCompletionCB, (XtPointer) tbox );
1873 
1874   /* Select all text when gaining focus. */
1875   XtAddCallback( w, XmNfocusCallback,
1876                  (XtCallbackProc) SelectAllTextCB, (XtPointer) tbox );
1877 
1878   XtAddCallback( w, XmNactivateCallback,
1879                  (XtCallbackProc) ActivateCB, (XtPointer) tbox );
1880 
1881   XtAddCallback( w, XmNvalueChangedCallback,
1882                  (XtCallbackProc) ValueChangedCB, (XtPointer) tbox );
1883 
1884 #if XmVersion > 1001
1885   /* We want to enable date transfer in drag and drop format. */
1886   compound_text_atom = XmInternAtom( XtDisplay( w ), "COMPOUND_TEXT", False );
1887   date_transfer_atom = XmInternAtom( XtDisplay( w ), XmUbDATE_TRANSFER,
1888                                      False );
1889 
1890   targets[ 0 ] = date_transfer_atom;
1891   targets[ 1 ] = compound_text_atom;
1892 
1893   n = 0;
1894   XtSetArg( args[ n ], XmNimportTargets, targets ); n++;
1895   XtSetArg( args[ n ], XmNnumImportTargets, XtNumber( targets ) ); n++;
1896   XtSetArg( args[ n ], XmNdropProc, DateDropCB ); n++;
1897 
1898   XmDropSiteUpdate( w, args, n );
1899 
1900 #endif
1901 
1902   return( w );
1903 
1904 } /* CreateDateField */
1905 
1906 
1907 /*----------------------------------------------------------------------*/
1908 
1909 static void
CreateDateSelectionPopup(XmUbTimeBoxWidget tbox)1910   CreateDateSelectionPopup( XmUbTimeBoxWidget  tbox )
1911 {
1912   /* Variables. */
1913   Arg       args[ 8 ];
1914   Widget    month_display;
1915   Cardinal  n;
1916   char      *name_buffer;
1917   String    wname;
1918   XmString  xm, mxm, wxm;
1919 
1920   /* Code. */
1921 
1922   /* Reset flag that stop child creation temporarily. */
1923   tbox -> tbox.internal_widgets_created = False;
1924 
1925   /* Get the name of the "parent" widget. */
1926   wname = XtName( (Widget)tbox );
1927 
1928   name_buffer = XtMalloc( strlen( wname ) + 8 );
1929 
1930   /* The dialog itself. */
1931   sprintf( name_buffer, "%sDtDi", wname );
1932   /* We don't need any OK or Cancel buttons, so create a normal form dialog. */
1933 
1934   n = 0;
1935   tbox -> tbox.date_selection_popup = XmCreateFormDialog(
1936     (Widget) tbox, name_buffer, args, n );
1937 
1938   /* Set resources on the shell. */
1939   n = 0;
1940   XtSetArg( args[ n ], XmNdeleteResponse, XmDO_NOTHING ); n++;
1941   if( tbox -> tbox.date_selection_title != NULL ){
1942     XtSetArg( args[ n ], XmNtitle, tbox -> tbox.date_selection_title ); n++;
1943   } else {
1944     XtSetArg( args[ n ], XmNtitle, default_date_selection_title ); n++;
1945   }
1946 
1947   XtSetValues( XtParent( tbox -> tbox.date_selection_popup ), args, n );
1948 
1949   /* We must catch close events on the shell and prevent it from being
1950      destroyed. */
1951   XmAddProtocolCallback( XtParent( tbox -> tbox.date_selection_popup ),
1952                          protocol_atom, delete_atom,
1953                          (XtCallbackProc) PopdownDateSelectionDialogCB,
1954                          (XtPointer) tbox );
1955 
1956   sprintf( name_buffer, "%sMd", wname );
1957   n = 0;
1958   XtSetArg( args[ n ], XmNmarginHeight, 10 ); n++;
1959   XtSetArg( args[ n ], XmNmarginWidth, 5 ); n++;
1960 
1961   if( tbox -> tbox.year_label == NULL )
1962     xm = XmStringCreateLtoR( default_year_string, XmSTRING_DEFAULT_CHARSET );
1963   else
1964     xm = tbox -> tbox.year_label;
1965   XtSetArg( args[ n ], XmUbNmdiYearLabel, xm ); n++;
1966 
1967   if( tbox -> tbox.month_label == NULL )
1968     mxm = XmStringCreateLtoR( default_month_string, XmSTRING_DEFAULT_CHARSET );
1969   else
1970     mxm = tbox -> tbox.month_label;
1971   XtSetArg( args[ n ], XmUbNmdiMonthLabel, mxm ); n++;
1972 
1973   if( tbox -> tbox.week_label == NULL )
1974     wxm = XmStringCreateLtoR( default_week_string, XmSTRING_DEFAULT_CHARSET );
1975   else
1976     wxm = tbox -> tbox.week_label;
1977   XtSetArg( args[ n ], XmUbNmdiWeekLabel, wxm ); n++;
1978 
1979 
1980   month_display = XmUbCreateMonthDisplay(
1981     tbox -> tbox.date_selection_popup, name_buffer, args, n );
1982 
1983   if( tbox -> tbox.year_label == NULL )
1984     XmStringFree( xm );
1985   if( tbox -> tbox.month_label == NULL )
1986     XmStringFree( mxm );
1987   if( tbox -> tbox.week_label == NULL )
1988     XmStringFree( wxm );
1989 
1990   /* DateSelectedInDialogCB must also pop the dialog down. If we add both
1991      here it is not guaranteed that the dialog exists when our selection
1992      callback is called. */
1993   XtAddCallback( month_display, XmUbNmdiDateSelectedCallback,
1994                  (XtCallbackProc) DateSelectedInDialogCB, (XtPointer) tbox );
1995 
1996   n = 0;
1997   XtSetArg( args[ n ], XmNtopAttachment, XmATTACH_FORM ); n++;
1998   XtSetArg( args[ n ], XmNleftAttachment, XmATTACH_FORM ); n++;
1999   XtSetArg( args[ n ], XmNrightAttachment, XmATTACH_FORM ); n++;
2000   XtSetArg( args[ n ], XmNbottomAttachment, XmATTACH_FORM ); n++;
2001   XtSetValues( month_display, args, n );
2002 
2003   /* For own callbacks to take effect. */
2004   XmUbMonthDisplaySetMonth( month_display, 0, 0 );
2005 
2006   XtManageChild( month_display );
2007 
2008   /* Cleanup. */
2009   XtFree( name_buffer );
2010 
2011   /* Back to stopping child widgets. */
2012   tbox -> tbox.internal_widgets_created = True;
2013 
2014 
2015   return;
2016 
2017 } /* CreateDateSelectionPopup */
2018 
2019 
2020 /*----------------------------------------------------------------------*/
2021 
2022 static void
CreateMenu(XmUbTimeBoxWidget tbox,String base_name)2023   CreateMenu( XmUbTimeBoxWidget  tbox,
2024               String             base_name )
2025 {
2026 
2027   /* Variables. */
2028   Arg       args[ 8 ];
2029   Cardinal  n;
2030   char      *name;
2031 
2032 
2033   /* Code. */
2034 
2035   /* Allocate room enough for the possible default names. */
2036   name = XtMalloc( strlen( base_name ) + 10 );
2037 
2038   /* Must create a menu bar, since a cascade button will only accept such a
2039      parent. */
2040   sprintf( name, "%sBr", base_name );
2041   n = 0;
2042   XtSetArg( args[ n ], XmNmarginHeight, 0 ); n++;
2043   XtSetArg( args[ n ], XmNmarginWidth, 0 ); n++;
2044   XtSetArg( args[ n ], XmNspacing, 0 ); n++;
2045   XtSetArg( args[ n ], XmNtraversalOn, True ); n++;
2046   tbox -> tbox.internal_children[ XmUbTB_CHILD_MENU_BAR ] =
2047     XmCreateMenuBar( (Widget) tbox, name, args, n );
2048 
2049   /* Pulldown menu. */
2050   sprintf( name, "%sPd", base_name );
2051   n = 0;
2052   tbox -> tbox.internal_children[ XmUbTB_CHILD_MENU_PD ] =
2053     XmCreatePulldownMenu(
2054       tbox -> tbox.internal_children[ XmUbTB_CHILD_MENU_BAR ], name, args, n );
2055 
2056   /* The cascade button. */
2057   sprintf( name, "%sCa", base_name );
2058   n = 0;
2059 
2060   if( tbox -> tbox.menu_label != NULL ){
2061     XtSetArg( args[ n ], XmNlabelString, tbox -> tbox.menu_label ); n++;
2062     XtSetArg( args[ n ], XmNlabelType, XmSTRING ); n++;
2063 
2064   } else if( tbox -> tbox.menu_pixmap != XmUNSPECIFIED_PIXMAP ){
2065     XtSetArg( args[ n ], XmNlabelPixmap, tbox -> tbox.menu_pixmap ); n++;
2066     XtSetArg( args[ n ], XmNlabelType, XmPIXMAP ); n++;
2067 
2068   } else {
2069     tbox -> tbox.menu_label =
2070       XmStringCreateLtoR( "-", XmSTRING_DEFAULT_CHARSET );
2071 
2072     XtSetArg( args[ n ], XmNlabelString, tbox -> tbox.menu_label ); n++;
2073     XtSetArg( args[ n ], XmNlabelType, XmSTRING ); n++;
2074     XtSetArg( args[ n ], XmNmarginHeight, 0 ); n++;
2075 
2076   }
2077 
2078   XtSetArg( args[ n ], XmNalignment, XmALIGNMENT_CENTER ); n++;
2079   XtSetArg( args[ n ], XmNsubMenuId,
2080             tbox -> tbox.internal_children[ XmUbTB_CHILD_MENU_PD ] ); n++;
2081   XtSetArg( args[ n ], XmNshadowThickness, 0 ); n++;
2082   XtSetArg( args[ n ], XmNtraversalOn, True ); n++;
2083 
2084   tbox -> tbox.internal_children[ XmUbTB_CHILD_MENU_CASC ] =
2085     XmCreateCascadeButton(
2086       tbox -> tbox.internal_children[ XmUbTB_CHILD_MENU_BAR ], name, args, n );
2087 
2088   /* The menu items. */
2089   if( tbox -> tbox.menu_items == NULL ){
2090 
2091     XmUbMenuItem  default_menu_items[ MAX_NO_DEFAULT_MENU_ITEMS ];
2092     int           num_created;
2093 
2094     /* Initialize the array. */
2095     InitializeDefaultMenu( tbox, default_menu_items, &num_created );
2096 
2097     CreateMenuItems(
2098       tbox, tbox -> tbox.internal_children[ XmUbTB_CHILD_MENU_PD ],
2099       default_menu_items, num_created );
2100 
2101   } else
2102     CreateMenuItems(
2103       tbox, tbox -> tbox.internal_children[ XmUbTB_CHILD_MENU_PD ],
2104       tbox -> tbox.menu_items, tbox -> tbox.num_menu_items );
2105 
2106 
2107   XtManageChild( tbox -> tbox.internal_children[ XmUbTB_CHILD_MENU_CASC ] );
2108   XtManageChild( tbox -> tbox.internal_children[ XmUbTB_CHILD_MENU_BAR ] );
2109 
2110   XtFree( name );
2111 
2112 
2113   return;
2114 
2115 } /* CreateMenu */
2116 
2117 
2118 /*----------------------------------------------------------------------*/
2119 
2120 static void
CreateMenuItems(XmUbTimeBoxWidget tbox,Widget parent,XmUbMenuItemRef items,int num_items)2121   CreateMenuItems( XmUbTimeBoxWidget  tbox,
2122                    Widget             parent,
2123                    XmUbMenuItemRef    items,
2124                    int                num_items )
2125 {
2126   /* Variables. */
2127   Arg       args[ 5 ];
2128   char      *default_name;
2129   int       index;
2130   Cardinal  n;
2131   Widget    w;
2132 
2133   /* Code. */
2134 
2135   default_name = XtMalloc( strlen( XtName( parent ) ) + 3 );
2136   sprintf( default_name, "%sMI", XtName( parent ) );
2137 
2138   for( index = 0; index < num_items; index ++ ){
2139 
2140     switch( items[ index ].item ){
2141       case XmUbITEM_SEPARATOR:
2142         n = 0;
2143         XtSetArg( args[ n ], XmNorientation, XmHORIZONTAL ); n++;
2144         w = XmCreateSeparator( parent,
2145           ( items[ index ].name == NULL ? default_name : items[ index ].name ),
2146           args, n );
2147 
2148         break;
2149 
2150       case XmUbITEM_PUSH_BUTTON:
2151         /* Set the function to be called as user data. */
2152         n = 0;
2153         XtSetArg( args[ n ], XmNlabelString, items[ index ].label ); n++;
2154         XtSetArg( args[ n ], XmNuserData,    (XtPointer) tbox ); n++;
2155         w = XmCreatePushButton( parent,
2156           ( items[ index ].name == NULL ? default_name : items[ index ].name ),
2157           args, n );
2158 
2159         /* For predefined actions, call common routine.
2160            For other actions, register as callbacks directly. */
2161         if( ( items[ index ].proc != XmUbTB_NO_ACTION ) &&
2162             ( (intptr_t)items[ index ].proc <= (intptr_t)XmUbTB_LAST_PREDEF_ACTION ) )
2163           XtAddCallback( w, XmNactivateCallback,
2164                          (XtCallbackProc) MenuItemActivatedCB,
2165                          (XtPointer) items[ index ].proc );
2166 
2167         else if( items[ index ].proc != XmUbTB_NO_ACTION )
2168           XtAddCallback( w, XmNactivateCallback,
2169                          items[ index ].proc, items[ index ].client_data );
2170 
2171         break;
2172 
2173 
2174       default:
2175         /* Insert error message here !!!!!!! */
2176         return;
2177 
2178     }
2179 
2180     XtManageChild( w );
2181 
2182   } /* for */
2183 
2184 
2185   return;
2186 
2187 } /* CreateMenuItems */
2188 
2189 
2190 /*----------------------------------------------------------------------*/
2191 
2192 static Widget
CreateTimeField(XmUbTimeBoxWidget tbox,char * name)2193   CreateTimeField( XmUbTimeBoxWidget  tbox,
2194                    char               *name )
2195 {
2196 
2197   /* Variables. */
2198   Arg           args[ 5 ];
2199   short         columns;
2200   Cardinal      n;
2201   char          text_buffer[ TEXT_BUFFER_LENGTH ];
2202   TIM_TIME_REF  time;
2203   Widget        w;
2204 
2205   /* Code. */
2206 
2207   /* Find out how long the longest text in the time field is. */
2208   /* Assume that 23:59 yields the longest text. */
2209   time = TimMakeTime( 1970, 1, 1, 23, 59, 59 );
2210   TimFormatTime( time, text_buffer, TEXT_BUFFER_LENGTH - 1 );
2211   columns = (short) ( strlen( text_buffer ) + 1 );
2212 
2213   n = 0;
2214   XtSetArg( args[ n ], XmNeditMode, XmSINGLE_LINE_EDIT ); n++;
2215   XtSetArg( args[ n ], XmNcolumns, columns ); n++;
2216   XtSetArg( args[ n ], XmNtraversalOn, True ); n++;
2217 
2218   w = XmCreateText( (Widget) tbox, name, args, n );
2219 
2220   /* We want to be able to pop up our own time selection dialog. */
2221   XtOverrideTranslations( w, timeTextTranslations );
2222 /*  XtAugmentTranslations( w, timeTextTranslations ); */
2223 
2224   /* We want the completion callback when losing focus. */
2225   XtAddCallback( w, XmNlosingFocusCallback,
2226                  (XtCallbackProc) TimeCompletionCB, (XtPointer) tbox );
2227 
2228   /* Select all text when gaining focus. */
2229   XtAddCallback( w, XmNfocusCallback,
2230                  (XtCallbackProc) SelectAllTextCB, (XtPointer) tbox );
2231 
2232   XtAddCallback( w, XmNactivateCallback,
2233                  (XtCallbackProc) ActivateCB, (XtPointer) tbox );
2234 
2235   XtAddCallback( w, XmNvalueChangedCallback,
2236                  (XtCallbackProc) ValueChangedCB, (XtPointer) tbox );
2237 
2238 
2239   return( w );
2240 
2241 } /* CreateTimeField */
2242 
2243 
2244 /*----------------------------------------------------------------------*/
2245 
2246 static void
CreateTimeSelectionPopup(XmUbTimeBoxWidget tbox)2247   CreateTimeSelectionPopup( XmUbTimeBoxWidget  tbox )
2248 {
2249   /* Variables. */
2250   Arg        args[ 8 ];
2251   Widget     cancel;
2252   Widget     form;
2253   Dimension  height, max_height;
2254   Cardinal   n;
2255   char       *name_buffer;
2256   Widget     ok;
2257   Widget     sep;
2258   Widget     time_slider;
2259   Dimension  width, max_width;
2260   String     wname;
2261 
2262   /* Code. */
2263 
2264   /* Reset flag that stop child creation temporarily. */
2265   tbox -> tbox.internal_widgets_created = False;
2266 
2267   /* Get the name of the "parent" widget. */
2268   wname = XtName( (Widget)tbox );
2269 
2270   name_buffer = XtMalloc( strlen( wname ) + 6 );
2271 
2272   /* The dialog itself. */
2273   sprintf( name_buffer, "%sTDi", wname );
2274 
2275   n = 0;
2276   form = XmCreateFormDialog( (Widget) tbox, name_buffer, args, n );
2277 
2278   tbox -> tbox.time_selection_popup = form;
2279 
2280   /* In the form, we want a time slider, a separator and two buttons. */
2281   sprintf( name_buffer, "%sTs", wname );
2282   n = 0;
2283   XtSetArg( args[ n ], XmNmarginHeight, 10 ); n++;
2284   XtSetArg( args[ n ], XmNmarginWidth, 5 ); n++;
2285   XtSetArg( args[ n ], XmNwidth, 300 ); n++;
2286 
2287   time_slider = XmUbCreateTimeSlider( form, name_buffer, args, n );
2288 
2289   sprintf( name_buffer, "%sTSep", wname );
2290 
2291   n = 0;
2292   XtSetArg( args[ n ], XmNorientation, XmHORIZONTAL ); n++;
2293   sep = XmCreateSeparator( form, name_buffer, args, n );
2294 
2295   sprintf( name_buffer, "%sTok", wname );
2296   n = 0;
2297   XtSetArg( args[ n ], XmNlabelString, tbox -> tbox.ok_label ); n++;
2298   ok = XmCreatePushButton( form, name_buffer, args, n );
2299 
2300   sprintf( name_buffer, "%sTcan", wname );
2301   n = 0;
2302   XtSetArg( args[ n ], XmNlabelString, tbox -> tbox.cancel_label ); n++;
2303   cancel = XmCreatePushButton( form, name_buffer, args, n );
2304 
2305   /* Attach the components. */
2306   n = 0;
2307   XtSetArg( args[ n ], XmNtopAttachment, XmATTACH_FORM ); n++;
2308   XtSetArg( args[ n ], XmNleftAttachment, XmATTACH_FORM ); n++;
2309   XtSetArg( args[ n ], XmNrightAttachment, XmATTACH_FORM ); n++;
2310   XtSetArg( args[ n ], XmNbottomAttachment, XmATTACH_WIDGET ); n++;
2311   XtSetArg( args[ n ], XmNbottomWidget, sep ); n++;
2312   XtSetArg( args[ n ], XmNbottomOffset, 3 ); n++;
2313   XtSetValues( time_slider, args, n );
2314 
2315   n = 0;
2316   XtSetArg( args[ n ], XmNleftAttachment, XmATTACH_FORM ); n++;
2317   XtSetArg( args[ n ], XmNrightAttachment, XmATTACH_FORM ); n++;
2318   XtSetArg( args[ n ], XmNbottomAttachment, XmATTACH_WIDGET ); n++;
2319   XtSetArg( args[ n ], XmNbottomWidget, ok ); n++;
2320   XtSetArg( args[ n ], XmNbottomOffset, 3 ); n++;
2321   XtSetValues( sep, args, n );
2322 
2323   n = 0;
2324   XtSetArg( args[ n ], XmNleftAttachment, XmATTACH_FORM ); n++;
2325   XtSetArg( args[ n ], XmNleftOffset, 6 ); n++;
2326   XtSetArg( args[ n ], XmNbottomAttachment, XmATTACH_FORM ); n++;
2327   XtSetArg( args[ n ], XmNbottomOffset, 3 ); n++;
2328   XtSetValues( ok, args, n );
2329 
2330   n = 0;
2331   XtSetArg( args[ n ], XmNrightAttachment, XmATTACH_FORM ); n++;
2332   XtSetArg( args[ n ], XmNrightOffset, 6 ); n++;
2333   XtSetArg( args[ n ], XmNbottomAttachment, XmATTACH_FORM ); n++;
2334   XtSetArg( args[ n ], XmNbottomOffset, 3 ); n++;
2335   XtSetValues( cancel, args, n );
2336 
2337 
2338   /* Set resources on the shell. */
2339   n = 0;
2340   XtSetArg( args[ n ], XmNdeleteResponse, XmDO_NOTHING ); n++;
2341   if( tbox -> tbox.time_selection_title != NULL ){
2342     XtSetArg( args[ n ], XmNtitle, tbox -> tbox.time_selection_title ); n++;
2343   } else {
2344     XtSetArg( args[ n ], XmNtitle, default_time_selection_title ); n++;
2345   }
2346 
2347   XtSetValues( XtParent( form ), args, n );
2348 
2349   /* We must catch close events on the shell and prevent it from being
2350      destroyed. */
2351   XmAddProtocolCallback( XtParent( form ), protocol_atom, delete_atom,
2352                          (XtCallbackProc) PopdownTimeSelectionDialogCB,
2353                          (XtPointer) tbox );
2354 
2355   /* Callbacks. */
2356   XtAddCallback( time_slider, XmNactivateCallback,
2357                  (XtCallbackProc) TimeSelectedInDialogCB, (XtPointer) tbox );
2358   XtAddCallback( ok, XmNactivateCallback,
2359                  (XtCallbackProc) TimeSelectedInDialogCB, (XtPointer) tbox );
2360   XtAddCallback( cancel, XmNactivateCallback,
2361                  (XtCallbackProc) PopdownTimeSelectionDialogCB,
2362                  (XtPointer) tbox );
2363 
2364 
2365   /* Manage the internal widget (but not the form!) */
2366   XtManageChild( time_slider );
2367   XtManageChild( sep );
2368   XtManageChild( ok );
2369   XtManageChild( cancel );
2370 
2371   /* Set both buttons the same size. */
2372   n = 0;
2373   XtSetArg( args[ n ], XmNwidth, &width ); n++;
2374   XtSetArg( args[ n ], XmNheight, &height ); n++;
2375   XtGetValues( ok, args, n );
2376 
2377   max_width  = width;
2378   max_height = height;
2379 
2380   XtGetValues( cancel, args, n );
2381 
2382   if( width > max_width )
2383     max_width = width;
2384   if( height > max_height )
2385      max_height = height;
2386 
2387   n = 0;
2388   XtSetArg( args[ n ], XmNwidth, max_width ); n++;
2389   XtSetArg( args[ n ], XmNheight, max_height ); n++;
2390   XtSetValues( ok, args, n );
2391   XtSetValues( cancel, args, n );
2392 
2393   /* Cleanup. */
2394   XtFree( name_buffer );
2395 
2396   /* Back to stopping child widgets. */
2397   tbox -> tbox.internal_widgets_created = True;
2398 
2399 
2400   return;
2401 
2402 } /* CreateTimeSelectionPopup */
2403 
2404 
2405 /*----------------------------------------------------------------------*/
2406 
2407 static void
DateCompletionCB(Widget tw,XmUbTimeBoxWidget tbox,XmTextVerifyCallbackStruct * call_data)2408   DateCompletionCB( Widget                      tw,
2409                     XmUbTimeBoxWidget           tbox,
2410                     XmTextVerifyCallbackStruct  *call_data )
2411 {
2412   /* Variables. */
2413   int                child_index;
2414   Boolean            restart;
2415   XmUbTimeBoxStatus  status;
2416 
2417   /* Code. */
2418 
2419 DateCompletionCB_START:
2420 
2421   /* Find child index for this field. */
2422   child_index = ChildIndex( tbox, tw );
2423 
2424   /* Completion is different depending on which field we are dealing with. */
2425   switch( child_index ){
2426 
2427     case XmUbTB_CHILD_START_DATE:
2428       status = CompleteStartDate( tbox );
2429       break;
2430 
2431 
2432     case XmUbTB_CHILD_END_DATE:
2433       status = CompleteEndDate( tbox );
2434       break;
2435 
2436     default:
2437       /* This should not happen. */
2438       printf( "DateCompletionCB ERROR, called for wrong child.\n" );
2439       return;
2440 
2441   } /* switch */
2442 
2443   /* Issue the callback(s). */
2444   restart = TimeCompletionCallback( tw, child_index, tbox,
2445 				  (XmAnyCallbackStruct *) call_data,
2446 				  status );
2447   if( restart )
2448     goto DateCompletionCB_START;
2449 
2450 
2451   return;
2452 
2453 } /* DateCompletionCB */
2454 
2455 
2456 /*----------------------------------------------------------------------*/
2457 
2458 #if XmVersion > 1001
2459 
2460 static void
DateDropCB(Widget w,XtPointer client_data,XmDropProcCallbackStruct * drop_data)2461   DateDropCB( Widget                    w,
2462               XtPointer                 client_data,
2463               XmDropProcCallbackStruct  *drop_data )
2464 {
2465   /* Variables. */
2466   Arg                     args[ 5 ];
2467   Atom                    compound_text_atom;
2468   Atom                    date_transfer_atom;
2469   Atom                    *export_list;
2470   int                     index;
2471   XmTextPosition          insert_pos;
2472   Cardinal                n;
2473   Cardinal                num_exports;
2474   int                     num_transfers = 0;
2475   XmDropTransferEntryRec  transfer_entries[ 2 ];
2476   XmDropTransferEntry     transfer_list;
2477 
2478   /* Code. */
2479 
2480   compound_text_atom = XmInternAtom( XtDisplay( w ), "COMPOUND_TEXT", False );
2481   date_transfer_atom = XmInternAtom( XtDisplay( w ), XmUbDATE_TRANSFER,
2482                                      False );
2483 
2484   /* Set the transfer resources. */
2485   n = 0;
2486 
2487   /* Cancel the drop if the action is not a drop or if user wants a link. */
2488   if( ( drop_data -> dropAction != XmDROP ) ||
2489       ( drop_data -> operation  == XmDROP_LINK ) ){
2490     XtSetArg( args[ n ], XmNtransferStatus, XmTRANSFER_FAILURE ); n++;
2491 
2492   } else {
2493     /* Go on with the drop. Establish the transfer list and start transfer. */
2494 
2495     /* Get the exported targets for the drag context and select the
2496        desired one. */
2497     n = 0;
2498     XtSetArg( args[ n ], XmNexportTargets, &export_list ); n++;
2499     XtSetArg( args[ n ], XmNnumExportTargets, &num_exports ); n++;
2500     XtGetValues( drop_data -> dragContext, args, n );
2501 
2502     /* Our preferred format is date transfer. See if we can find it. */
2503     for( index = 0; index < num_exports; index ++ ){
2504 
2505       if( export_list[ index ] == date_transfer_atom ){
2506         transfer_entries[ 0 ].target      = date_transfer_atom;
2507         transfer_entries[ 0 ].client_data = (XtPointer) w;
2508         num_transfers = 1;
2509 
2510         break;
2511       }
2512     }
2513 
2514     /* Alternative format is compound text. */
2515     if( num_transfers == 0 ){
2516 
2517       for( index = 0; index < num_exports; index ++ ){
2518 
2519         if( export_list[ index ] == compound_text_atom ){
2520           transfer_entries[ 0 ].target      = compound_text_atom;
2521           transfer_entries[ 0 ].client_data = (XtPointer) w;
2522           num_transfers = 1;
2523 
2524           /* The text should be inserted at the drop position. */
2525           insert_pos = XmTextXYToPos( w, drop_data -> x, drop_data -> y );
2526           XmTextSetInsertionPosition( w, insert_pos );
2527 
2528           break;
2529         }
2530       }
2531     }
2532 
2533     transfer_list = transfer_entries;
2534 
2535     XtSetArg( args[ n ], XmNdropTransfers, transfer_list ); n++;
2536     XtSetArg( args[ n ], XmNnumDropTransfers, num_transfers ); n++;
2537     XtSetArg( args[ n ], XmNtransferProc, TransferDateField ); n++;
2538   }
2539 
2540   /* Start the transfer or cancel. */
2541   XmDropTransferStart( drop_data -> dragContext, args, n );
2542 
2543 
2544   return;
2545 
2546 } /* DateDropCB */
2547 
2548 #endif
2549 
2550 /*----------------------------------------------------------------------*/
2551 
2552 static void
DeleteChild(Widget widget)2553   DeleteChild( Widget  widget )
2554 {
2555 
2556   /* Variables. */
2557   int                index;
2558   XmUbTimeBoxWidget  tbox;
2559 
2560   /* Code. */
2561 
2562   tbox = (XmUbTimeBoxWidget) XtParent( widget );
2563 
2564   /* Clear the internal reference. */
2565   for( index = 0; index < NO_INTERNAL_CHILDREN; index ++ ){
2566     if( tbox -> tbox.internal_children[ index ] == widget ){
2567       tbox -> tbox.internal_children[ index ] = NULL;
2568       break;
2569     }
2570   }
2571 
2572   /* Perform the actual operation */
2573   (* ( (CompositeWidgetClass) (xmUbTimeBoxWidgetClass ->
2574      core_class.superclass) ) -> composite_class.delete_child ) ( widget );
2575 
2576 
2577   return;
2578 
2579 } /* DeleteChild */
2580 
2581 
2582 /*----------------------------------------------------------------------*/
2583 
2584 static void
Destroy(Widget widget)2585   Destroy( Widget   widget )
2586 {
2587   /* Variables. */
2588   XmUbTimeBoxWidget  tbox;
2589 
2590   /* Code. */
2591 
2592   tbox = (XmUbTimeBoxWidget) widget;
2593 
2594   /* Free the copied strings. */
2595   if( tbox -> tbox.year_marker != NULL )
2596     XtFree( tbox -> tbox.year_marker );
2597   if( tbox -> tbox.month_marker != NULL )
2598     XtFree( tbox -> tbox.month_marker );
2599   if( tbox -> tbox.week_marker != NULL )
2600     XtFree( tbox -> tbox.week_marker );
2601   if( tbox -> tbox.day_marker != NULL )
2602     XtFree( tbox -> tbox.day_marker );
2603   if( tbox -> tbox.hour_marker != NULL )
2604     XtFree( tbox -> tbox.hour_marker );
2605   if( tbox -> tbox.minute_marker != NULL )
2606     XtFree( tbox -> tbox.minute_marker );
2607 
2608   if( tbox -> tbox.time_selection_title != NULL )
2609     XtFree( tbox -> tbox.time_selection_title );
2610   if( tbox -> tbox.date_selection_title != NULL )
2611     XtFree( tbox -> tbox.date_selection_title );
2612 
2613   /* Free XmStrings. */
2614   if( tbox -> tbox.ok_label != NULL )
2615     XmStringFree( tbox -> tbox.ok_label );
2616   if( tbox -> tbox.cancel_label != NULL )
2617     XmStringFree( tbox -> tbox.cancel_label );
2618   if( tbox -> tbox.week_label != NULL )
2619     XmStringFree( tbox -> tbox.week_label );
2620   if( tbox -> tbox.month_label != NULL )
2621     XmStringFree( tbox -> tbox.month_label );
2622   if( tbox -> tbox.year_label != NULL )
2623     XmStringFree( tbox -> tbox.year_label );
2624 
2625   /* Remove callbacks. */
2626   XtRemoveAllCallbacks( widget, XmNactivateCallback );
2627   XtRemoveAllCallbacks( widget, XmNvalueChangedCallback );
2628   XtRemoveAllCallbacks( widget, XmUbNtboxCompletionCallback );
2629 
2630 
2631   return;
2632 
2633 } /* Destroy */
2634 
2635 
2636 /*----------------------------------------------------------------------*/
2637 
2638 static void
DoLayout(XmUbTimeBoxWidget tbox,Widget initiator,XtWidgetGeometry * request,KidDimensionRec sizes[])2639   DoLayout( XmUbTimeBoxWidget  tbox,
2640             Widget             initiator,
2641             XtWidgetGeometry   *request,
2642             KidDimensionRec    sizes[] )
2643 {
2644   /* Variables. */
2645   int               index;
2646   Widget            kid;
2647 
2648   /* Code. */
2649 
2650   /* All positions and dimensions are in the sizes array. */
2651   if( tbox -> tbox.menu_enabled &&
2652       ( tbox -> tbox.internal_children[ XmUbTB_CHILD_MENU_BAR ] != NULL ) ){
2653 
2654     index = XmUbTB_CHILD_MENU_BAR;
2655     kid   = tbox -> tbox.internal_children[ index ];
2656 
2657     XtConfigureWidget( kid, sizes[ index ].x, sizes[ index ].y,
2658       sizes[ index ].width, sizes[ index ].height, kid -> core.border_width );
2659   }
2660 
2661   /* Loop for the text widgets. */
2662   for( index = XmUbTB_CHILD_START_DATE; index < NO_INTERNAL_CHILDREN;
2663        index ++ ){
2664 
2665     kid = tbox -> tbox.internal_children[ index ];
2666 
2667     if( ( kid != NULL ) && XtIsManaged( kid ) )
2668       XtConfigureWidget( kid, sizes[ index ].x, sizes[ index ].y,
2669         sizes[ index ].width, sizes[ index ].height,
2670         kid -> core.border_width );
2671   }
2672 
2673 
2674   return;
2675 
2676 } /* DoLayout */
2677 
2678 
2679 /*----------------------------------------------------------------------*/
2680 
2681 static void
DateSelectedInDialogCB(Widget md,XmUbTimeBoxWidget tbox,XmUbMonthDisplayCallbackStruct * call_data)2682   DateSelectedInDialogCB( Widget                          md,
2683                           XmUbTimeBoxWidget               tbox,
2684                           XmUbMonthDisplayCallbackStruct  *call_data )
2685 {
2686   /* Variables. */
2687   char                       buffer[ TIME_STRING_BUFFER_LEN ];
2688   XmUbTimeBoxCallbackStruct  cb;
2689   Boolean                    known_field = True;
2690   TIM_TIME_REF               time;
2691 
2692   /* Code. */
2693 
2694   /* Get the selected date. */
2695   time = TimMakeTime( call_data -> selected_year, call_data -> selected_month,
2696                       call_data -> selected_day, 0, 0, 0 );
2697 
2698   /* Create the string. */
2699   TimFormatDate( time, buffer, TIME_STRING_BUFFER_LEN - 1 );
2700 
2701   if( call_data -> range ){
2702 
2703     /* The first date is the start date. */
2704     (void) XmUbTimeBoxSetStartDateString( (Widget) tbox, buffer );
2705 
2706     /* Set the end date too. */
2707     time = TimMakeTime( call_data -> end_year, call_data -> end_month,
2708                         call_data -> end_day, 0, 0, 0 );
2709     TimFormatDate( time, buffer, TIME_STRING_BUFFER_LEN - 1 );
2710 
2711     (void) XmUbTimeBoxSetEndDateString( (Widget) tbox, buffer );
2712 
2713   } else {
2714 
2715     switch( tbox -> tbox.field_for_date_selection ){
2716 
2717       case XmUbTB_CHILD_START_DATE:
2718         (void) XmUbTimeBoxSetStartDateString( (Widget) tbox, buffer );
2719         break;
2720 
2721       case XmUbTB_CHILD_END_DATE:
2722         (void) XmUbTimeBoxSetEndDateString( (Widget) tbox, buffer );
2723         break;
2724 
2725       default:
2726         known_field = False;
2727         break;
2728     }
2729   }
2730 
2731   /* We have to call the callback to pop down the dialog here, since it
2732      might destroy the widget. */
2733   PopdownDateSelectionDialogCB( md, tbox, (XmAnyCallbackStruct *) call_data );
2734 
2735   /* Call activate callback. */
2736   if( known_field && ( tbox -> tbox.activate_callback != NULL ) ){
2737 
2738     /* Set up callback structure. */
2739 
2740     cb.reason      = XmUbCR_DATE_PICKED;
2741     cb.event       = NULL;
2742     cb.child_index = tbox -> tbox.field_for_date_selection;
2743     cb.child       = tbox -> tbox.internal_children[ cb.child_index ];
2744     cb.range       = call_data -> range;
2745 
2746     XtCallCallbackList( (Widget) tbox, tbox -> tbox.activate_callback,
2747                         (XtPointer) &cb );
2748   }
2749 
2750 
2751   return;
2752 
2753 } /* DateSelectedInDialogCB */
2754 
2755 
2756 /*----------------------------------------------------------------------*/
2757 
2758 static void
FillInStartOfMonth(XmUbTimeBoxWidget tbox)2759   FillInStartOfMonth( XmUbTimeBoxWidget  tbox )
2760 {
2761   /* Variables. */
2762   TIM_TIME_REF  now;
2763   TIM_TIME_REF  tloc;
2764   int           month, year;
2765 
2766   /* Code. */
2767 
2768   /* Get the start date of the week and display it in the text field. */
2769   now  = TimMakeTimeNow();
2770   tloc = TimLocalTime( now );
2771 
2772   year  = TimIndexOfYear( tloc );
2773   month = TimIndexOfMonth( tloc );
2774 
2775   /* Get start of week. */
2776   tloc = TimMakeTime( year, month, 1, 0, 0, 0 );
2777 
2778   (void) XmUbTimeBoxSetStartDate( (Widget) tbox, tloc );
2779   (void) XmUbTimeBoxSetStartTime( (Widget) tbox, tloc );
2780 
2781 
2782   return;
2783 
2784 } /* FillInStartOfMonth */
2785 
2786 
2787 /*----------------------------------------------------------------------*/
2788 
2789 static void
FillInStartOfWeek(XmUbTimeBoxWidget tbox)2790   FillInStartOfWeek( XmUbTimeBoxWidget  tbox )
2791 {
2792   /* Variables. */
2793   TIM_TIME_REF     now;
2794   TIM_STATUS_TYPE  status;
2795   TIM_TIME_REF     tloc;
2796   int              week, year;
2797 
2798   /* Code. */
2799 
2800   /* Get the start date of the week and display it in the text field. */
2801   now  = TimMakeTimeNow();
2802   tloc = TimLocalTime( now );
2803 
2804   year = TimIndexOfYear( tloc );
2805   week = TimIndexOfWeek( tloc );
2806 
2807   /* Get start of week. */
2808   status = TimMakeTimeFromWeek( year, week, &tloc );
2809   if( status != TIM_OK )
2810     return;
2811 
2812   (void) XmUbTimeBoxSetStartDate( (Widget) tbox, tloc );
2813   (void) XmUbTimeBoxSetStartTime( (Widget) tbox, tloc );
2814 
2815 
2816   return;
2817 
2818 } /* FillInStartOfWeek */
2819 
2820 
2821 /*----------------------------------------------------------------------*/
2822 
2823 static XtGeometryResult
GeometryManager(Widget widget,XtWidgetGeometry * request,XtWidgetGeometry * reply)2824   GeometryManager( Widget            widget,
2825                    XtWidgetGeometry  *request,
2826                    XtWidgetGeometry  *reply )
2827 {
2828 
2829   XtWidgetGeometry   own_request;
2830   Dimension          old_width, old_height;
2831   Dimension          pref_height;
2832   Dimension          pref_width;
2833   KidDimensionRec    kids_sizes[ NO_INTERNAL_CHILDREN ];
2834   XtGeometryResult   result;
2835   XmUbTimeBoxWidget  tbox;
2836 
2837   /* Code. */
2838 
2839   tbox = (XmUbTimeBoxWidget) XtParent( widget );
2840 
2841   /* Find out how big the widget would be if the resize were allowed. */
2842   GetChildPrefSizes( tbox, NULL, request, kids_sizes );
2843   PrepareLayout( tbox, kids_sizes, &pref_width, &pref_height );
2844 
2845   /* If no change in dimensions, allow the request. */
2846   if( ( pref_width == tbox -> core.width ) &&
2847       ( pref_height == tbox -> core.height )){
2848     DoLayout( tbox, widget, request, kids_sizes );
2849     return XtGeometryYes;
2850   }
2851 
2852   /* We must ask our parent to resize us. */
2853   own_request.request_mode = CWWidth | CWHeight;
2854   own_request.width  = pref_width;
2855   own_request.height = pref_height;
2856 
2857   /* Save dimensions. */
2858   old_width  = tbox -> core.width;
2859   old_height = tbox -> core.height;
2860 
2861   tbox -> tbox.resize_called = False;
2862 
2863   /* We are not interested in any compromise geometry. */
2864   result = XtMakeGeometryRequest( (Widget) tbox, &own_request, NULL );
2865 
2866   /* Reset to old dimensions if request not granted. */
2867   if( result != XtGeometryYes ){
2868     tbox -> core.width  = old_width;
2869     tbox -> core.height = old_height;
2870 
2871   } else {
2872     if( !tbox -> tbox.resize_called )
2873       Resize( (Widget) tbox );
2874   }
2875 
2876   /* Always grant child's request. */
2877   return XtGeometryYes;
2878 
2879 } /* GeometryManager */
2880 
2881 
2882 /*----------------------------------------------------------------------*/
2883 
2884 static void
GetChildPrefSizes(XmUbTimeBoxWidget tbox,Widget initiator,XtWidgetGeometry * request,KidDimensionRec sizes[])2885   GetChildPrefSizes( XmUbTimeBoxWidget  tbox,
2886                      Widget             initiator,
2887                      XtWidgetGeometry   *request,
2888                      KidDimensionRec    sizes[] )
2889 {
2890   /* Variables. */
2891   XtWidgetGeometry  desired;
2892   int               index;
2893   Widget            kid;
2894 
2895   /* Code. */
2896 
2897   /* Initialize. */
2898   for( index = 0; index < NO_INTERNAL_CHILDREN; index ++ ){
2899     sizes[ index ].width  = 0;
2900     sizes[ index ].height = 0;
2901     sizes[ index ].x      = 0;
2902     sizes[ index ].y      = 0;
2903   }
2904 
2905   /* Get the preferred sizes for the children. */
2906   for( index = 0; index < NO_INTERNAL_CHILDREN; index ++ ){
2907 
2908     /* The pulldown menu should not be considered. */
2909     if( ( index == XmUbTB_CHILD_MENU_PD ) ||
2910         ( index == XmUbTB_CHILD_MENU_CASC ) )
2911       continue;
2912 
2913     kid = tbox -> tbox.internal_children[ index ];
2914 
2915     if( ( kid != NULL ) && XtIsManaged( kid ) ){
2916 
2917       KidsPreferredGeometry( kid, initiator, request, &desired );
2918 
2919       sizes[ index ].width  = desired.width;
2920       sizes[ index ].height = desired.height;
2921 
2922     }
2923 
2924   } /* for */
2925 
2926 
2927   return;
2928 
2929 } /* GetChildPrefSizes */
2930 
2931 
2932 /*----------------------------------------------------------------------*/
2933 
2934 XmUbTimeBoxStatus
GetChildString(XmUbTimeBoxWidget tbox,int child,char ** str)2935   GetChildString( XmUbTimeBoxWidget  tbox,
2936                   int                child,
2937                   char               **str )
2938 {
2939   /* Variables. */
2940   Widget  tw;
2941 
2942   /* Code. */
2943 
2944   tw = tbox -> tbox.internal_children[ child ];
2945   if( tw == NULL )
2946     return( TBOX_NO_FIELD );
2947 
2948   *str = XmTextGetString( tw );
2949 
2950   /* For an empty string, we return a status value. */
2951   if( strlen( *str ) == 0 ){
2952     XtFree( *str );
2953     return( TBOX_EMPTY );
2954   }
2955 
2956   return( TBOX_OK );
2957 
2958 } /* GetChildString */
2959 
2960 
2961 /*----------------------------------------------------------------------*/
2962 
2963 XmUbTimeBoxStatus
GetStartDateTime(XmUbTimeBoxWidget tbox,Boolean use_defaults,TIM_TIME_REF * date_time)2964   GetStartDateTime( XmUbTimeBoxWidget  tbox,
2965                     Boolean            use_defaults,
2966                     TIM_TIME_REF       *date_time )
2967 {
2968   /* Variables. */
2969   TIM_TIME_REF       date;
2970   XmUbTimeBoxStatus  status;
2971   TIM_TIME_REF       time;
2972 
2973   /* Code. */
2974 
2975   status = XmUbTimeBoxGetStartDate( (Widget) tbox, &date );
2976   if( status != TBOX_OK ){
2977     if( use_defaults )
2978       date = TimMakeTime( 1970, 1, 1, 0, 0, 0 );
2979     else
2980       return( status );
2981   }
2982 
2983   status = XmUbTimeBoxGetStartTime( (Widget) tbox, &time );
2984   if( status != TBOX_OK ){
2985     if( use_defaults )
2986       time = TimMakeTime( 1970, 1, 1, 0, 0, 0 );
2987     else
2988       return( status );
2989   }
2990 
2991   /* Construct combined time. */
2992   *date_time = CombineDateAndTime( date, time );
2993 
2994 
2995   return( TBOX_OK );
2996 
2997 } /* GetStartDateTime */
2998 
2999 
3000 /*----------------------------------------------------------------------*/
3001 
3002 static void
GetValuesHook(Widget w,ArgList args,Cardinal * num_args)3003   GetValuesHook( Widget    w,
3004                  ArgList   args,
3005                  Cardinal  *num_args )
3006 {
3007   /* Variables. */
3008   int                index;
3009   XmUbTimeBoxWidget  tbox;
3010 
3011   /* Code. */
3012 
3013   tbox = (XmUbTimeBoxWidget) w;
3014 
3015   /* Copy the XmStrings. */
3016   for( index = 0; index < *num_args; index ++ ){
3017 
3018     if( strcmp( args[ index ].name, XmNcancelLabelString ) == 0 ){
3019       * ( XmString *) ( args[ index ].value ) =
3020         XmStringCopy( tbox -> tbox.cancel_label );
3021 
3022     } else if( strcmp( args[ index ].name, XmNokLabelString ) == 0 ){
3023       * ( XmString *) ( args[ index ].value ) =
3024         XmStringCopy( tbox -> tbox.ok_label );
3025 
3026     } else if( strcmp( args[ index ].name, XmUbNtboxMonthLabel ) == 0 ){
3027       * ( XmString *) ( args[ index ].value ) =
3028         XmStringCopy( tbox -> tbox.month_label );
3029 
3030     } else if( strcmp( args[ index ].name, XmUbNtboxWeekLabel ) == 0 ){
3031       * ( XmString *) ( args[ index ].value ) =
3032         XmStringCopy( tbox -> tbox.week_label );
3033 
3034     } else if( strcmp( args[ index ].name, XmUbNtboxYearLabel ) == 0 ){
3035       * ( XmString *) ( args[ index ].value ) =
3036         XmStringCopy( tbox -> tbox.year_label );
3037 
3038     }
3039   }
3040 
3041 
3042   return;
3043 
3044 } /* GetValuesHook */
3045 
3046 
3047 /*----------------------------------------------------------------------*/
3048 
3049 static void
Initialize(Widget treq,Widget tnew,ArgList args,Cardinal * num_args)3050   Initialize( Widget     treq,
3051               Widget     tnew,
3052               ArgList    args,
3053               Cardinal   *num_args )
3054 {
3055 
3056   /* Variables. */
3057   int                index;
3058   KidDimensionRec    kids_sizes[ NO_INTERNAL_CHILDREN ];
3059   XmUbTimeBoxWidget  new;
3060   char               *newstr;
3061   Dimension          pref_width;
3062   Dimension          pref_height;
3063   char               *str;
3064   XmString           xm;
3065 
3066   /* Code. */
3067 
3068   new = (XmUbTimeBoxWidget) tnew;
3069 
3070   /* Initialize private fields. */
3071   for( index = 0; index < NO_INTERNAL_CHILDREN; index ++ )
3072     new -> tbox.internal_children[ index ] = NULL;
3073 
3074   new -> tbox.time_selection_popup = NULL;
3075   new -> tbox.date_selection_popup = NULL;
3076 
3077   new -> tbox.field_for_time_selection = XmUbTB_CHILD_START_TIME;
3078   new -> tbox.field_for_date_selection = XmUbTB_CHILD_START_DATE;
3079 
3080   /* Start size if none supplied. */
3081   if( new -> core.width == 0 )
3082     new -> core.width = 100;
3083   if( new -> core.height == 0 )
3084     new -> core.height = 100;
3085 
3086   /* The atoms must be set up here, since we need a display varaible for it. */
3087   if( ! context_dependent_done ){
3088     protocol_atom = XmInternAtom( XtDisplay( tnew ), "WM_PROTOCOLS", False );
3089     delete_atom   = XmInternAtom( XtDisplay( tnew ),
3090       "WM_DELETE_WINDOW", False );
3091 
3092     context_dependent_done = True;
3093   }
3094 
3095   /* Copy XmStrings and/or use defaults. */
3096   if( new -> tbox.ok_label == NULL )
3097     xm = XmStringCreateLtoR( default_ok_string, XmSTRING_DEFAULT_CHARSET );
3098   else
3099     xm = XmStringCopy( new -> tbox.ok_label );
3100   new -> tbox.ok_label = xm;
3101 
3102   if( new -> tbox.cancel_label == NULL )
3103     xm = XmStringCreateLtoR( default_cancel_string, XmSTRING_DEFAULT_CHARSET );
3104   else
3105     xm = XmStringCopy( new -> tbox.cancel_label );
3106   new -> tbox.cancel_label = xm;
3107 
3108   if( new -> tbox.week_label != NULL ){
3109     xm = XmStringCopy( new -> tbox.week_label );
3110     new -> tbox.week_label = xm;
3111   }
3112   if( new -> tbox.month_label != NULL ){
3113     xm = XmStringCopy( new -> tbox.month_label );
3114     new -> tbox.month_label = xm;
3115   }
3116   if( new -> tbox.year_label != NULL ){
3117     xm = XmStringCopy( new -> tbox.year_label );
3118     new -> tbox.year_label = xm;
3119   }
3120 
3121   /* Copy title strings. */
3122   if( new -> tbox.time_selection_title != NULL ){
3123     str = XtMalloc( strlen( new -> tbox.time_selection_title ) + 1 );
3124     strcpy( str, new -> tbox.time_selection_title );
3125     new -> tbox.time_selection_title = str;
3126   }
3127   if( new -> tbox.date_selection_title != NULL ){
3128     str = XtMalloc( strlen( new -> tbox.date_selection_title ) + 1 );
3129     strcpy( str, new -> tbox.date_selection_title );
3130     new -> tbox.date_selection_title = str;
3131   }
3132 
3133 
3134   /* Copy strings for scanning. */
3135 #define SetMarker( field, default )   \
3136 { \
3137   if( field == NULL ){ \
3138     newstr = XtMalloc( strlen( default )+1 ); \
3139     strcpy( newstr, default ); \
3140     field = newstr; \
3141   } else { \
3142     newstr = XtMalloc( strlen( field )+1 ); \
3143     strcpy( newstr, field ); \
3144     field = newstr; \
3145   } \
3146 }
3147 
3148   SetMarker( new -> tbox.day_marker,    default_day_marker );
3149   SetMarker( new -> tbox.hour_marker,   default_hour_marker );
3150   SetMarker( new -> tbox.minute_marker, default_minute_marker );
3151   SetMarker( new -> tbox.month_marker,  default_month_marker );
3152   SetMarker( new -> tbox.week_marker,   default_week_marker );
3153   SetMarker( new -> tbox.year_marker,   default_year_marker );
3154 
3155 #undef SetMarker
3156 
3157 
3158   /* Create the internal widgets. */
3159   new -> tbox.internal_widgets_created = False;
3160 
3161   CreateInternalWidgets( new );
3162 
3163   new -> tbox.internal_widgets_created = True;
3164 
3165 
3166   /* Set the desired dimensions of the widget. */
3167   GetChildPrefSizes( new, NULL, NULL, kids_sizes );
3168   PrepareLayout( new, kids_sizes, &pref_width, &pref_height );
3169 
3170   new -> core.width  = pref_width;
3171   new -> core.height = pref_height;
3172 
3173   DoLayout( new, NULL, NULL, kids_sizes );
3174 
3175 
3176   return;
3177 
3178 } /* Initialize */
3179 
3180 
3181 /*----------------------------------------------------------------------*/
3182 
3183 static void
InitializeItem(int index,XmUbMenuItem items[],XmUbItem item,String label,XtCallbackProc proc,XtPointer client_data)3184   InitializeItem( int             index,
3185                   XmUbMenuItem    items[],
3186                   XmUbItem        item,
3187                   String          label,
3188                   XtCallbackProc  proc,
3189                   XtPointer       client_data )
3190 {
3191   /* Variables. */
3192 
3193   /* Code. */
3194 
3195   items[ index ].item = item;
3196 
3197   items[ index ].name = XtMalloc( 5 );
3198   if( item == XmUbITEM_PUSH_BUTTON )
3199     sprintf( items[ index ].name, "Bu%d", index );
3200   else
3201     sprintf( items[ index ].name, "Sep%d", index );
3202 
3203   items[ index ].label = XmStringCreateLtoR( label, XmSTRING_DEFAULT_CHARSET );
3204 
3205   items[ index ].proc        = proc;
3206   items[ index ].client_data = client_data;
3207 
3208 
3209   return;
3210 
3211 } /* InitializeItem */
3212 
3213 
3214 /*----------------------------------------------------------------------*/
3215 
3216 static void
InitializeDefaultMenu(XmUbTimeBoxWidget tbox,XmUbMenuItem items[],int * num_items_created)3217   InitializeDefaultMenu( XmUbTimeBoxWidget  tbox,
3218                          XmUbMenuItem       items[],
3219                          int                *num_items_created )
3220 {
3221   /* Variables. */
3222   int   n = 0;
3223 
3224   /* Code. */
3225 
3226   /* The items in the menu depend on the widget format. */
3227 
3228   /* The first field applies to all formats. */
3229   InitializeItem( n++, items, XmUbITEM_PUSH_BUTTON,
3230                   "Now", XmUbTB_ACTION_NOW, NULL );
3231 
3232   /* These apply only to ranges with two date fields. */
3233   if( ( tbox -> tbox.widget_format == XmUbTB_FORMAT_DD ) ||
3234       ( tbox -> tbox.widget_format == XmUbTB_FORMAT_DTDT ) ){
3235 
3236     InitializeItem( n++, items, XmUbITEM_SEPARATOR,
3237                     "", XmUbTB_NO_ACTION, NULL );
3238     InitializeItem( n++, items, XmUbITEM_PUSH_BUTTON,
3239                     "This week", XmUbTB_ACTION_THIS_WEEK, NULL );
3240     InitializeItem( n++, items, XmUbITEM_PUSH_BUTTON,
3241                     "This month", XmUbTB_ACTION_THIS_MONTH, NULL );
3242    }
3243 
3244   /* The following apply to range fields that include the time. */
3245   if( ( tbox -> tbox.widget_format == XmUbTB_FORMAT_TT )  ||
3246       ( tbox -> tbox.widget_format == XmUbTB_FORMAT_DTT ) ||
3247       ( tbox -> tbox.widget_format == XmUbTB_FORMAT_DTDT ) ){
3248 
3249     InitializeItem( n++, items, XmUbITEM_SEPARATOR,
3250                     "", XmUbTB_NO_ACTION, NULL );
3251     InitializeItem( n++, items, XmUbITEM_PUSH_BUTTON,
3252                     "+ One Hour", XmUbTB_ACTION_PLUS_ONE_HOUR, NULL );
3253     InitializeItem( n++, items, XmUbITEM_PUSH_BUTTON,
3254                     "+ Two Hours", XmUbTB_ACTION_PLUS_TWO_HOURS, NULL );
3255   }
3256 
3257   /* These apply to ranges with date fields. */
3258   if( ( tbox -> tbox.widget_format == XmUbTB_FORMAT_DD ) ||
3259       ( tbox -> tbox.widget_format == XmUbTB_FORMAT_DTDT ) ){
3260 
3261     InitializeItem( n++, items, XmUbITEM_SEPARATOR,
3262                     "", XmUbTB_NO_ACTION, NULL );
3263     InitializeItem( n++, items, XmUbITEM_PUSH_BUTTON,
3264                     "+ One Week", XmUbTB_ACTION_PLUS_ONE_WEEK, NULL );
3265     InitializeItem( n++, items, XmUbITEM_PUSH_BUTTON,
3266                     "+ Two Weeks", XmUbTB_ACTION_PLUS_TWO_WEEKS, NULL );
3267     InitializeItem( n++, items, XmUbITEM_PUSH_BUTTON,
3268                     "+ One Month", XmUbTB_ACTION_PLUS_ONE_MONTH, NULL );
3269   }
3270 
3271 
3272   *num_items_created = n;
3273 
3274   return;
3275 
3276 } /* InitializeDefaultMenu */
3277 
3278 
3279 /*----------------------------------------------------------------------*/
3280 
3281 static void
InsertChild(Widget widget)3282   InsertChild( Widget  widget )
3283 {
3284 
3285   /* Variables. */
3286   Cardinal           num_params;
3287   String             params[ 1 ];
3288   XmUbTimeBoxWidget  tbox;
3289 
3290   /* Code. */
3291 
3292   tbox = (XmUbTimeBoxWidget) XtParent( widget );
3293 
3294   /* We do not allow the application to create children. */
3295   if( tbox -> tbox.internal_widgets_created ){
3296 
3297     params[ 0 ] = XtClass( tbox ) -> core_class.class_name;
3298     num_params  = 1;
3299     XtAppErrorMsg( XtWidgetToApplicationContext( widget ),
3300                    "childError", "number", "WidgetError",
3301                    "Applications cannot add children to %s widgets.",
3302                    params, &num_params );
3303   }
3304 
3305   /* This is an internal child. Adding it is OK. */
3306   (* ( (CompositeWidgetClass) (xmUbTimeBoxWidgetClass ->
3307      core_class.superclass) ) -> composite_class.insert_child ) ( widget );
3308 
3309 
3310   return;
3311 
3312 } /* InsertChild */
3313 
3314 
3315 /*----------------------------------------------------------------------*/
3316 
3317 static void
KidsPreferredGeometry(Widget kid,Widget initiator,XtWidgetGeometry * request,XtWidgetGeometry * desired)3318   KidsPreferredGeometry( Widget            kid,
3319                          Widget            initiator,
3320                          XtWidgetGeometry  *request,
3321                          XtWidgetGeometry  *desired )
3322 {
3323 
3324   /* Code. */
3325 
3326   if( ( kid == initiator ) && ( request != NULL ) ){
3327     /* The initiator should not be queried. */
3328     if( request -> request_mode & CWWidth )
3329       desired -> width = request -> width;
3330     else
3331       desired -> width = (Dimension) kid -> core.width;
3332 
3333     if( request -> request_mode & CWHeight )
3334       desired -> height = request -> height;
3335     else
3336       desired -> height = (Dimension) kid -> core.height;
3337 
3338   } else
3339     (void) XtQueryGeometry( kid, NULL, desired );
3340 
3341 
3342   return;
3343 
3344 } /* KidsPreferredGeometry */
3345 
3346 
3347 /*----------------------------------------------------------------------*/
3348 
3349 static void
MenuItemActivatedCB(Widget pb,XtCallbackProc action,XmAnyCallbackStruct * call_data)3350   MenuItemActivatedCB( Widget               pb,
3351                        XtCallbackProc       action,
3352                        XmAnyCallbackStruct  *call_data )
3353 {
3354   /* Variables. */
3355   Arg                        args[ 5 ];
3356   XmUbTimeBoxCallbackStruct  cb;
3357   Cardinal                   n;
3358   Boolean                    range = True;
3359   XmUbTimeBoxWidget          tbox;
3360 
3361   /* Code. */
3362 
3363   /* The time box widget id is in user data. */
3364   n = 0;
3365   XtSetArg( args[ n ], XmNuserData, &tbox ); n++;
3366   XtGetValues( pb, args, n );
3367 
3368   /* What to do depends on the selected action. */
3369   switch((intptr_t)action){
3370 
3371     case (intptr_t) XmUbTB_ACTION_THIS_WEEK:
3372       FillInStartOfWeek( tbox );
3373       AddDateWeek( tbox, 1, 1 );
3374       break;
3375 
3376     case (intptr_t) XmUbTB_ACTION_THIS_MONTH:
3377       FillInStartOfMonth( tbox );
3378       AddDateMonth( tbox, 1, 1 );
3379       break;
3380 
3381     case (intptr_t) XmUbTB_ACTION_PLUS_ONE_HOUR:
3382       AddDateHour( tbox, 1 );
3383       break;
3384 
3385     case (intptr_t) XmUbTB_ACTION_PLUS_TWO_HOURS:
3386       AddDateHour( tbox, 2 );
3387       break;
3388 
3389     case (intptr_t) XmUbTB_ACTION_PLUS_ONE_WEEK:
3390       AddDateWeek( tbox, 1, 0 );
3391       break;
3392 
3393     case (intptr_t) XmUbTB_ACTION_PLUS_TWO_WEEKS:
3394       AddDateWeek( tbox, 2, 0 );
3395       break;
3396 
3397     case (intptr_t) XmUbTB_ACTION_PLUS_ONE_MONTH:
3398       AddDateMonth( tbox, 1, 0 );
3399       break;
3400 
3401     case (intptr_t) XmUbTB_ACTION_TIME_NOW:
3402       (void) XmUbTimeBoxSetStartTime( (Widget) tbox,
3403                                       TimLocalTime( TimMakeTimeNow() ) );
3404       range = False;
3405       break;
3406 
3407     case (intptr_t) XmUbTB_ACTION_DATE_NOW:
3408       (void) XmUbTimeBoxSetStartDate( (Widget) tbox,
3409                                       TimLocalTime( TimMakeTimeNow() ) );
3410       range = False;
3411       break;
3412 
3413     case (intptr_t) XmUbTB_ACTION_NOW:
3414       (void) XmUbTimeBoxSetStartDate( (Widget) tbox,
3415                                       TimLocalTime( TimMakeTimeNow() ) );
3416       (void) XmUbTimeBoxSetStartTime( (Widget) tbox,
3417                                       TimLocalTime( TimMakeTimeNow() ) );
3418       range = False;
3419 
3420       break;
3421 
3422     default:
3423       return;
3424 
3425   } /* switch */
3426 
3427   /* Set the keyboard focus to the most recently inserted text. */
3428   switch( (intptr_t) action ){
3429 
3430     case (intptr_t) XmUbTB_ACTION_TIME_NOW:
3431       /* Set keyboard focus to the start time field. */
3432       if( tbox -> tbox.internal_children[ XmUbTB_CHILD_START_TIME ] != NULL )
3433         XmProcessTraversal(
3434           tbox -> tbox.internal_children[ XmUbTB_CHILD_START_TIME ],
3435           XmTRAVERSE_CURRENT );
3436 
3437       break;
3438 
3439     case (intptr_t) XmUbTB_ACTION_DATE_NOW:
3440       /* Set keyboard focus to the start date field. */
3441       if( tbox -> tbox.internal_children[ XmUbTB_CHILD_START_DATE ] != NULL )
3442         XmProcessTraversal(
3443           tbox -> tbox.internal_children[ XmUbTB_CHILD_START_DATE ],
3444           XmTRAVERSE_CURRENT );
3445 
3446       break;
3447 
3448     case (intptr_t) XmUbTB_ACTION_NOW:
3449       /* Set keyboard focus to the start time or date field. */
3450       if( tbox -> tbox.internal_children[ XmUbTB_CHILD_START_TIME ] != NULL )
3451         XmProcessTraversal(
3452           tbox -> tbox.internal_children[ XmUbTB_CHILD_START_TIME ],
3453           XmTRAVERSE_CURRENT );
3454       else if(
3455            tbox -> tbox.internal_children[ XmUbTB_CHILD_START_DATE ] != NULL )
3456         XmProcessTraversal(
3457           tbox -> tbox.internal_children[ XmUbTB_CHILD_START_DATE ],
3458           XmTRAVERSE_CURRENT );
3459 
3460       break;
3461 
3462     default:
3463       /* Set keyboard focus to the end time or date field. */
3464       if( tbox -> tbox.internal_children[ XmUbTB_CHILD_END_TIME ] != NULL )
3465         XmProcessTraversal(
3466           tbox -> tbox.internal_children[ XmUbTB_CHILD_END_TIME ],
3467           XmTRAVERSE_CURRENT );
3468       else if(
3469            tbox -> tbox.internal_children[ XmUbTB_CHILD_END_DATE ] != NULL )
3470         XmProcessTraversal(
3471           tbox -> tbox.internal_children[ XmUbTB_CHILD_END_DATE ],
3472           XmTRAVERSE_CURRENT );
3473 
3474       break;
3475 
3476   } /* switch */
3477 
3478   /* A default action was selected. Invoke activate callbacks. */
3479   if( tbox -> tbox.activate_callback != NULL ){
3480 
3481     cb.reason      = XmUbCR_DEFAULT_ACTION;
3482     cb.event       = NULL;
3483     cb.child_index = 0;
3484     cb.child       = NULL;
3485     cb.action      = action;
3486     cb.range       = range;
3487 
3488     XtCallCallbackList( (Widget) tbox, tbox -> tbox.activate_callback,
3489                         (XtPointer) &cb );
3490 
3491   }
3492 
3493 
3494 
3495   return;
3496 
3497 } /* MenuItemActivatedCB */
3498 
3499 
3500 /*----------------------------------------------------------------------*/
3501 
3502 Widget
MonthDisplayId(XmUbTimeBoxWidget tbox)3503   MonthDisplayId( XmUbTimeBoxWidget  tbox )
3504 {
3505   /* Variables. */
3506   char    *name_buffer;
3507   Widget  md;
3508   String  wname;
3509 
3510   /* Code. */
3511 
3512   wname = XtName( (Widget)tbox );
3513 
3514   /* Get the id of the month display widget. */
3515   name_buffer = XtMalloc( strlen( wname ) + 8 );
3516   /* sprintf( name_buffer, "%sMd", wname, wname ); */
3517   sprintf( name_buffer, "%sMd", wname );
3518 
3519   md = XtNameToWidget( tbox -> tbox.date_selection_popup, name_buffer );
3520 
3521   XtFree( name_buffer );
3522 
3523 
3524   return( md );
3525 
3526 } /* MonthDisplayId */
3527 
3528 
3529 /*----------------------------------------------------------------------*/
3530 
3531 static void
Resize(Widget widget)3532   Resize( Widget    widget )
3533 {
3534 
3535   XmUbTimeBoxWidget  tbox;
3536 
3537   /* Code. */
3538 
3539   tbox = (XmUbTimeBoxWidget) widget;
3540 
3541   tbox -> tbox.resize_called = True;
3542 
3543   /* The sizes or positions of the children do not depend on the
3544      time box widget size, so we don't need to recalculate anything. */
3545 
3546 
3547   return;
3548 
3549 } /* Resize */
3550 
3551 
3552 /*----------------------------------------------------------------------*/
3553 
3554 static XtGeometryResult
QueryGeometry(Widget widget,XtWidgetGeometry * proposed,XtWidgetGeometry * answer)3555   QueryGeometry( Widget             widget,
3556                  XtWidgetGeometry  *proposed,
3557                  XtWidgetGeometry  *answer )
3558 {
3559 
3560   KidDimensionRec    kids_sizes[ NO_INTERNAL_CHILDREN ];
3561   Dimension          pref_height;
3562   Dimension          pref_width;
3563   XmUbTimeBoxWidget  tbox;
3564 
3565   /* Code. */
3566 
3567 
3568   tbox = (XmUbTimeBoxWidget) widget;
3569 
3570   /* Get dimensions that we *really* want. */
3571   GetChildPrefSizes( tbox, NULL, NULL, kids_sizes );
3572   PrepareLayout( tbox, kids_sizes, &pref_width, &pref_height );
3573 
3574   answer -> request_mode = CWWidth | CWHeight;
3575   answer -> width  = pref_width;
3576   answer -> height = pref_height;
3577 
3578 
3579   if( proposed == NULL ){
3580     /* This is a query for the requested geometry. */
3581 
3582     if(( answer -> height == (int) tbox -> core.height ) &&
3583        ( answer -> width  == (int) tbox -> core.width ))
3584       return XtGeometryNo;
3585     else
3586       return XtGeometryAlmost;
3587   }
3588 
3589 
3590   /* The parent supplied a geometry suggestion. */
3591   if(( answer -> height == proposed -> height ) &&
3592      ( answer -> width  == proposed -> width ))
3593     return XtGeometryYes;
3594 
3595   if( ( proposed -> height <= 1 ) ||
3596       ( proposed -> width  <= 1 ) )
3597     /* That's too small ! */
3598     return XtGeometryNo;
3599 
3600 
3601   /* Only a compromise left. */
3602   return XtGeometryAlmost;
3603 
3604 } /* QueryGeometry */
3605 
3606 
3607 /*----------------------------------------------------------------------*/
3608 
3609 static void
PopdownDateSelectionDialogCB(Widget md,XmUbTimeBoxWidget tbox,XmAnyCallbackStruct * call_data)3610   PopdownDateSelectionDialogCB( Widget               md,
3611                                 XmUbTimeBoxWidget    tbox,
3612                                 XmAnyCallbackStruct  *call_data )
3613 {
3614   /* Code. */
3615 
3616   if( tbox -> tbox.destroy_dialogs ){
3617     XtDestroyWidget( XtParent( tbox -> tbox.date_selection_popup ) );
3618     tbox -> tbox.date_selection_popup = NULL;
3619 
3620   } else
3621     XtUnmanageChild( tbox -> tbox.date_selection_popup );
3622 
3623 
3624   return;
3625 
3626 } /* PopdownDateSelectionDialogCB */
3627 
3628 
3629 /*----------------------------------------------------------------------*/
3630 
3631 static void
PopdownTimeSelectionDialogCB(Widget tw,XmUbTimeBoxWidget tbox,XmAnyCallbackStruct * call_data)3632   PopdownTimeSelectionDialogCB( Widget               tw,
3633                                 XmUbTimeBoxWidget    tbox,
3634                                 XmAnyCallbackStruct  *call_data )
3635 {
3636   /* Code. */
3637 
3638   if( tbox -> tbox.destroy_dialogs ){
3639     XtDestroyWidget( XtParent( tbox -> tbox.time_selection_popup ) );
3640     tbox -> tbox.time_selection_popup = NULL;
3641 
3642   } else
3643     XtUnmanageChild( tbox -> tbox.time_selection_popup );
3644 
3645 
3646   return;
3647 
3648 } /* PopdownTimeSelectionDialogCB */
3649 
3650 
3651 /*----------------------------------------------------------------------*/
3652 
3653 static void
PopupDateSelection(Widget widget)3654   PopupDateSelection( Widget  widget )
3655 {
3656   /* Variables. */
3657   XmUbTimeBoxStatus  status;
3658   XmUbTimeBoxWidget  tbox;
3659   time_t             time;
3660 
3661   /* Code. */
3662 
3663   /* We are called with the child. */
3664   tbox = (XmUbTimeBoxWidget) XtParent( widget );
3665 
3666   /* If user callback, call it. */
3667   if( tbox -> tbox.popup_selection_callback != NULL ){
3668     CallDialogPopupCallback( tbox, widget, XmUbCR_POPUP_DATE_SELECTION );
3669 
3670     return;
3671   }
3672 
3673   /* No callback is set and we should use our own dialog. */
3674   if( tbox -> tbox.date_selection_popup == NULL )
3675     CreateDateSelectionPopup( tbox );
3676 
3677   /* Set the index of the child that popped up the dialog. */
3678   tbox -> tbox.field_for_date_selection = ChildIndex( tbox, widget );
3679 
3680   /* Pop up the dialog. */
3681 
3682   /* Set the current month first. */
3683   switch( tbox -> tbox.field_for_date_selection ){
3684     case XmUbTB_CHILD_START_DATE:
3685       status = XmUbTimeBoxGetStartDate( (Widget) tbox, &time );
3686       break;
3687 
3688     case XmUbTB_CHILD_END_DATE:
3689       status = XmUbTimeBoxGetEndDate( (Widget) tbox, &time );
3690 
3691       /* If no date is entered, try with the starting date as default. */
3692       if( status != TBOX_OK )
3693         status = XmUbTimeBoxGetStartDate( (Widget) tbox, &time );
3694       break;
3695 
3696     default:
3697       /* Can only be popped up from a date field. */
3698       return;
3699   }
3700 
3701   /* If no default date, use today. */
3702   if( status != TBOX_OK )
3703     time = TimLocalTime( TimMakeTimeNow() );
3704 
3705   XmUbMonthDisplaySetMonth( MonthDisplayId( tbox ), TimIndexOfYear( time ),
3706                             TimIndexOfMonth( time ) );
3707 
3708   XtManageChild( tbox -> tbox.date_selection_popup );
3709 
3710   /* Set the focus to the current date. */
3711   XmUbMonthDisplaySetFocusToDay( MonthDisplayId( tbox ),
3712                                  TimIndexOfDay( time ) );
3713 
3714 
3715   return;
3716 
3717 } /* PopupDateSelection */
3718 
3719 
3720 /*----------------------------------------------------------------------*/
3721 
3722 static void
PopupDateSelectionAction(Widget w,XEvent * event,String * params,Cardinal num_params)3723   PopupDateSelectionAction( Widget    w,
3724                             XEvent    *event,
3725                             String    *params,
3726                             Cardinal  num_params )
3727 {
3728   /* Variables. */
3729   Widget  parent;
3730 
3731   /* Code. */
3732 
3733   parent = XtParent( w );
3734 
3735   (* ( (XmUbTimeBoxClassRec *) ( XtClass( parent ) ) ) ->
3736      timebox_class.popup_date_selection ) ( w );
3737 
3738 
3739   return;
3740 
3741 } /* PopupDateSelectionAction */
3742 
3743 
3744 /*----------------------------------------------------------------------*/
3745 
3746 static void
PopupTimeSelection(Widget widget)3747   PopupTimeSelection( Widget  widget )
3748 {
3749   /* Variables. */
3750   XmUbTimeBoxStatus  status;
3751   XmUbTimeBoxWidget  tbox;
3752   Widget             text_field;
3753   time_t             time;
3754 
3755   /* Code. */
3756 
3757   /* We are called with the child. */
3758   tbox = (XmUbTimeBoxWidget) XtParent( widget );
3759 
3760   /* If user callback, call it. */
3761   if( tbox -> tbox.popup_selection_callback != NULL ){
3762     CallDialogPopupCallback( tbox, widget, XmUbCR_POPUP_TIME_SELECTION );
3763 
3764     return;
3765   }
3766 
3767   /* No callback is set and we should use our own dialog. */
3768   if( tbox -> tbox.time_selection_popup == NULL )
3769     CreateTimeSelectionPopup( tbox );
3770 
3771   /* Set the index of the child that popped up the dialog. */
3772   tbox -> tbox.field_for_time_selection = ChildIndex( tbox, widget );
3773 
3774 
3775   /* Set the start time first. */
3776   switch( tbox -> tbox.field_for_time_selection ){
3777     case XmUbTB_CHILD_START_TIME:
3778       status = XmUbTimeBoxGetStartTime( (Widget) tbox, &time );
3779       break;
3780 
3781     case XmUbTB_CHILD_END_TIME:
3782       status = XmUbTimeBoxGetEndTime( (Widget) tbox, &time );
3783       break;
3784 
3785     default:
3786       /* Can only be popped up from a time field. */
3787       return;
3788 
3789   }
3790 
3791   /* If we could get no default, use now. */
3792   if( status != TBOX_OK )
3793     time = TimLocalTime( TimMakeTimeNow() );
3794 
3795   XmUbTimeSliderSetTime( TimeSliderId( tbox ), time );
3796 
3797   XtManageChild( tbox -> tbox.time_selection_popup );
3798 
3799   /* Set keyboard focus to the text field. */
3800   text_field = XmUbTimeSliderGetChild( TimeSliderId( tbox ),
3801                                        XmUbTS_CHILD_TEXT_FIELD );
3802   if( text_field != NULL )
3803     XmProcessTraversal( text_field, XmTRAVERSE_CURRENT );
3804 
3805 
3806   return;
3807 
3808 } /* PopupTimeSelection */
3809 
3810 
3811 /*----------------------------------------------------------------------*/
3812 
3813 static void
PopupTimeSelectionAction(Widget w,XEvent * event,String * params,Cardinal num_params)3814   PopupTimeSelectionAction( Widget    w,
3815                             XEvent    *event,
3816                             String    *params,
3817                             Cardinal  num_params )
3818 {
3819   /* Variables. */
3820   Widget  parent;
3821 
3822   /* Code. */
3823 
3824   parent = XtParent( w );
3825 
3826   (* ( (XmUbTimeBoxClassRec *) ( XtClass( parent ) ) ) ->
3827      timebox_class.popup_time_selection ) ( w );
3828 
3829 
3830   return;
3831 
3832 } /* PopupTimeSelectionAction */
3833 
3834 
3835 /*----------------------------------------------------------------------*/
3836 
3837 static void
PrepareLayout(XmUbTimeBoxWidget tbox,KidDimensionRec sizes[],Dimension * own_width,Dimension * own_height)3838   PrepareLayout( XmUbTimeBoxWidget  tbox,
3839                  KidDimensionRec    sizes[],
3840                  Dimension          *own_width,
3841                  Dimension          *own_height )
3842 {
3843   /* Variables. */
3844   int        first_field;
3845   int        index_of_first_field = 0;
3846   int        index_of_last_field = 0;
3847   int        last_field;
3848   int        index;
3849   Dimension  max_widget_height;
3850   Dimension  max_widget_width;
3851   Position   pos_offset;
3852   Dimension  spacing;
3853   Position   text_field_start;
3854   int        use_field;
3855 
3856   /* Code. */
3857 
3858   if( tbox -> tbox.menu_enabled &&
3859       ( tbox -> tbox.menu_position == XmUbPOSITION_FIRST ) ){
3860     /* The menu should be placed to the left of the first field. */
3861     sizes[ XmUbTB_CHILD_MENU_BAR ].x = (Position) tbox -> tbox.margin_width;
3862 
3863     text_field_start = sizes[ XmUbTB_CHILD_MENU_BAR ].x +
3864       (Position) sizes[ XmUbTB_CHILD_MENU_BAR ].width +
3865       (Position) tbox -> tbox.menu_spacing;
3866 
3867   } else {
3868     /* Menu last or not at all. */
3869     text_field_start = (Position) tbox -> tbox.margin_width;
3870   }
3871 
3872   /* Position the text widgets. */
3873 
3874   switch( tbox -> tbox.widget_format ){
3875     case XmUbTB_FORMAT_D:
3876     case XmUbTB_FORMAT_T:
3877       if( tbox -> tbox.widget_format == XmUbTB_FORMAT_D )
3878         index = XmUbTB_CHILD_START_DATE;
3879       else
3880         index = XmUbTB_CHILD_START_TIME;
3881 
3882       sizes[ index ].x = text_field_start;
3883       sizes[ index ].y = (Position) tbox -> tbox.margin_height;
3884 
3885       *own_width  = (Dimension) sizes[ index ].x + sizes[ index ].width +
3886                     2 * tbox -> tbox.margin_width;
3887       *own_height = MAX( sizes[ XmUbTB_CHILD_MENU_BAR ].height,
3888                          sizes[ index ].height ) +
3889                     2 * tbox -> tbox.margin_height;
3890 
3891       index_of_first_field = index;
3892       index_of_last_field  = index;
3893 
3894       break;
3895 
3896     case XmUbTB_FORMAT_DT:
3897     case XmUbTB_FORMAT_DD:
3898     case XmUbTB_FORMAT_TT:
3899 
3900       if( tbox -> tbox.widget_format == XmUbTB_FORMAT_DT ){
3901         first_field = XmUbTB_CHILD_START_DATE;
3902         last_field  = XmUbTB_CHILD_START_TIME;
3903         spacing     = tbox -> tbox.field_spacing;
3904 
3905       } else if( tbox -> tbox.widget_format == XmUbTB_FORMAT_DD ){
3906         first_field = XmUbTB_CHILD_START_DATE;
3907         last_field  = XmUbTB_CHILD_END_DATE;
3908         spacing     = tbox -> tbox.range_spacing;
3909 
3910       } else {
3911         first_field = XmUbTB_CHILD_START_TIME;
3912         last_field  = XmUbTB_CHILD_END_TIME;
3913         spacing     = tbox -> tbox.range_spacing;
3914       }
3915 
3916       sizes[ first_field ].x = text_field_start;
3917       sizes[ first_field ].y = (Position) tbox -> tbox.margin_height;
3918 
3919       if( ( tbox -> tbox.orientation == XmHORIZONTAL ) ||
3920           ( ( tbox -> tbox.widget_format == XmUbTB_FORMAT_DT ) &&
3921             tbox -> tbox.component_together ) ){
3922         /* Text fields should be ordered horizontally. */
3923         sizes[ last_field ].x = sizes[ first_field ].x +
3924           (Position) sizes[ first_field ].width + (Position) spacing;
3925 
3926         sizes[ last_field ].y = sizes[ first_field ].y;
3927 
3928         *own_width = (Dimension) sizes[ last_field ].x +
3929           sizes[ last_field ].width + tbox -> tbox.margin_width;
3930 
3931         *own_height = MAX( MAX( sizes[ first_field ].height,
3932                                 sizes[ last_field ].height ),
3933                            sizes[ XmUbTB_CHILD_MENU_BAR ].height ) +
3934                       2 * tbox -> tbox.margin_height;
3935 
3936       } else {
3937         /* Text fields should be ordered vertically. */
3938 
3939         sizes[ last_field ].x = sizes[ first_field ].x;
3940 
3941         sizes[ last_field ].y = sizes[ first_field ].y +
3942           (Position) sizes[ first_field ].height + (Position) spacing;
3943 
3944         *own_width = (Dimension) sizes[ first_field ].x +
3945           MAX( sizes[ first_field ].width, sizes[ last_field ].width ) +
3946           tbox -> tbox.margin_width;
3947 
3948         *own_height = (Dimension) sizes[ last_field ].y +
3949                       sizes[ last_field ].height + tbox -> tbox.margin_height;
3950       }
3951 
3952       index_of_first_field = first_field;
3953       index_of_last_field  = last_field;
3954 
3955       break;
3956 
3957     case XmUbTB_FORMAT_DTDT:
3958       sizes[ XmUbTB_CHILD_START_DATE ].x = text_field_start;
3959       sizes[ XmUbTB_CHILD_START_DATE ].y =
3960         (Position) tbox -> tbox.margin_height;
3961 
3962       if( tbox -> tbox.orientation == XmHORIZONTAL ){
3963         /* Horizontal orientation. */
3964 
3965         sizes[ XmUbTB_CHILD_START_TIME ].x =
3966           sizes[ XmUbTB_CHILD_START_DATE ].x +
3967           (Position) sizes[ XmUbTB_CHILD_START_DATE ].width +
3968           (Position) tbox -> tbox.field_spacing;
3969         sizes[ XmUbTB_CHILD_START_TIME ].y =
3970           sizes[ XmUbTB_CHILD_START_DATE ].y;
3971 
3972         sizes[ XmUbTB_CHILD_END_DATE ].x =
3973           sizes[ XmUbTB_CHILD_START_TIME ].x +
3974           (Position) sizes[ XmUbTB_CHILD_START_TIME ].width +
3975           (Position) tbox -> tbox.range_spacing;
3976         sizes[ XmUbTB_CHILD_END_DATE ].y =
3977           sizes[ XmUbTB_CHILD_START_DATE ].y;
3978 
3979         sizes[ XmUbTB_CHILD_END_TIME ].x =
3980           sizes[ XmUbTB_CHILD_END_DATE ].x +
3981           (Position) sizes[ XmUbTB_CHILD_END_DATE ].width +
3982           (Position) tbox -> tbox.field_spacing;
3983         sizes[ XmUbTB_CHILD_END_TIME ].y =
3984           sizes[ XmUbTB_CHILD_START_DATE ].y;
3985 
3986         max_widget_height = sizes[ XmUbTB_CHILD_MENU_BAR ].height;
3987         for( index = XmUbTB_CHILD_START_DATE; index < NO_INTERNAL_CHILDREN;
3988              index ++ ){
3989           if( sizes[ index ].height > max_widget_height )
3990             max_widget_height = sizes[ index ].height;
3991         }
3992 
3993         *own_width = (Dimension) sizes[ XmUbTB_CHILD_END_TIME ].y +
3994                      sizes[ XmUbTB_CHILD_END_TIME ].width +
3995                      tbox -> tbox.margin_width;
3996         *own_height = max_widget_height + 2 * tbox -> tbox.margin_height;
3997 
3998       } else if( tbox -> tbox.component_together ){
3999         /* Place the text widgets in two rows. */
4000 
4001         sizes[ XmUbTB_CHILD_START_TIME ].x =
4002           sizes[ XmUbTB_CHILD_START_DATE ].x +
4003           (Position) sizes[ XmUbTB_CHILD_START_DATE ].width +
4004           (Position) tbox -> tbox.field_spacing;
4005         sizes[ XmUbTB_CHILD_START_TIME ].y =
4006           sizes[ XmUbTB_CHILD_START_DATE ].y;
4007 
4008         sizes[ XmUbTB_CHILD_END_DATE ].x = sizes[ XmUbTB_CHILD_START_DATE ].x;
4009         sizes[ XmUbTB_CHILD_END_DATE ].y = sizes[ XmUbTB_CHILD_START_DATE ].y +
4010           (Position) sizes[ XmUbTB_CHILD_START_DATE ].height +
4011           (Position) tbox -> tbox.range_spacing;
4012 
4013         sizes[ XmUbTB_CHILD_END_TIME ].x = sizes[ XmUbTB_CHILD_END_DATE ].x +
4014           (Position) sizes[ XmUbTB_CHILD_END_DATE ].width +
4015           (Position) tbox -> tbox.field_spacing;
4016         sizes[ XmUbTB_CHILD_END_TIME ].y = sizes[ XmUbTB_CHILD_END_DATE ].y;
4017 
4018         *own_width = MAX( (Dimension) sizes[ XmUbTB_CHILD_START_TIME ].x +
4019                           sizes[ XmUbTB_CHILD_START_TIME ].width,
4020                           (Dimension) sizes[ XmUbTB_CHILD_END_TIME ].x +
4021                           sizes[ XmUbTB_CHILD_END_TIME ].width ) +
4022                      tbox -> tbox.margin_width;
4023         *own_height = (Dimension) sizes[ XmUbTB_CHILD_END_TIME ].y +
4024                       MAX( sizes[ XmUbTB_CHILD_END_TIME ].height,
4025                            sizes[ XmUbTB_CHILD_END_DATE ].height ) +
4026                       tbox -> tbox.margin_height;
4027 
4028       } else {
4029         /* Place all text fields under eachother. */
4030 
4031         sizes[ XmUbTB_CHILD_START_TIME ].x =
4032           sizes[ XmUbTB_CHILD_START_DATE ].x;
4033         sizes[ XmUbTB_CHILD_START_TIME ].y =
4034           sizes[ XmUbTB_CHILD_START_DATE ].y +
4035           (Position) sizes[ XmUbTB_CHILD_START_DATE ].height +
4036           (Position) tbox -> tbox.field_spacing;
4037 
4038         sizes[ XmUbTB_CHILD_END_DATE ].x =
4039           sizes[ XmUbTB_CHILD_START_DATE ].x;
4040         sizes[ XmUbTB_CHILD_END_DATE ].y =
4041           sizes[ XmUbTB_CHILD_START_TIME ].y +
4042           (Position) sizes[ XmUbTB_CHILD_START_TIME ].height +
4043           (Position) tbox -> tbox.range_spacing;
4044 
4045         sizes[ XmUbTB_CHILD_END_TIME ].x =
4046           sizes[ XmUbTB_CHILD_START_DATE ].x;
4047         sizes[ XmUbTB_CHILD_END_TIME ].y =
4048           sizes[ XmUbTB_CHILD_END_DATE ].y +
4049           (Position) sizes[ XmUbTB_CHILD_END_DATE ].height +
4050           (Position) tbox -> tbox.field_spacing;
4051 
4052         max_widget_width = 0;
4053         for( index = XmUbTB_CHILD_START_DATE; index < NO_INTERNAL_CHILDREN;
4054              index ++ ){
4055           if( sizes[ index ].width > max_widget_width )
4056             max_widget_width = sizes[ index ].width;
4057         }
4058 
4059         *own_width = (Dimension) sizes[ XmUbTB_CHILD_START_DATE ].x +
4060                      max_widget_width + tbox -> tbox.margin_width;
4061         *own_height = (Dimension) sizes[ XmUbTB_CHILD_END_TIME ].y +
4062                       sizes[ XmUbTB_CHILD_END_TIME ].height +
4063                       tbox -> tbox.margin_height;
4064       }
4065 
4066       index_of_first_field = XmUbTB_CHILD_START_DATE;
4067       index_of_last_field  = XmUbTB_CHILD_END_TIME;
4068 
4069       break;
4070 
4071     case XmUbTB_FORMAT_DTT:
4072       sizes[ XmUbTB_CHILD_START_DATE ].x = text_field_start;
4073       sizes[ XmUbTB_CHILD_START_DATE ].y =
4074         (Position) tbox -> tbox.margin_height;
4075 
4076       if( tbox -> tbox.orientation == XmHORIZONTAL ){
4077         /* Lay out the text fields horizontally. */
4078         sizes[ XmUbTB_CHILD_START_TIME ].x =
4079           sizes[ XmUbTB_CHILD_START_DATE ].x +
4080           (Position) sizes[ XmUbTB_CHILD_START_DATE ].width +
4081           (Position) tbox -> tbox.field_spacing;
4082         sizes[ XmUbTB_CHILD_START_TIME ].y =
4083           sizes[ XmUbTB_CHILD_START_DATE ].y;
4084 
4085         sizes[ XmUbTB_CHILD_END_TIME ].x = sizes[ XmUbTB_CHILD_START_TIME ].x +
4086           (Position) sizes[ XmUbTB_CHILD_START_TIME ].width +
4087           (Position) tbox -> tbox.range_spacing;
4088         sizes[ XmUbTB_CHILD_END_TIME ].y =
4089           sizes[ XmUbTB_CHILD_START_DATE ].y;
4090 
4091         max_widget_height = sizes[ XmUbTB_CHILD_MENU_BAR ].height;
4092         for( index = XmUbTB_CHILD_START_DATE; index < NO_INTERNAL_CHILDREN;
4093              index ++ ){
4094           if( sizes[ index ].height > max_widget_height )
4095             max_widget_height = sizes[ index ].height;
4096         }
4097 
4098         *own_width = (Dimension) sizes[ XmUbTB_CHILD_END_TIME ].x +
4099           sizes[ XmUbTB_CHILD_END_TIME ].width + tbox -> tbox.margin_width;
4100         *own_height = max_widget_height + 2 * tbox -> tbox.margin_height;
4101 
4102       } else if( tbox -> tbox.component_together ){
4103         /* Place the text widgets in two rows. */
4104 
4105         sizes[ XmUbTB_CHILD_START_TIME ].x =
4106           sizes[ XmUbTB_CHILD_START_DATE ].x +
4107           (Position) sizes[ XmUbTB_CHILD_START_DATE ].width +
4108           (Position) tbox -> tbox.field_spacing;
4109         sizes[ XmUbTB_CHILD_START_TIME ].y =
4110           sizes[ XmUbTB_CHILD_START_DATE ].y;
4111 
4112         sizes[ XmUbTB_CHILD_END_TIME ].x = sizes[ XmUbTB_CHILD_START_TIME ].x;
4113         sizes[ XmUbTB_CHILD_END_TIME ].y = sizes[ XmUbTB_CHILD_START_TIME ].y +
4114           (Position) sizes[ XmUbTB_CHILD_START_TIME ].height +
4115           (Position) tbox -> tbox.range_spacing;
4116 
4117         *own_width = MAX( (Dimension) sizes[ XmUbTB_CHILD_START_TIME ].x +
4118                           sizes[ XmUbTB_CHILD_START_TIME ].width,
4119                           (Dimension) sizes[ XmUbTB_CHILD_END_TIME ].x +
4120                           sizes[ XmUbTB_CHILD_END_TIME ].width ) +
4121                      tbox -> tbox.margin_width;
4122 
4123         *own_height = (Dimension) sizes[ XmUbTB_CHILD_END_TIME ].y +
4124            sizes[ XmUbTB_CHILD_END_TIME ].height +
4125            tbox -> tbox.margin_height;
4126 
4127       } else {
4128         /* Lay out all text widgets vertically. */
4129 
4130         sizes[ XmUbTB_CHILD_START_TIME ].x =
4131           sizes[ XmUbTB_CHILD_START_DATE ].x;
4132         sizes[ XmUbTB_CHILD_START_TIME ].y =
4133           sizes[ XmUbTB_CHILD_START_DATE ].y +
4134           (Position) sizes[ XmUbTB_CHILD_START_DATE ].height +
4135           (Position) tbox -> tbox.field_spacing;
4136 
4137         sizes[ XmUbTB_CHILD_END_TIME ].x =
4138           sizes[ XmUbTB_CHILD_START_DATE ].x;
4139         sizes[ XmUbTB_CHILD_END_TIME ].y =
4140           sizes[ XmUbTB_CHILD_START_TIME ].y +
4141           (Position) sizes[ XmUbTB_CHILD_START_TIME ].height +
4142           (Position) tbox -> tbox.range_spacing;
4143 
4144         max_widget_width = 0;
4145         for( index = XmUbTB_CHILD_START_DATE; index < NO_INTERNAL_CHILDREN;
4146              index ++ ){
4147           if( sizes[ index ].width > max_widget_width )
4148             max_widget_width = sizes[ index ].width;
4149         }
4150 
4151         *own_width = (Dimension) sizes[ XmUbTB_CHILD_START_DATE ].x +
4152                      max_widget_width + tbox -> tbox.margin_width;
4153         *own_height = (Dimension) sizes[ XmUbTB_CHILD_END_TIME ].y +
4154                       sizes[ XmUbTB_CHILD_END_TIME ].height +
4155                       tbox -> tbox.margin_height;
4156       }
4157 
4158       index_of_first_field = XmUbTB_CHILD_START_DATE;
4159       index_of_last_field  = XmUbTB_CHILD_END_TIME;
4160 
4161       break;
4162   }
4163 
4164   /* If the menu button should be placed last, this is the time to do it. */
4165   if( tbox -> tbox.menu_enabled ){
4166 
4167     if( tbox -> tbox.menu_position == XmUbPOSITION_FIRST ){
4168       /* The menu has already been positioned horizontally. */
4169       use_field = index_of_first_field;
4170 
4171     } else {
4172       /* Position the menu after the last field. */
4173       use_field = index_of_last_field;
4174 
4175       sizes[ XmUbTB_CHILD_MENU_BAR ].x = sizes[ use_field ].x +
4176         (Position) ( sizes[ use_field ].width + tbox -> tbox.menu_spacing );
4177 
4178       *own_width += ( sizes[ XmUbTB_CHILD_MENU_BAR ].width +
4179                       tbox -> tbox.menu_spacing );
4180     }
4181 
4182     /* Center the menu vertically with the adjacent field. */
4183 
4184     if( sizes[ use_field ].height > sizes[ XmUbTB_CHILD_MENU_BAR ].height )
4185       pos_offset = (Position) ( sizes[ use_field ].height -
4186         sizes[ XmUbTB_CHILD_MENU_BAR ].height ) / 2;
4187     else
4188       pos_offset = - (Position) ( sizes[ XmUbTB_CHILD_MENU_BAR ].height -
4189         sizes[ use_field ].height ) / 2;
4190 
4191     sizes[ XmUbTB_CHILD_MENU_BAR ].y = sizes[ use_field ].y + pos_offset;
4192 
4193   }
4194 
4195   /* Modify own height if menu button last. */
4196   if( tbox -> tbox.menu_enabled &&
4197       ( tbox -> tbox.menu_position == XmUbPOSITION_LAST ) ){
4198 
4199       *own_height = MAX( ( (Dimension) sizes[ XmUbTB_CHILD_MENU_BAR ].y +
4200                            sizes[ XmUbTB_CHILD_MENU_BAR ].height ),
4201                          ( (Dimension) sizes[ use_field ].y +
4202                            sizes[ use_field ].height ) ) +
4203                     tbox -> tbox.margin_height;
4204   }
4205 
4206 
4207   return;
4208 
4209 } /* PrepareLayout */
4210 
4211 
4212 /*----------------------------------------------------------------------*/
4213 
4214 static Boolean
ResizeIfNeeded(XmUbTimeBoxWidget tbox,KidDimensionRec sizes[])4215   ResizeIfNeeded( XmUbTimeBoxWidget  tbox,
4216                   KidDimensionRec    sizes[] )
4217 {
4218 
4219   /* Variables. */
4220   Boolean           layout_done;
4221   Dimension         pref_height;
4222   Dimension         pref_width;
4223   XtWidgetGeometry  request;
4224   XtGeometryResult  result;
4225 
4226   /* Code. */
4227 
4228   /* Initialize. */
4229   layout_done = False;
4230 
4231   /* Get the preferred dimensions of the time box widget. */
4232   GetChildPrefSizes( tbox, NULL, NULL, sizes );
4233   PrepareLayout( tbox, sizes, &pref_width, &pref_height );
4234 
4235   /* If we want the same dimensions, no resizing is needed. */
4236   if(( pref_width  == tbox -> core.width ) &&
4237      ( pref_height == tbox -> core.height ))
4238     return False;
4239 
4240   /* Dimensions are different. Try to resize. */
4241   request.request_mode = CWWidth | CWHeight;
4242 
4243   request.width  = pref_width;
4244   request.height = pref_height;
4245 
4246   tbox -> tbox.resize_called = False;
4247 
4248   do {
4249 
4250     result = XtMakeGeometryRequest( (Widget) tbox, &request, &request );
4251 
4252   } while( result == XtGeometryAlmost );
4253 
4254   if( result == XtGeometryNo )
4255     return False;
4256 
4257   /* Resize done. Core fields have already been updated. */
4258   return( tbox -> tbox.resize_called );
4259 
4260 } /* ResizeIfNeeded */
4261 
4262 
4263 /*----------------------------------------------------------------------*/
4264 
4265 static void
SelectAllTextCB(Widget tw,XmUbTimeBoxWidget tbox,XmAnyCallbackStruct * call_data)4266   SelectAllTextCB( Widget               tw,
4267                    XmUbTimeBoxWidget    tbox,
4268                    XmAnyCallbackStruct  *call_data )
4269 {
4270   /* Variables. */
4271   XmTextPosition  last;
4272 
4273   /* Code. */
4274 
4275   /* Select all text in the text widget. */
4276 
4277   last = XmTextGetLastPosition( tw );
4278 
4279   if( last > 0 )
4280     XmTextSetSelection( tw, 0, last, CurrentTime );
4281 
4282   /* Set the insertion position to the start of the widget. */
4283   XmTextSetInsertionPosition( tw, 0 );
4284 
4285 
4286   return;
4287 
4288 } /* SelectAllTextCB */
4289 
4290 
4291 /*----------------------------------------------------------------------*/
4292 
4293 XmUbTimeBoxStatus
SetChildString(XmUbTimeBoxWidget tbox,int child,char * str)4294   SetChildString( XmUbTimeBoxWidget  tbox,
4295                   int                child,
4296                   char               *str )
4297 {
4298   /* Variables. */
4299   Widget  tw;
4300 
4301   /* Code. */
4302 
4303   tw = tbox -> tbox.internal_children[ child ];
4304   if( tw == NULL )
4305     return( TBOX_NO_FIELD );
4306 
4307   XmTextSetString( tw, str );
4308 
4309 
4310   return( TBOX_OK );
4311 
4312 } /* SetChildString */
4313 
4314 
4315 /*----------------------------------------------------------------------*/
4316 
4317 static Boolean
SetValues(Widget current,Widget request,Widget new,ArgList args,Cardinal * num_args)4318   SetValues( Widget     current,
4319              Widget     request,
4320              Widget     new,
4321              ArgList    args,
4322              Cardinal   *num_args )
4323 {
4324 #ifdef Differs
4325 #undef Differs
4326 #endif
4327 
4328 #define Differs( field )  ( curW -> field != newW -> field )
4329 
4330   /* Variables. */
4331   XmUbTimeBoxWidget  curW;
4332   int                index;
4333   Arg                local_args[ 3 ];
4334   Cardinal           n;
4335   char               *name_buffer;
4336   XmUbTimeBoxWidget  newW;
4337   char               *newstr;
4338   Boolean            redisplay = False;
4339   char               *str;
4340   Boolean            visual_changed = False;
4341   Widget             w;
4342   char               *wname;
4343   XmString           xm;
4344 
4345   /* Code. */
4346 
4347   curW = (XmUbTimeBoxWidget) current;
4348   newW = (XmUbTimeBoxWidget) new;
4349 
4350   /* Margins and spacings. */
4351   if( Differs( tbox.field_spacing ) ||
4352       Differs( tbox.menu_spacing )  ||
4353       Differs( tbox.range_spacing ) ||
4354       Differs( tbox.margin_width )  ||
4355       Differs( tbox.margin_height ) )
4356     visual_changed = True;
4357 
4358   /* These changes should be propagated to the child widgets. */
4359   if( Differs( core.background_pixel ) ||
4360       Differs( manager.foreground ) ){
4361 
4362     n = 0;
4363 
4364     if( Differs( core.background_pixel ) ){
4365       XtSetArg( local_args[ n ], XmNbackground,
4366                                  newW -> core.background_pixel ); n++;
4367     }
4368     if( Differs( manager.foreground ) ){
4369       XtSetArg( local_args[ n ], XmNforeground,
4370                                  newW -> manager.foreground ); n++;
4371     }
4372 
4373     /* Set the change for all child widgets. */
4374     for( index = 0; index < NO_INTERNAL_CHILDREN; index ++ )
4375       XtSetValues( newW -> tbox.internal_children[ index ], local_args, n );
4376 
4377     redisplay = True;
4378   }
4379 
4380   /* Changes affecting the time selection dialog. */
4381 
4382   if( Differs( tbox.ok_label ) ){
4383 
4384     if( curW -> tbox.ok_label != NULL )
4385       XmStringFree( curW -> tbox.ok_label );
4386 
4387     /* Copy the XmStrings and set new resources for dialog. */
4388     if( newW -> tbox.ok_label != NULL ){
4389       xm = XmStringCopy( newW -> tbox.ok_label );
4390       newW -> tbox.ok_label = xm;
4391     }
4392 
4393     if( newW -> tbox.time_selection_popup != NULL ){
4394       /* We need the Ok button. */
4395       wname = XtName( (Widget)newW );
4396       name_buffer = XtMalloc( strlen( wname ) + 6 );
4397       sprintf( name_buffer, "%sTok", wname );
4398 
4399       w = XtNameToWidget( newW -> tbox.time_selection_popup, name_buffer );
4400 
4401       if( w != NULL ){
4402         n = 0;
4403         XtSetArg( local_args[ n ], XmNlabelString,
4404                                    newW -> tbox.ok_label ); n++;
4405         XtSetValues( w, local_args, n );
4406       } else
4407         printf( "Error in XtNameToWidget, ok button is NULL.\n" );
4408     }
4409   }
4410 
4411   if( Differs( tbox.cancel_label ) ){
4412 
4413     if( curW -> tbox.cancel_label != NULL )
4414       XmStringFree( curW -> tbox.cancel_label );
4415 
4416     /* Copy the XmStrings and set new resources for dialog. */
4417     if( newW -> tbox.cancel_label != NULL ){
4418       xm = XmStringCopy( newW -> tbox.cancel_label );
4419       newW -> tbox.cancel_label = xm;
4420     }
4421 
4422     if( newW -> tbox.time_selection_popup != NULL ){
4423       /* We need the Ok button. */
4424       wname = XtName( (Widget)newW );
4425       name_buffer = XtMalloc( strlen( wname ) + 6 );
4426       sprintf( name_buffer, "%sTcan", wname );
4427 
4428       w = XtNameToWidget( newW -> tbox.time_selection_popup, name_buffer );
4429 
4430       if( w != NULL ){
4431         n = 0;
4432         XtSetArg( local_args[ n ], XmNlabelString,
4433                                    newW -> tbox.cancel_label ); n++;
4434         XtSetValues( w, local_args, n );
4435       } else
4436         printf( "Error in XtNameToWidget, cancel button is NULL.\n" );
4437     }
4438   }
4439 
4440   /* Changes affecting the time selection dialog shell. */
4441   if( Differs( tbox.time_selection_title ) ){
4442 
4443     if( curW -> tbox.time_selection_title != NULL )
4444       XtFree( curW -> tbox.time_selection_title );
4445 
4446     if( newW -> tbox.time_selection_title != NULL ){
4447       str = XtMalloc( strlen( newW -> tbox.time_selection_title ) + 1 );
4448       strcpy( str, newW -> tbox.time_selection_title );
4449       newW -> tbox.time_selection_title = str;
4450     }
4451 
4452     if( newW -> tbox.time_selection_popup != NULL ){
4453       n = 0;
4454       XtSetArg( local_args[ n ], XmNtitle,
4455                                  newW -> tbox.time_selection_title ); n++;
4456       XtSetValues( XtParent( newW -> tbox.time_selection_popup ),
4457                    local_args, n );
4458     }
4459   }
4460 
4461   /* Changes affecting the date selection dialog shell. */
4462   if( Differs( tbox.date_selection_title ) ){
4463 
4464     if( curW -> tbox.date_selection_title != NULL )
4465       XtFree( curW -> tbox.date_selection_title );
4466 
4467     if( newW -> tbox.date_selection_title != NULL ){
4468       str = XtMalloc( strlen( newW -> tbox.date_selection_title ) + 1 );
4469       strcpy( str, newW -> tbox.date_selection_title );
4470       newW -> tbox.date_selection_title = str;
4471     }
4472 
4473     if( newW -> tbox.date_selection_popup != NULL ){
4474       n = 0;
4475       XtSetArg( local_args[ n ], XmNtitle,
4476                                  newW -> tbox.date_selection_title ); n++;
4477       XtSetValues( XtParent( newW -> tbox.date_selection_popup ),
4478                    local_args, n );
4479     }
4480   }
4481 
4482 
4483   /* Changes affecting the month display dialog. */
4484   if( Differs( tbox.week_label )  ||
4485       Differs( tbox.month_label ) ||
4486       Differs( tbox.year_label ) ){
4487 
4488     n = 0;
4489 
4490     if( Differs( tbox.week_label ) ){
4491 
4492       if( curW -> tbox.week_label != NULL )
4493         XmStringFree( curW -> tbox.week_label );
4494 
4495       if( newW -> tbox.week_label != NULL ){
4496         xm = XmStringCopy( newW -> tbox.week_label );
4497         newW -> tbox.week_label = xm;
4498       }
4499 
4500       XtSetArg( local_args[ n ], XmUbNmdiWeekLabel,
4501                                  newW -> tbox.week_label ); n++;
4502     }
4503 
4504     if( Differs( tbox.month_label ) ){
4505 
4506       if( curW -> tbox.month_label != NULL )
4507         XmStringFree( curW -> tbox.week_label );
4508 
4509       if( newW -> tbox.month_label != NULL ){
4510         xm = XmStringCopy( newW -> tbox.month_label );
4511         newW -> tbox.month_label = xm;
4512       }
4513 
4514       XtSetArg( local_args[ n ], XmUbNmdiMonthLabel,
4515                                  newW -> tbox.month_label ); n++;
4516     }
4517 
4518     if( Differs( tbox.year_label ) ){
4519 
4520       if( curW -> tbox.year_label != NULL )
4521         XmStringFree( curW -> tbox.week_label );
4522 
4523       if( newW -> tbox.year_label != NULL ){
4524         xm = XmStringCopy( newW -> tbox.year_label );
4525         newW -> tbox.year_label = xm;
4526       }
4527 
4528       XtSetArg( local_args[ n ], XmUbNmdiYearLabel,
4529                                  newW -> tbox.year_label ); n++;
4530     }
4531 
4532     if( newW -> tbox.date_selection_popup != NULL )
4533       XtSetValues( newW -> tbox.date_selection_popup, local_args, n );
4534   }
4535 
4536 
4537 
4538   /* These resources may only be set at creation. */
4539   if( Differs( tbox.component_together ) ){
4540     WarningNoResourceChange( newW, "XmUbNtboxComponentTogether" );
4541     newW -> tbox.component_together = curW -> tbox.component_together;
4542   }
4543 
4544   if( Differs( tbox.destroy_dialogs ) ){
4545     WarningNoResourceChange( newW, "XmUbNtboxDestroyDialogs" );
4546     newW -> tbox.destroy_dialogs = curW -> tbox.destroy_dialogs;
4547   }
4548 
4549   if( Differs( tbox.menu_enabled ) ){
4550     WarningNoResourceChange( newW, "XmUbNtboxMenuEnabled" );
4551     newW -> tbox.menu_enabled = curW -> tbox.menu_enabled;
4552   }
4553 
4554   if( Differs( tbox.menu_items ) ){
4555     WarningNoResourceChange( newW, "XmUbNtboxMenuItems" );
4556     newW -> tbox.menu_items = curW -> tbox.menu_items;
4557   }
4558 
4559   if( Differs( tbox.menu_label ) ){
4560     WarningNoResourceChange( newW, "XmUbNtboxMenuLabel" );
4561     newW -> tbox.menu_label = curW -> tbox.menu_label;
4562   }
4563 
4564   if( Differs( tbox.menu_pixmap ) ){
4565     WarningNoResourceChange( newW, "XmUbNtboxMenuPixmap" );
4566     newW -> tbox.menu_pixmap = curW -> tbox.menu_pixmap;
4567   }
4568 
4569   if( Differs( tbox.menu_position ) ){
4570     WarningNoResourceChange( newW, "XmUbNtboxMenuPosition" );
4571     newW -> tbox.menu_position = curW -> tbox.menu_position;
4572   }
4573 
4574   if( Differs( tbox.num_menu_items ) ){
4575     WarningNoResourceChange( newW, "XmUbNtboxNumMenuItems" );
4576     newW -> tbox.num_menu_items = curW -> tbox.num_menu_items;
4577   }
4578 
4579   if( Differs( tbox.orientation ) ){
4580     WarningNoResourceChange( newW, "XmNorientation" );
4581     newW -> tbox.orientation = curW -> tbox.orientation;
4582   }
4583 
4584   if( Differs( tbox.widget_format ) ){
4585     WarningNoResourceChange( newW, "XmUbNtboxFormat" );
4586     newW -> tbox.widget_format = curW -> tbox.widget_format;
4587   }
4588 
4589   /* Copy strings for scanning. */
4590 #define SetMarker( field, default )   \
4591 { \
4592   if( curW -> field != newW -> field ){ \
4593     if( curW -> field != NULL ) \
4594       XtFree( curW -> field ); \
4595     if( newW -> field == NULL ){ \
4596       newstr = XtMalloc( strlen( default ) ); \
4597       strcpy( newstr, default ); \
4598       newW -> field = newstr; \
4599     } else { \
4600       newstr = XtMalloc( strlen( newW -> field ) ); \
4601       strcpy( newstr, newW -> field ); \
4602       newW -> field = newstr; \
4603     } \
4604   } \
4605 }
4606 
4607   SetMarker( tbox.day_marker,    default_day_marker );
4608   SetMarker( tbox.hour_marker,   default_hour_marker );
4609   SetMarker( tbox.minute_marker, default_minute_marker );
4610   SetMarker( tbox.month_marker,  default_month_marker );
4611   SetMarker( tbox.week_marker,   default_week_marker );
4612   SetMarker( tbox.year_marker,   default_year_marker );
4613 
4614 #undef SetMarker
4615 
4616   if( visual_changed ){
4617 
4618     KidDimensionRec  kids_sizes[ NO_INTERNAL_CHILDREN ];
4619     Boolean          resized;
4620 
4621     /* Code. */
4622 
4623     resized = ResizeIfNeeded( newW, kids_sizes );
4624     if( resized )
4625       DoLayout( newW, NULL, NULL, kids_sizes );
4626 
4627   }
4628 
4629   return( redisplay || visual_changed );
4630 
4631 #undef Differs
4632 
4633 } /* SetValues */
4634 
4635 
4636 /*----------------------------------------------------------------------*/
4637 
4638 static void
TimeCompletionCB(Widget tw,XmUbTimeBoxWidget tbox,XmTextVerifyCallbackStruct * call_data)4639   TimeCompletionCB( Widget                      tw,
4640                     XmUbTimeBoxWidget           tbox,
4641                     XmTextVerifyCallbackStruct  *call_data )
4642 {
4643   /* Variables. */
4644   int                child_index;
4645   Boolean            restart;
4646   XmUbTimeBoxStatus  status;
4647 
4648   /* Code. */
4649 
4650 TimeCompletionCB_START:
4651 
4652   /* Find child index for this field. */
4653   child_index = ChildIndex( tbox, tw );
4654 
4655   /* Completion is different depending on which field we are dealing with. */
4656   switch( child_index ){
4657 
4658     case XmUbTB_CHILD_START_TIME:
4659       status = CompleteStartTime( tbox );
4660       break;
4661 
4662 
4663     case XmUbTB_CHILD_END_TIME:
4664       status = CompleteEndTime( tbox );
4665       break;
4666 
4667     default:
4668       /* This should not happen. */
4669       printf( "TimeCompletionCB ERROR, called for wrong child.\n" );
4670       return;
4671 
4672   } /* switch */
4673 
4674   /* If there was an error, take care of it. May lead to restart. */
4675   restart = TimeCompletionCallback( tw, child_index, tbox,
4676 				    (XmAnyCallbackStruct *) call_data,
4677 				    status );
4678   if( restart )
4679     goto TimeCompletionCB_START;
4680 
4681 
4682   return;
4683 
4684 } /* TimeCompletionCB */
4685 
4686 
4687 /*----------------------------------------------------------------------*/
4688 
4689 static Boolean
TimeCompletionCallback(Widget tw,int child_index,XmUbTimeBoxWidget tbox,XmAnyCallbackStruct * call_data,XmUbTimeBoxStatus reason)4690   TimeCompletionCallback( Widget               tw,
4691 			  int                  child_index,
4692 			  XmUbTimeBoxWidget    tbox,
4693 			  XmAnyCallbackStruct  *call_data,
4694 			  XmUbTimeBoxStatus    reason )
4695 {
4696   /* Variables. */
4697   XmUbTimeBoxCallbackStruct  callback_struct;
4698   char                       *str;
4699 
4700   /* Code. */
4701 
4702   /* Initialize. Needed also if no callback. */
4703   callback_struct.child_index        = child_index;
4704   callback_struct.child              = tw;
4705   callback_struct.restart_completion = False;
4706 
4707   if( tbox -> tbox.completion_callback != NULL ){
4708 
4709     /* Common fields. */
4710     if( call_data == NULL )
4711       callback_struct.event = NULL;
4712     else
4713       callback_struct.event = call_data -> event;
4714 
4715     switch( reason ){
4716 
4717       case TBOX_OK:
4718         callback_struct.reason = XmUbCR_COMPLETION_SUCCESS;
4719         break;
4720 
4721       case TBOX_EMPTY:
4722         callback_struct.reason = XmUbCR_COMPLETION_EMPTY;
4723         break;
4724 
4725       case TBOX_NO_COMPLETION:
4726         callback_struct.reason = XmUbCR_COMPLETION_FAILED;
4727         break;
4728 
4729       default:
4730 	break;
4731     }
4732 
4733     XtCallCallbackList( (Widget) tbox,
4734                         tbox -> tbox.completion_callback,
4735                         (XtPointer) &callback_struct );
4736 
4737   } else {
4738 
4739     /* No callback was defined. */
4740 
4741     /* If completion failed, we should indicate this. */
4742     if( reason == TBOX_NO_COMPLETION ){
4743       /* Don't flicker the string if it is already set. */
4744       str = XmTextGetString( tw );
4745 
4746       if( strcmp( str, default_completion_failed_string ) != 0 )
4747         XmTextSetString( tw, default_completion_failed_string );
4748 
4749       XtFree( str );
4750     }
4751   }
4752 
4753 
4754   return( callback_struct.restart_completion );
4755 
4756 } /* TimeCompletionCallback */
4757 
4758 
4759 /*----------------------------------------------------------------------*/
4760 
4761 static void
TimeSelectedInDialogCB(Widget tw,XmUbTimeBoxWidget tbox,XmAnyCallbackStruct * call_data)4762   TimeSelectedInDialogCB( Widget               tw,
4763                           XmUbTimeBoxWidget    tbox,
4764                           XmAnyCallbackStruct  *call_data )
4765 {
4766   /* Variables. */
4767   XmUbTimeBoxCallbackStruct  cb;
4768   Boolean                    known_field = True;
4769   Widget                     slider;
4770   char                       *str;
4771 
4772   /* Code. */
4773 
4774   /* Get the id of the slider widget. */
4775   slider = TimeSliderId( tbox );
4776 
4777   if( slider == NULL )
4778     printf( "Error in XtNameToWidget call, slider is NULL.\n" );
4779 
4780   /* Get the selected time. */
4781   str = XmUbTimeSliderGetTimeString( (Widget) slider );
4782 
4783   /* Set the time in the box. */
4784   switch( tbox -> tbox.field_for_time_selection ){
4785     case XmUbTB_CHILD_START_TIME:
4786      XmUbTimeBoxSetStartTimeString( (Widget) tbox, str );
4787      break;
4788 
4789     case XmUbTB_CHILD_END_TIME:
4790       XmUbTimeBoxSetEndTimeString( (Widget) tbox, str );
4791       break;
4792 
4793     default:
4794       /* Not a recognized field. */
4795       known_field = False;
4796       break;
4797   }
4798 
4799   /* Get rid of the dialog. */
4800   PopdownTimeSelectionDialogCB( tw, tbox, (XmAnyCallbackStruct *) call_data );
4801 
4802 
4803   /* Cleanup. */
4804   XtFree( str );
4805 
4806   /* Call activate callback. */
4807   if( known_field && ( tbox -> tbox.activate_callback != NULL ) ){
4808 
4809     /* Set up callback structure. */
4810 
4811     cb.reason      = XmUbCR_TIME_PICKED;
4812     cb.event       = NULL;
4813     cb.child_index = tbox -> tbox.field_for_time_selection;
4814     cb.child       = tbox -> tbox.internal_children[ cb.child_index ];
4815 
4816     XtCallCallbackList( (Widget) tbox, tbox -> tbox.activate_callback,
4817                         (XtPointer) &cb );
4818   }
4819 
4820 
4821   return;
4822 
4823 } /* TimeSelectedInDialogCB */
4824 
4825 
4826 /*----------------------------------------------------------------------*/
4827 
4828 Widget
TimeSliderId(XmUbTimeBoxWidget tbox)4829   TimeSliderId( XmUbTimeBoxWidget  tbox )
4830 {
4831   /* Variables. */
4832   char    *name_buffer;
4833   Widget  slider;
4834   String  wname;
4835 
4836   /* Code. */
4837 
4838   wname = XtName( (Widget)tbox );
4839 
4840   /* Get the id of the slider widget. */
4841   name_buffer = XtMalloc( strlen( wname ) * 2 + 8 );
4842   sprintf( name_buffer, "%sTs", wname );
4843 
4844   slider = XtNameToWidget( tbox -> tbox.time_selection_popup, name_buffer );
4845 
4846   XtFree( name_buffer );
4847 
4848 
4849   return( slider );
4850 
4851 } /* TimeSliderId */
4852 
4853 
4854 /*----------------------------------------------------------------------*/
4855 
4856 #if XmVersion > 1001
4857 
4858 static void
TransferDateField(Widget w,XtPointer closure,Atom * seltype,Atom * type,XtPointer value,unsigned long * length,int format)4859   TransferDateField( Widget         w,
4860                      XtPointer      closure,
4861                      Atom           *seltype,
4862                      Atom           *type,
4863                      XtPointer      value,
4864                      unsigned long  *length,
4865                      int            format )
4866 {
4867   /* Variables. */
4868   char                       buffer[ TIME_STRING_BUFFER_LEN ];
4869   XmUbTimeBoxCallbackStruct  cb;
4870   Atom                       compound_text_atom;
4871   Atom                       date_transfer_atom;
4872   Boolean                    ok;
4873   XmTextPosition             pos;
4874   Boolean                    range_transfer = False;
4875   char                       *str;
4876   XmUbTimeBoxWidget          tbox;
4877   TIM_TIME_REF               time;
4878   XmUbDateTransferRef        transfer_data;
4879   Widget                     tw;
4880   XmString                   xm;
4881 
4882   /* Code. */
4883 
4884   compound_text_atom = XmInternAtom( XtDisplay( w ), "COMPOUND_TEXT", False );
4885   date_transfer_atom = XmInternAtom( XtDisplay( w ), XmUbDATE_TRANSFER,
4886                                      False );
4887 
4888   /* The text widget is passed in the parameter closure. */
4889   tw   = (Widget) closure;
4890   tbox = (XmUbTimeBoxWidget) XtParent( tw );
4891 
4892   if( *type == date_transfer_atom ){
4893     /* We are being passed a structure with date information.
4894        Construct a string with the date in the local format. */
4895 
4896     /* Convert the first date, regardless of the type. */
4897     transfer_data = (XmUbDateTransferRef) value;
4898 
4899     time = TimMakeTime( transfer_data -> year, transfer_data -> month,
4900                         transfer_data -> day, 0, 0, 0 );
4901     ConvertToDateString( tbox, time, buffer, TIME_STRING_BUFFER_LEN - 1 );
4902 
4903     if( transfer_data -> type == XmUbTRANSFER_DATE ){
4904 
4905       /* Replace the text with the new date. */
4906       XmTextSetString( tw, buffer );
4907 
4908     } else {
4909 
4910       /* This is a range transfer. Set the start date. */
4911       (void) XmUbTimeBoxSetStartDateString( (Widget) tbox, buffer );
4912 
4913       /* Convert end of range. */
4914       if( ( tbox -> tbox.widget_format == XmUbTB_FORMAT_DD ) ||
4915           ( tbox -> tbox.widget_format == XmUbTB_FORMAT_DTDT ) ){
4916 
4917         time = TimMakeTime( transfer_data -> end_year,
4918                             transfer_data -> end_month,
4919                             transfer_data -> end_day, 0, 0, 0 );
4920         ConvertToDateString( tbox, time, buffer, TIME_STRING_BUFFER_LEN - 1 );
4921 
4922         (void) XmUbTimeBoxSetEndDateString( (Widget) tbox, buffer );
4923 
4924         range_transfer = True;
4925 
4926       }
4927     }
4928 
4929 
4930     /* Call the activate callback. */
4931     if( tbox -> tbox.activate_callback != NULL ){
4932 
4933       cb.reason      = XmUbCR_DATE_DROPPED;
4934       cb.event       = NULL;
4935       cb.child_index = ChildIndex( tbox, tw );
4936       cb.child       = tw;
4937       cb.range       = range_transfer;
4938 
4939       XtCallCallbackList( (Widget) tbox, tbox -> tbox.activate_callback,
4940                           (XtPointer) &cb );
4941     }
4942 
4943 
4944   } else if( *type == compound_text_atom ){
4945     /* We are getting compound text. Need to convert it to normal string. */
4946     xm = XmCvtCTToXmString( value );
4947     ok = XmStringGetLtoR( xm, XmSTRING_DEFAULT_CHARSET, &str );
4948 
4949     /* Insert the string at the current position. */
4950     if( ok ){
4951 
4952       pos = XmTextGetInsertionPosition( tw );
4953       XmTextInsert( tw, pos, str );
4954 
4955       XtFree( str );
4956     }
4957 
4958     XmStringFree( xm );
4959   }
4960 
4961 
4962   return;
4963 
4964 } /* TransferDateField */
4965 
4966 #endif
4967 
4968 /*----------------------------------------------------------------------*/
4969 
4970 static void
ValueChangedCB(Widget tw,XmUbTimeBoxWidget tbox,XmAnyCallbackStruct * call_data)4971   ValueChangedCB( Widget               tw,
4972                   XmUbTimeBoxWidget    tbox,
4973                   XmAnyCallbackStruct  *call_data )
4974 {
4975   /* Variables. */
4976   XmUbTimeBoxCallbackStruct  cb;
4977 
4978   /* Code. */
4979 
4980   if( tbox -> tbox.value_changed_callback == NULL )
4981     return;
4982 
4983   /* Set up callback structure. */
4984 
4985   cb.reason      = XmCR_VALUE_CHANGED;
4986   cb.event       = call_data -> event;
4987   cb.child_index = ChildIndex( tbox, tw );
4988   cb.child       = tw;
4989 
4990   XtCallCallbackList( (Widget) tbox,
4991                       tbox -> tbox.value_changed_callback,
4992                       (XtPointer) &cb );
4993 
4994 
4995   return;
4996 
4997 } /* ValueChangedCB */
4998 
4999 
5000 /*----------------------------------------------------------------------*/
5001 
5002 static void
WarningNoResourceChange(XmUbTimeBoxWidget tbox,String resource)5003   WarningNoResourceChange( XmUbTimeBoxWidget  tbox,
5004                            String             resource )
5005 {
5006   /* Variables. */
5007   Cardinal  num_params;
5008   String    params[ 2 ];
5009 
5010   /* Code. */
5011 
5012   params[ 0 ] = resource;
5013   params[ 1 ] = XtClass( tbox ) -> core_class.class_name;
5014   num_params  = 2;
5015   XtAppWarningMsg( XtWidgetToApplicationContext( (Widget) tbox ),
5016 		   "resourceError", "setValues", "WidgetError",
5017 		   "Resource %s may not be changed in %s widgets.",
5018 		   params, &num_params );
5019 
5020   return;
5021 
5022 } /* WarningNoResourceChange */
5023 
5024 
5025 /*----------------------------------------------------------------------*/
5026 
5027 Widget
XmUbCreateTimeBox(Widget parent,String name,ArgList arglist,Cardinal argcount)5028   XmUbCreateTimeBox( Widget    parent,
5029                      String    name,
5030                      ArgList   arglist,
5031                      Cardinal  argcount )
5032 {
5033 
5034   /* Code. */
5035 
5036   return XtCreateWidget( name, xmUbTimeBoxWidgetClass,
5037                          parent, arglist, argcount );
5038 
5039 } /* XmUbCreateTimeBox */
5040 
5041 
5042 /*----------------------------------------------------------------------*/
5043 
5044 Widget
XmUbTimeBoxGetChild(Widget widget,int child)5045   XmUbTimeBoxGetChild( Widget  widget,
5046                        int     child )
5047 {
5048 
5049   /* Variables. */
5050   XmUbTimeBoxWidget  tbox;
5051 
5052   /* Code. */
5053 
5054   tbox = (XmUbTimeBoxWidget) widget;
5055 
5056 
5057   return( tbox -> tbox.internal_children[ child ] );
5058 
5059 
5060 } /* XmUbTimeBoxGetChild */
5061 
5062 
5063 /*----------------------------------------------------------------------*/
5064 
5065 XmUbTimeBoxStatus
XmUbTimeBoxGetEndDateString(Widget widget,char ** str)5066   XmUbTimeBoxGetEndDateString( Widget  widget,
5067                                char    **str )
5068 {
5069   /* Variables. */
5070   XmUbTimeBoxStatus  status;
5071 
5072   /* Code. */
5073 
5074   status = GetChildString( (XmUbTimeBoxWidget) widget,
5075                            XmUbTB_CHILD_END_DATE, str );
5076 
5077 
5078   return( status );
5079 
5080 } /* XmUbTimeBoxGetEndDateString */
5081 
5082 
5083 /*----------------------------------------------------------------------*/
5084 
5085 XmUbTimeBoxStatus
XmUbTimeBoxGetEndTimeString(Widget widget,char ** str)5086   XmUbTimeBoxGetEndTimeString( Widget  widget,
5087                                char    **str )
5088 {
5089   /* Variables. */
5090   XmUbTimeBoxStatus  status;
5091 
5092   /* Code. */
5093 
5094   status = GetChildString( (XmUbTimeBoxWidget) widget,
5095                            XmUbTB_CHILD_END_TIME, str );
5096 
5097 
5098   return( status );
5099 
5100 } /* XmUbTimeBoxGetEndTimeString */
5101 
5102 
5103 /*----------------------------------------------------------------------*/
5104 
5105 XmUbTimeBoxStatus
XmUbTimeBoxGetStartDateString(Widget widget,char ** str)5106   XmUbTimeBoxGetStartDateString( Widget  widget,
5107                                  char    **str )
5108 {
5109   /* Variables. */
5110   XmUbTimeBoxStatus  status;
5111 
5112   /* Code. */
5113 
5114   status = GetChildString( (XmUbTimeBoxWidget) widget,
5115                            XmUbTB_CHILD_START_DATE, str );
5116 
5117 
5118   return( status );
5119 
5120 } /* XmUbTimeBoxGetStartDateString */
5121 
5122 
5123 /*----------------------------------------------------------------------*/
5124 
5125 XmUbTimeBoxStatus
XmUbTimeBoxGetStartTimeString(Widget widget,char ** str)5126   XmUbTimeBoxGetStartTimeString( Widget  widget,
5127                                  char    **str )
5128 {
5129   /* Variables. */
5130   XmUbTimeBoxStatus  status;
5131 
5132   /* Code. */
5133 
5134   status = GetChildString( (XmUbTimeBoxWidget) widget,
5135                            XmUbTB_CHILD_START_TIME, str );
5136 
5137 
5138   return( status );
5139 
5140 } /* XmUbTimeBoxGetStartTimeString */
5141 
5142 
5143 /*----------------------------------------------------------------------*/
5144 
5145 XmUbTimeBoxStatus
XmUbTimeBoxGetEndDate(Widget widget,time_t * date)5146   XmUbTimeBoxGetEndDate( Widget   widget,
5147                          time_t   *date )
5148 {
5149   /* Variables. */
5150   char               *datestr;
5151   XmUbTimeBoxStatus  status;
5152   TIM_STATUS_TYPE    tim_status;
5153   TIM_TIME_REF       tmp_date;
5154 
5155   /* Code. */
5156 
5157   status = XmUbTimeBoxGetEndDateString( widget, &datestr );
5158 
5159   if( status != TBOX_OK )
5160     return( status );
5161 
5162   /* Try to convert to date. */
5163   tim_status = TimMakeDateFromString( &tmp_date, datestr );
5164 
5165   if( tim_status == TIM_OK )
5166     *date = tmp_date;
5167   else
5168     status = TBOX_CONV_ERROR;
5169 
5170   /* Cleanup. */
5171   XtFree( datestr );
5172 
5173 
5174   return( status );
5175 
5176 } /* XmUbTimeBoxGetEndDate */
5177 
5178 
5179 /*----------------------------------------------------------------------*/
5180 
5181 XmUbTimeBoxStatus
XmUbTimeBoxGetStartDate(Widget widget,time_t * date)5182   XmUbTimeBoxGetStartDate( Widget   widget,
5183                            time_t   *date )
5184 {
5185   /* Variables. */
5186   char               *datestr;
5187   XmUbTimeBoxStatus  status;
5188   TIM_STATUS_TYPE    tim_status;
5189   TIM_TIME_REF       tmp_date;
5190 
5191   /* Code. */
5192 
5193   status = XmUbTimeBoxGetStartDateString( widget, &datestr );
5194 
5195   if( status != TBOX_OK )
5196     return( status );
5197 
5198   /* Try to convert to date. */
5199   tim_status = TimMakeDateFromString( &tmp_date, datestr );
5200 
5201   if( tim_status == TIM_OK )
5202     *date = tmp_date;
5203   else
5204     status = TBOX_CONV_ERROR;
5205 
5206   /* Cleanup. */
5207   XtFree( datestr );
5208 
5209 
5210   return( status );
5211 
5212 } /* XmUbTimeBoxGetStartDate */
5213 
5214 
5215 /*----------------------------------------------------------------------*/
5216 
5217 XmUbTimeBoxStatus
XmUbTimeBoxGetEndTime(Widget widget,time_t * time)5218   XmUbTimeBoxGetEndTime( Widget   widget,
5219                          time_t   *time )
5220 {
5221   /* Variables. */
5222   char               *timestr;
5223   XmUbTimeBoxStatus  status;
5224   TIM_STATUS_TYPE    tim_status;
5225   TIM_TIME_REF       tmp_time;
5226 
5227   /* Code. */
5228 
5229   status = XmUbTimeBoxGetEndTimeString( widget, &timestr );
5230 
5231   if( status != TBOX_OK )
5232     return( status );
5233 
5234   /* Try to convert to date. */
5235   tim_status = TimMakeTimeFromString( &tmp_time, timestr );
5236 
5237   if( tim_status == TIM_OK )
5238     *time = tmp_time;
5239   else
5240     status = TBOX_CONV_ERROR;
5241 
5242   /* Cleanup. */
5243   XtFree( timestr );
5244 
5245 
5246   return( status );
5247 
5248 } /* XmUbTimeBoxGetEndTime */
5249 
5250 
5251 /*----------------------------------------------------------------------*/
5252 
5253 XmUbTimeBoxStatus
XmUbTimeBoxGetStartTime(Widget widget,time_t * time)5254   XmUbTimeBoxGetStartTime( Widget   widget,
5255                            time_t   *time )
5256 {
5257   /* Variables. */
5258   char               *timestr;
5259   XmUbTimeBoxStatus  status;
5260   TIM_STATUS_TYPE    tim_status;
5261   TIM_TIME_REF       tmp_time;
5262 
5263   /* Code. */
5264 
5265   status = XmUbTimeBoxGetStartTimeString( widget, &timestr );
5266 
5267   if( status != TBOX_OK )
5268     return( status );
5269 
5270   /* Try to convert to date. */
5271   tim_status = TimMakeTimeFromString( &tmp_time, timestr );
5272 
5273   if( tim_status == TIM_OK )
5274     *time = tmp_time;
5275   else
5276     status = TBOX_CONV_ERROR;
5277 
5278   /* Cleanup. */
5279   XtFree( timestr );
5280 
5281 
5282   return( status );
5283 
5284 } /* XmUbTimeBoxGetStartTime */
5285 
5286 
5287 /*----------------------------------------------------------------------*/
5288 
5289 XmUbTimeBoxStatus
XmUbTimeBoxSetEndDate(Widget widget,time_t date)5290   XmUbTimeBoxSetEndDate( Widget  widget,
5291                          time_t  date )
5292 {
5293   /* Variables. */
5294   char               buffer[ TIME_STRING_BUFFER_LEN ];
5295   XmUbTimeBoxWidget  tbox;
5296 
5297   /* Code. */
5298 
5299   tbox = (XmUbTimeBoxWidget) widget;
5300 
5301   /* Convert the date to a string. */
5302   ConvertToDateString( tbox, date, buffer, TIME_STRING_BUFFER_LEN - 1 );
5303 
5304   /* Set the string. */
5305   return( SetChildString( tbox, XmUbTB_CHILD_END_DATE, buffer ) );
5306 
5307 } /* XmUbTimeBoxSetEndDate */
5308 
5309 
5310 /*----------------------------------------------------------------------*/
5311 
5312 XmUbTimeBoxStatus
XmUbTimeBoxSetEndTime(Widget widget,time_t time)5313   XmUbTimeBoxSetEndTime( Widget  widget,
5314                          time_t  time )
5315 {
5316   /* Variables. */
5317   char               buffer[ TIME_STRING_BUFFER_LEN ];
5318   XmUbTimeBoxWidget  tbox;
5319 
5320   /* Code. */
5321 
5322   tbox = (XmUbTimeBoxWidget) widget;
5323 
5324   /* Convert the date to a string. */
5325   ConvertToTimeString( tbox, time, buffer, TIME_STRING_BUFFER_LEN - 1 );
5326 
5327   /* Set the string. */
5328   return( SetChildString( tbox, XmUbTB_CHILD_END_TIME, buffer ) );
5329 
5330 } /* XmUbTimeBoxSetEndTime */
5331 
5332 
5333 /*----------------------------------------------------------------------*/
5334 
5335 XmUbTimeBoxStatus
XmUbTimeBoxSetStartDate(Widget widget,time_t date)5336   XmUbTimeBoxSetStartDate( Widget  widget,
5337                            time_t  date )
5338 {
5339   /* Variables. */
5340   char               buffer[ TIME_STRING_BUFFER_LEN ];
5341   XmUbTimeBoxWidget  tbox;
5342 
5343   /* Code. */
5344 
5345   tbox = (XmUbTimeBoxWidget) widget;
5346 
5347   /* Convert the date to a string. */
5348   ConvertToDateString( tbox, date, buffer, TIME_STRING_BUFFER_LEN - 1 );
5349 
5350   /* Set the string. */
5351   return( SetChildString( tbox, XmUbTB_CHILD_START_DATE, buffer ) );
5352 
5353 } /* XmUbTimeBoxSetStartDate */
5354 
5355 
5356 /*----------------------------------------------------------------------*/
5357 
5358 XmUbTimeBoxStatus
XmUbTimeBoxSetStartTime(Widget widget,time_t time)5359   XmUbTimeBoxSetStartTime( Widget  widget,
5360                            time_t  time )
5361 {
5362   /* Variables. */
5363   char               buffer[ TIME_STRING_BUFFER_LEN ];
5364   XmUbTimeBoxWidget  tbox;
5365 
5366   /* Code. */
5367 
5368   tbox = (XmUbTimeBoxWidget) widget;
5369 
5370   /* Convert the date to a string. */
5371   ConvertToTimeString( tbox, time, buffer, TIME_STRING_BUFFER_LEN - 1 );
5372 
5373   /* Set the string. */
5374   return( SetChildString( tbox, XmUbTB_CHILD_START_TIME, buffer ) );
5375 
5376 } /* XmUbTimeBoxSetStartTime */
5377 
5378 
5379 /*----------------------------------------------------------------------*/
5380 
5381 XmUbTimeBoxStatus
XmUbTimeBoxSetEndDateString(Widget widget,char * str)5382   XmUbTimeBoxSetEndDateString( Widget  widget,
5383                                char    *str )
5384 {
5385   /* Code. */
5386 
5387   return( SetChildString( (XmUbTimeBoxWidget) widget,
5388                           XmUbTB_CHILD_END_DATE, str ) );
5389 
5390 } /* XmUbTimeBoxSetEndDateString */
5391 
5392 
5393 /*----------------------------------------------------------------------*/
5394 
5395 XmUbTimeBoxStatus
XmUbTimeBoxSetEndTimeString(Widget widget,char * str)5396   XmUbTimeBoxSetEndTimeString( Widget  widget,
5397                                char    *str )
5398 {
5399   /* Code. */
5400 
5401   return( SetChildString( (XmUbTimeBoxWidget) widget,
5402                           XmUbTB_CHILD_END_TIME, str ) );
5403 
5404 } /* XmUbTimeBoxSetEndTimeString */
5405 
5406 
5407 /*----------------------------------------------------------------------*/
5408 
5409 XmUbTimeBoxStatus
XmUbTimeBoxSetStartDateString(Widget widget,char * str)5410   XmUbTimeBoxSetStartDateString( Widget  widget,
5411                                  char    *str )
5412 {
5413   /* Code. */
5414 
5415   return( SetChildString( (XmUbTimeBoxWidget) widget,
5416                           XmUbTB_CHILD_START_DATE, str ) );
5417 
5418 } /* XmUbTimeBoxSetStartDateString */
5419 
5420 
5421 /*----------------------------------------------------------------------*/
5422 
5423 XmUbTimeBoxStatus
XmUbTimeBoxSetStartTimeString(Widget widget,char * str)5424   XmUbTimeBoxSetStartTimeString( Widget  widget,
5425                                  char    *str )
5426 {
5427   /* Code. */
5428 
5429   return( SetChildString( (XmUbTimeBoxWidget) widget,
5430                           XmUbTB_CHILD_START_TIME, str ) );
5431 
5432 } /* XmUbTimeBoxSetStartTimeString */
5433 
5434 
5435 /*----------------------------------------------------------------------*/
5436 
5437 void
XmUbTimeBoxPopupDateDialog(Widget widget,int child_index)5438   XmUbTimeBoxPopupDateDialog( Widget  widget,
5439                               int     child_index )
5440 {
5441   /* Variables. */
5442   Widget  child;
5443 
5444   /* Code. */
5445 
5446   child = XmUbTimeBoxGetChild( widget, child_index );
5447 
5448   if( child != NULL )
5449     PopupDateSelection( child );
5450 
5451 
5452   return;
5453 
5454 } /* XmUbTimeBoxPopupDateDialog */
5455 
5456 
5457 /*----------------------------------------------------------------------*/
5458 
5459 void
XmUbTimeBoxPopupTimeDialog(Widget widget,int child_index)5460   XmUbTimeBoxPopupTimeDialog( Widget  widget,
5461                               int     child_index )
5462 {
5463   /* Variables. */
5464   Widget  child;
5465 
5466   /* Code. */
5467 
5468   child = XmUbTimeBoxGetChild( widget, child_index );
5469 
5470   if( child != NULL )
5471     PopupTimeSelection( child );
5472 
5473 
5474   return;
5475 
5476 } /* XmUbTimeBoxPopupTimeDialog */
5477