1 /*----------------------------------------------------------------------------
2 --
3 --  Module:           XmUbMonthDisplay
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:         XmUbMonthD.c
14 --
15 --  Authors:          Roger Larsson, Ulrika Bornetun
16 --  Creation date:    1993-09-26
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: XmUbMonthD.c, Version: 1.2, Date: 95/06/21 20:47:47";
32 
33 
34 /*----------------------------------------------------------------------------
35 --  Include files
36 ----------------------------------------------------------------------------*/
37 
38 #include <stdio.h>
39 #include <string.h>
40 #include <assert.h>
41 #include <X11/Intrinsic.h>
42 #include <X11/StringDefs.h>
43 #include <X11/Xatom.h>
44 #include <Xm/XmP.h>
45 
46 #if XmVersion > 1001
47 #include <Xm/AtomMgr.h>
48 #include <Xm/DragDrop.h>
49 #endif
50 
51 #include <Xm/Label.h>
52 #include <Xm/PushB.h>
53 #include <Xm/RowColumn.h>
54 #include <Xm/Separator.h>
55 
56 /* Rogge's tools. */
57 #include "TimDate.h"
58 
59 /* Private widget header file. */
60 #include "XmUbMonthDP.h"
61 
62 /* Other widgets. */
63 #include "XmUbArrLab.h"
64 
65 /* Drag and drop. */
66 #if XmVersion > 1001
67 #include "XmUbDragDrop.h"
68 #include "DateDragIcon.h"
69 #include "DateDragMask.h"
70 #include "DateDragInvIcon.h"
71 #include "DateDragInvIconMask.h"
72 #endif
73 
74 /*----------------------------------------------------------------------------
75 --  Macro definitions
76 ----------------------------------------------------------------------------*/
77 
78 #ifdef MAX
79 #undef MAX
80 #endif
81 
82 #ifdef MIN
83 #undef MIN
84 #endif
85 
86 #define MAX( x, y )  ( ( x ) > ( y ) ? ( x ) : ( y ) )
87 #define MIN( x, y )  ( ( x ) < ( y ) ? ( x ) : ( y ) )
88 
89 #define XmUbMD_CHILD_ERROR  -1
90 
91 #define LABEL_BUFFER_LENGTH  30
92 #define TEXT_BUFFER_LENGTH   20
93 
94 #define PREVIOUS_MONTH_OFFSET  100
95 #define NEXT_MONTH_OFFSET      200
96 
97 #define TITLE_ID_USER_DATA     1
98 
99 /*----------------------------------------------------------------------------
100 --  Type declarations
101 ----------------------------------------------------------------------------*/
102 
103 typedef struct {
104 
105   Dimension  width;
106   Dimension  height;
107   Position   x;
108   Position   y;
109 
110 } KidDimensionRec;
111 
112 /*----------------------------------------------------------------------------
113 --  Global definitions
114 ----------------------------------------------------------------------------*/
115 
116 /* Internal Motif functions (how do we know about this....?) */
117 extern void
118   _XmBackgroundColorDefault();
119 extern void
120   _XmForegroundColorDefault();
121 
122 static char  default_month_string[] = "Month";
123 static char  default_year_string[]  = "Year";
124 
125 /* The month display resource list. */
126 static XtResource resources[] = {
127   {
128     XmUbNmdiDateSelectedCallback,
129     XmCCallback,
130     XmRCallback, sizeof( XtCallbackList ),
131     XtOffset( XmUbMonthDisplayWidget, md.date_selected_callback ),
132     XmRCallback,
133     NULL
134   },
135   {
136     XmUbNmdiNewMonthCallback,
137     XmCCallback,
138     XmRCallback, sizeof( XtCallbackList ),
139     XtOffset( XmUbMonthDisplayWidget, md.new_month_callback ),
140     XmRCallback,
141     NULL
142   },
143   {
144     XmUbNmdiTitleCallback,
145     XmCCallback,
146     XmRCallback, sizeof( XtCallbackList ),
147     XtOffset( XmUbMonthDisplayWidget, md.title_callback ),
148     XmRImmediate,
149     (XtPointer) NULL
150   },
151   {
152     XmNmarginHeight,
153     XmCMarginHeight,
154     XtRDimension, sizeof( Dimension ),
155     XtOffset( XmUbMonthDisplayWidget, md.margin_height ),
156     XtRImmediate,
157     (XtPointer) 0
158   },
159   {
160     XmNmarginWidth,
161     XmCMarginWidth,
162     XtRDimension, sizeof( Dimension ),
163     XtOffset( XmUbMonthDisplayWidget, md.margin_width ),
164     XtRImmediate,
165     (XtPointer) 0
166   },
167   {
168     XmUbNmdiOtherMonthForeground,
169     XmCForeground,
170     XtRPixel, sizeof( Pixel ),
171     XtOffset( XmUbMonthDisplayWidget, md.other_month_foreground ),
172     XmRCallProc,
173     (XtPointer) _XmForegroundColorDefault
174   },
175   {
176     XmUbNmdiArrowSpacing,
177     XmCSpacing,
178     XtRDimension, sizeof( Dimension ),
179     XtOffset( XmUbMonthDisplayWidget, md.arrow_spacing ),
180     XtRImmediate,
181     (XtPointer) 2
182   },
183   {
184     XmUbNmdiCurrentMonth,
185     XmUbCMdiCurrentMonth,
186     XtRInt, sizeof( int ),
187     XtOffset( XmUbMonthDisplayWidget, md.current_month ),
188     XtRImmediate,
189     (XtPointer) 0
190   },
191   {
192     XmUbNmdiCurrentYear,
193     XmUbCMdiCurrentYear,
194     XtRInt, sizeof( int ),
195     XtOffset( XmUbMonthDisplayWidget, md.current_year ),
196     XtRImmediate,
197     (XtPointer) 0
198   },
199   {
200     XmUbNmdiDayChars,
201     XmUbCMdiDayChars,
202     XtRInt, sizeof( int ),
203     XtOffset( XmUbMonthDisplayWidget, md.day_name_characters ),
204     XtRImmediate,
205     (XtPointer) 2
206   },
207   {
208     XmUbNmdiEnableSeparator,
209     XmUbCMdiEnableSeparator,
210     XtRBoolean, sizeof( Boolean ),
211     XtOffset( XmUbMonthDisplayWidget, md.enable_separator ),
212     XtRImmediate,
213     (XtPointer) True
214   },
215   {
216     XmUbNmdiFillOutWeek,
217     XmUbCMdiFillOutWeek,
218     XtRBoolean, sizeof( Boolean ),
219     XtOffset( XmUbMonthDisplayWidget, md.fill_out_week ),
220     XtRImmediate,
221     (XtPointer) True
222   },
223   {
224     XmUbNmdiLabelSpacing,
225     XmCSpacing,
226     XtRDimension, sizeof( Dimension ),
227     XtOffset( XmUbMonthDisplayWidget, md.label_spacing ),
228     XtRImmediate,
229     (XtPointer) 2
230   },
231   {
232     XmUbNmdiMonthLabel,
233     XmUbCMdiMonthLabel,
234     XmRXmString, sizeof( XmString ),
235     XtOffset( XmUbMonthDisplayWidget, md.month_label ),
236     XtRImmediate,
237     (XtPointer) NULL
238   },
239   {
240     XmUbNmdiMonthArrows,
241     XmUbCMdiMonthArrows,
242     XtRBoolean, sizeof( Boolean ),
243     XtOffset( XmUbMonthDisplayWidget, md.month_arrows ),
244     XtRImmediate,
245     (XtPointer) True
246   },
247   {
248     XmUbNmdiRecomputeHeight,
249     XmUbCMdiRecomputeHeight,
250     XtRBoolean, sizeof( Boolean ),
251     XtOffset( XmUbMonthDisplayWidget, md.recompute_height ),
252     XtRImmediate,
253     (XtPointer) True
254   },
255   {
256     XmUbNmdiRecomputeWidth,
257     XmUbCMdiRecomputeWidth,
258     XtRBoolean, sizeof( Boolean ),
259     XtOffset( XmUbMonthDisplayWidget, md.recompute_width ),
260     XtRImmediate,
261     (XtPointer) True
262   },
263   {
264     XmUbNmdiSaturdayForeground,
265     XmCForeground,
266     XtRPixel, sizeof( Pixel ),
267     XtOffset( XmUbMonthDisplayWidget, md.sat_foreground ),
268     XmRCallProc,
269     (XtPointer) _XmForegroundColorDefault
270   },
271   {
272     XmUbNmdiSundayForeground,
273     XmCForeground,
274     XtRPixel, sizeof( Pixel ),
275     XtOffset( XmUbMonthDisplayWidget, md.sun_foreground ),
276     XmRCallProc,
277     (XtPointer) _XmForegroundColorDefault
278   },
279   {
280     XmUbNmdiTitleAlignment,
281     XmCAlignment,
282     XmRAlignment, sizeof( unsigned char ),
283     XtOffset( XmUbMonthDisplayWidget, md.title_alignment ),
284     XtRImmediate,
285     (XtPointer) XmALIGNMENT_CENTER
286   },
287   {
288     XmUbNmdiTitleShadows,
289     XmUbCMdiTitleShadows,
290     XtRBoolean, sizeof( Boolean ),
291     XtOffset( XmUbMonthDisplayWidget, md.title_shadows ),
292     XtRImmediate,
293     (XtPointer) True
294   },
295   {
296     XmUbNmdiTodayForeground,
297     XmCForeground,
298     XtRPixel, sizeof( Pixel ),
299     XtOffset( XmUbMonthDisplayWidget, md.today_foreground ),
300     XmRCallProc,
301     (XtPointer) _XmForegroundColorDefault
302   },
303   {
304     XmUbNmdiUpdateDayCallback,
305     XmCCallback,
306     XmRCallback, sizeof( XtCallbackList ),
307     XtOffset( XmUbMonthDisplayWidget, md.update_day_callback ),
308     XmRImmediate,
309     (XtPointer) NULL
310   },
311   {
312     XmUbNmdiUseDefaultTitleCallback,
313     XmUbCMdiUseDefaultTitleCallback,
314     XtRBoolean, sizeof( Boolean ),
315     XtOffset( XmUbMonthDisplayWidget, md.use_default_title_callback ),
316     XtRImmediate,
317     (XtPointer) True
318   },
319   {
320     XmUbNmdiWeekLabel,
321     XmUbCMdiWeekLabel,
322     XmRXmString, sizeof( XmString ),
323     XtOffset( XmUbMonthDisplayWidget, md.week_number_label ),
324     XtRImmediate,
325     (XtPointer) NULL
326   },
327   {
328     XmUbNmdiWeekNumberForeground,
329     XmCForeground,
330     XtRPixel, sizeof( Pixel ),
331     XtOffset( XmUbMonthDisplayWidget, md.week_number_foreground ),
332     XmRCallProc,
333     (XtPointer) _XmForegroundColorDefault
334   },
335   {
336     XmUbNmdiWeekNumbers,
337     XmUbCMdiWeekNumbers,
338     XtRBoolean, sizeof( Boolean ),
339     XtOffset( XmUbMonthDisplayWidget, md.week_numbers ),
340     XtRImmediate,
341     (XtPointer) True
342   },
343   {
344     XmUbNmdiWeekdayForeground,
345     XmCForeground,
346     XtRPixel, sizeof( Pixel ),
347     XtOffset( XmUbMonthDisplayWidget, md.weekday_foreground ),
348     XmRCallProc,
349     (XtPointer) _XmForegroundColorDefault
350   },
351   {
352     XmUbNmdiYearArrows,
353     XmUbCMdiYearArrows,
354     XtRBoolean, sizeof( Boolean ),
355     XtOffset( XmUbMonthDisplayWidget, md.year_arrows ),
356     XtRImmediate,
357     (XtPointer) True
358   },
359   {
360     XmUbNmdiYearLabel,
361     XmUbCMdiYearLabel,
362     XmRXmString, sizeof( XmString ),
363     XtOffset( XmUbMonthDisplayWidget, md.year_label ),
364     XtRImmediate,
365     (XtPointer) NULL
366   },
367 
368 };  /* resources */
369 
370 
371 /*----------------------------------------------------------------------------
372 --  Function prototypes
373 ----------------------------------------------------------------------------*/
374 
375 /* Class methods. */
376 static void
377   ChangeManaged( Widget  widget );
378 
379 static void
380   ClassInitialize();
381 
382 static void
383   DeleteChild( Widget  widget );
384 
385 static void
386   Destroy( Widget   widget );
387 
388 static void
389   ExposeMonthDisplay( Widget  widget,
390                       XEvent  *event,
391                       Region  region );
392 
393 static XtGeometryResult
394   GeometryManager( Widget            widget,
395                    XtWidgetGeometry  *request,
396                    XtWidgetGeometry  *reply );
397 
398 static void
399   GetValuesHook( Widget    w,
400                  ArgList   args,
401                  Cardinal  *num_args );
402 
403 static void
404   Initialize( Widget     treq,
405               Widget     tnew,
406               ArgList    args,
407               Cardinal   *num_args );
408 
409 static void
410   InsertChild( Widget  widget );
411 
412 static XtGeometryResult
413   QueryGeometry( Widget             widget,
414                  XtWidgetGeometry  *proposed,
415                  XtWidgetGeometry  *answer );
416 
417 static void
418   Resize( Widget    widget );
419 
420 static Boolean
421   SetValues( Widget     current,
422              Widget     request,
423              Widget     new,
424              ArgList    args,
425              Cardinal   *num_args );
426 
427 
428 /* Internal functions. */
429 
430 /* Gets the date that is set for a button. */
431 static void
432   ButtonDate( XmUbMonthDisplayWidget  md,
433               Widget                  button,
434               int                     *year,
435               int                     *month,
436               int                     *day );
437 
438 static void
439   CallNewMonthCallbacks( XmUbMonthDisplayWidget  md );
440 
441 /* If not in the child list, returns XmUbMD_CHILD_ERROR. */
442 static int
443   ChildIndex( XmUbMonthDisplayWidget  md,
444               Widget                  child );
445 
446 static void
447   CreateMonthRowColumns( XmUbMonthDisplayWidget  md,
448                          String                  name );
449 
450 static void
451   CreateInternalWidgets( XmUbMonthDisplayWidget  md );
452 
453 static Widget
454   DateButton( XmUbMonthDisplayWidget  md,
455               int                     day_number );
456 
457 static int
458   DateButtonIndex( XmUbMonthDisplayWidget  md,
459                    int                     day_number );
460 
461 #if XmVersion > 1001
462 static Boolean
463   DateDragConvertProc( Widget         w,
464                        Atom           *selection,
465                        Atom           *target,
466                        Atom           *typeRtn,
467                        XtPointer      *valueRtn,
468                        unsigned long  *lengthRtn,
469                        int            *formatRtn,
470                        unsigned long  *max_lengthRtn,
471                        XtPointer      client_data,
472                        XtRequestId    *request_id );
473 
474 static void
475   DateEnterDropSiteCB( Widget                         drag_context,
476                        XmUbMonthDisplayWidget         md,
477                        XmDropSiteEnterCallbackStruct  *call_data );
478 
479 static void
480   DateLeaveDropSiteCB( Widget                         drag_context,
481                        XmUbMonthDisplayWidget         md,
482                        XmDropSiteLeaveCallbackStruct  *call_data );
483 #endif
484 
485 static void
486   DayNumberButtonActivatedCB( Widget                      pb,
487                               XmUbMonthDisplayWidget      md,
488                               XmPushButtonCallbackStruct  *call_data );
489 
490 
491 /* The sizes array  must have been processed by GetChildPrefSizes
492    before DoLayout is called. */
493 static void
494   DoLayout( XmUbMonthDisplayWidget  md,
495             Widget                  initiator,
496             XtWidgetGeometry        *request,
497             KidDimensionRec         sizes[] );
498 
499 /* Fills in the width and height fields in the kids dimension recs. */
500 static void
501   GetChildPrefSizes( XmUbMonthDisplayWidget  md,
502                      Widget                  initiator,
503                      XtWidgetGeometry        *request,
504                      KidDimensionRec         sizes[] );
505 
506 
507 /* The sizes array must have been prepared by GetChildPrefSizes before this
508    function is called. */
509 static void
510   GetOwnPreferredSize( XmUbMonthDisplayWidget  md,
511                        KidDimensionRec         sizes[],
512                        Dimension               *pref_width,
513                        Dimension               *pref_height );
514 
515 static void
516   KidsPreferredGeometry( Widget            kid,
517                          Widget            initiator,
518                          XtWidgetGeometry  *request,
519                          XtWidgetGeometry  *desired );
520 
521 static void
522   MonthScrolledCB( Widget                        pb,
523                    XmUbMonthDisplayWidget        md,
524                    XmUbArrowLabelCallbackStruct  *call_data );
525 
526 /* ResizeIfNeeded fills in the sizes array. Does not have to be initialized. */
527 static Boolean
528   ResizeIfNeeded( XmUbMonthDisplayWidget  md,
529                   KidDimensionRec         sizes[] );
530 
531 static void
532   SetDayNames( XmUbMonthDisplayWidget  md );
533 
534 #if XmVersion > 1001
535 static void
536   StartDateDrag( Widget    w,
537                  XEvent    *event,
538                  String    *params,
539                  Cardinal  num_params );
540 #endif
541 
542 static void
543   TitleBarPressedCB( Widget                      pb,
544                      XmUbMonthDisplayWidget      md,
545                      XmPushButtonCallbackStruct  *call_data );
546 
547 static void
548   UpdateDayButton( XmUbMonthDisplayWidget  md,
549                    int                     index,
550                    int                     date,
551                    XmUbWhichMonth          which_month );
552 
553 static void
554   UpdateNewMonth( XmUbMonthDisplayWidget  md );
555 
556 static void
557   UpdateWeekButton( XmUbMonthDisplayWidget  md,
558                     int                     index,
559                     TIM_TIME_REF            time_of_first_day,
560                     Boolean                 mapped );
561 
562 static void
563   WarningNoResourceChange( XmUbMonthDisplayWidget  md,
564                            String                  resource );
565 
566 static void
567   WeekNumberButtonActivatedCB( Widget                      pb,
568                                XmUbMonthDisplayWidget      md,
569                                XmPushButtonCallbackStruct  *call_data );
570 
571 static void
572   YearScrolledCB( Widget                        pb,
573                   XmUbMonthDisplayWidget        md,
574                   XmUbArrowLabelCallbackStruct  *call_data );
575 
576 /*----------------------------------------------------------------------------
577 --  Initialization of the class record.
578 ----------------------------------------------------------------------------*/
579 
580 #if XmVersion > 1001
581 
582 /* Date label translation list. */
583 static char dateTranslationTable[] =
584   "<Btn2Down>: start-date-drag()";
585 
586 static XtTranslations  dateTranslations;
587 
588 /* Action list. */
589 static XtActionsRec actionsList[] =
590 {
591   { "start-date-drag", (XtActionProc) StartDateDrag },
592 };
593 
594 #endif
595 
596 /* This initialization has to be done after the methods have been declared. */
597 XmUbMonthDisplayClassRec xmUbMonthDisplayClassRec = {
598 
599   { /* Core class fields. */
600     /* superclass */                    (WidgetClass) &xmManagerClassRec,
601     /* class_name */                    "XmUbMonthDisplay",
602     /* widget_size */                   sizeof( XmUbMonthDisplayRec ),
603     /* class_initialize */              ClassInitialize,
604     /* class_part_initialize */         NULL,
605     /* class_inited */                  False,
606     /* initialize */                    Initialize,
607     /* initialize_hook */               NULL,
608     /* realize */                       XtInheritRealize,
609 #if XmVersion > 1001
610     /* actions */                       actionsList,
611     /* num_actions */                   XtNumber( actionsList ),
612 #else
613     /* actions */                       NULL,
614     /* num_actions */                   0,
615 #endif
616     /* resources */                     resources,
617     /* num_resources */                 XtNumber( resources ),
618     /* xrm_class */                     NULLQUARK,
619     /* compress_motion */               True,
620     /* compress_exposure */             True,
621     /* compress_enterleave */           True,
622     /* visible_interest */              False,
623     /* destroy */                       Destroy,
624     /* resize */                        Resize,
625     /* expose */                        ExposeMonthDisplay,
626     /* set_values */                    SetValues,
627     /* set_values_hook */               NULL,
628     /* set_values_almost */             XtInheritSetValuesAlmost,
629     /* get_values_hook */               GetValuesHook,
630     /* accept_focus */                  NULL,
631     /* version */                       XtVersion,
632     /* callback_private */              NULL,
633     /* tm_table */                      NULL,
634     /* query_geometry */                QueryGeometry,
635     /* display_accelerator */           XtInheritDisplayAccelerator,
636     /* extension */                     NULL
637   },
638   { /* Composite class part. */
639     /* geometry_manager */              GeometryManager,
640     /* change_managed */                ChangeManaged,
641     /* insert_child */                  InsertChild,
642     /* delete_child */                  DeleteChild,
643     /* extension */                     NULL
644   },
645   { /* Constraint class fields. */
646     /* subresources */                  NULL,
647     /* subresource_count */             0,
648     /* constraint_size */               sizeof(
649                                           XmUbMonthDisplayConstraintsRec ),
650     /* initialize */                    NULL,
651     /* destroy */                       NULL,
652     /* set_values */                    NULL,
653     /* extension */                     NULL
654   },
655   { /* XmManager class part. */
656     /* translations */                  NULL,
657     /* get_resources */                 NULL,
658     /* num_get_resources */             0,
659     /* get_constraint_resources */      NULL,
660     /* num_get_constraint_resources */  0,
661     /* extension */                     NULL
662   },
663   { /* Month display class part. */
664     /* extension */                     NULL
665   },
666 
667 };
668 
669 
670 /* Class record pointer. */
671 WidgetClass
672   xmUbMonthDisplayWidgetClass = (WidgetClass) &xmUbMonthDisplayClassRec;
673 
674 
675 
676 /*----------------------------------------------------------------------------
677 --  Functions
678 ----------------------------------------------------------------------------*/
679 
680 
681 static void
ButtonDate(XmUbMonthDisplayWidget md,Widget button,int * year,int * month,int * day)682   ButtonDate( XmUbMonthDisplayWidget  md,
683               Widget                  button,
684               int                     *year,
685               int                     *month,
686               int                     *day )
687 {
688   /* Variables. */
689   Arg       args[ 1 ];
690   Cardinal  n;
691   int       user_data;
692 
693   /* Code. */
694 
695   /* The date information is in the user data resource of the button. */
696   n = 0;
697   XtSetArg( args[ n ], XmNuserData, &user_data ); n++;
698   XtGetValues( button, args, n );
699 
700   *day = user_data % 100;
701 
702   if( user_data < PREVIOUS_MONTH_OFFSET ){
703     /* Current month. */
704     *month = md -> md.current_month;
705     *year  = md -> md.current_year;
706 
707   } else if( user_data < NEXT_MONTH_OFFSET ){
708     /* Previous month. */
709     *month = md -> md.current_month - 1;
710     *year  = md -> md.current_year;
711 
712     if( *month < 1 ){
713       *month = 12;
714       (*year) --;
715     }
716 
717   } else {
718     /* Next month. */
719     *month = md -> md.current_month + 1;
720     *year  = md -> md.current_year;
721 
722     if( *month > 12 ){
723       *month = 1;
724       (*year) ++;
725     }
726   }
727 
728 
729   return;
730 
731 } /* ButtonDate */
732 
733 
734 /*----------------------------------------------------------------------*/
735 
736 static void
CallNewMonthCallbacks(XmUbMonthDisplayWidget md)737   CallNewMonthCallbacks( XmUbMonthDisplayWidget  md )
738 {
739   /* Variables. */
740   XmUbMonthDisplayCallbackStruct  cb;
741 
742   /* Code. */
743 
744   if( md -> md.new_month_callback == NULL )
745     return;
746 
747   /* Callbacks are defined. */
748   /* Set up the callback structure. */
749   cb.reason         = XmUbCR_NEW_MONTH;
750   cb.event          = NULL;
751   cb.selected_month = md -> md.current_month;
752   cb.selected_year  = md -> md.current_year;
753 
754   /* Call the user callbacks. */
755   XtCallCallbackList( (Widget) md, md -> md.new_month_callback,
756                       (XtPointer) &cb );
757 
758 
759   return;
760 
761 } /* CallNewMonthCallbacks */
762 
763 
764 /*----------------------------------------------------------------------*/
765 
766 static void
ChangeManaged(Widget widget)767   ChangeManaged( Widget  widget )
768 {
769   /* Variables. */
770   Boolean                 layout_done;
771   KidDimensionRec         kids_sizes[ NO_INTERNAL_CHILDREN ];
772   XmUbMonthDisplayWidget  md;
773 
774 
775   /* Code. */
776 
777   md = (XmUbMonthDisplayWidget) widget;
778 
779   /* ResizeIfNeeded checks the size of all children and resizes the widget. */
780   layout_done = ResizeIfNeeded( md, kids_sizes );
781 
782   /* Do the layout. */
783   if( !layout_done )
784     DoLayout( md, NULL, NULL, kids_sizes );
785 
786 
787   return;
788 
789 } /* ChangeManaged */
790 
791 
792 /*----------------------------------------------------------------------*/
793 
794 static int
ChildIndex(XmUbMonthDisplayWidget md,Widget child)795   ChildIndex( XmUbMonthDisplayWidget  md,
796               Widget                  child )
797 {
798   /* Variables. */
799   int  index;
800 
801   /* Code. */
802 
803   for( index = 0; index < NO_INTERNAL_CHILDREN; index ++ ){
804 
805     if( md -> md.internal_children[ index ] == child )
806       return index;
807 
808   } /* for */
809 
810 
811   /* Specified child not found. */
812   return XmUbMD_CHILD_ERROR;
813 
814 } /* ChildIndex */
815 
816 
817 /*----------------------------------------------------------------------*/
818 
819 static void
ClassInitialize()820   ClassInitialize()
821 {
822   /* Code. */
823 
824 #if XmVersion > 1001
825   /* Parse translations tables. */
826   dateTranslations = XtParseTranslationTable( (String) dateTranslationTable );
827 #endif
828 
829   return;
830 
831 } /* ClassInitialize */
832 
833 
834 /*----------------------------------------------------------------------*/
835 
836 static void
CreateInternalWidgets(XmUbMonthDisplayWidget md)837   CreateInternalWidgets( XmUbMonthDisplayWidget  md )
838 {
839   /* Variables. */
840   Arg           args[ 5 ];
841   Cardinal      n;
842   char          *name_buffer;
843   String        wname;
844   XmString      xm;
845 
846   /* Code. */
847 
848   /* Get the name of the "parent" widget. */
849   wname = XtName( (Widget)md );
850   name_buffer = XtMalloc( strlen( wname ) + 4 );
851 
852   /* Title bar. */
853 
854   sprintf( name_buffer, "%sTi", wname );
855 
856   n = 0;
857   if( md -> md.title_shadows ){
858     XtSetArg( args[ n ], XmNshadowThickness, 1 ); n++;
859   } else {
860     XtSetArg( args[ n ], XmNshadowThickness, 0 ); n++;
861   }
862 
863   XtSetArg( args[ n ], XmNuserData, TITLE_ID_USER_DATA ); n++;
864   md -> md.internal_children[ XmUbMD_CHILD_TITLE ] =
865     XmCreatePushButton( (Widget) md, name_buffer, args, n );
866   XtManageChild( md -> md.internal_children[ XmUbMD_CHILD_TITLE ] );
867 
868   XtAddCallback( md -> md.internal_children[ XmUbMD_CHILD_TITLE ],
869                  XmNactivateCallback,
870                  (XtCallbackProc) TitleBarPressedCB, (XtPointer) md );
871 
872   /* Provide some user feedback -- no pressing if no action. */
873   if( ( md -> md.title_callback == NULL ) &&
874       ! md -> md.use_default_title_callback ){
875 
876     n = 0;
877     XtSetArg( args[ n ], XmNfillOnArm, False ); n++;
878     XtSetValues( md -> md.internal_children[ XmUbMD_CHILD_TITLE ], args, n );
879   }
880 
881 #if XmVersion > 1001
882   /* We have our own processing of drag. */
883   XtOverrideTranslations( md -> md.internal_children[ XmUbMD_CHILD_TITLE ],
884                           dateTranslations );
885 #endif
886 
887   /* Month display. */
888 
889   sprintf( name_buffer, "%sRc", wname );
890   CreateMonthRowColumns( md, name_buffer );
891 
892   XtManageChild( md -> md.internal_children[ XmUbMD_CHILD_ROW_COLUMN ] );
893   if( md -> md.internal_children[ XmUbMD_CHILD_WEEK_RC ] != NULL )
894     XtManageChild( md -> md.internal_children[ XmUbMD_CHILD_WEEK_RC ] );
895 
896   /* Month arrows. */
897   if( md -> md.month_arrows ){
898     sprintf( name_buffer, "%sMa", wname );
899 
900     n = 0;
901 
902     if( md -> md.month_label == NULL )
903       xm = XmStringCreateLtoR( default_month_string,
904                                XmSTRING_DEFAULT_CHARSET );
905     else
906       xm = md -> md.month_label;
907 
908     XtSetArg( args[ n ], XmNlabelString, xm ); n++;
909 
910     md -> md.internal_children[ XmUbMD_CHILD_MONTH_ARROW ] =
911       XmUbCreateArrowLabel( (Widget) md, name_buffer, args, n );
912 
913     if( md -> md.month_label == NULL )
914       XmStringFree( xm );
915 
916     XtAddCallback( md -> md.internal_children[ XmUbMD_CHILD_MONTH_ARROW ],
917                    XmNactivateCallback,
918                    (XtCallbackProc) MonthScrolledCB, (XtPointer) md );
919 
920     XtManageChild( md -> md.internal_children[ XmUbMD_CHILD_MONTH_ARROW ] );
921   }
922 
923   /* Year arrows. */
924   if( md -> md.year_arrows ){
925     sprintf( name_buffer, "%sYa", wname );
926 
927     n = 0;
928 
929     if( md -> md.year_label == NULL )
930       xm = XmStringCreateLtoR( default_year_string,
931                                XmSTRING_DEFAULT_CHARSET );
932     else
933       xm = md -> md.year_label;
934 
935     XtSetArg( args[ n ], XmNlabelString, xm ); n++;
936 
937     md -> md.internal_children[ XmUbMD_CHILD_YEAR_ARROW ] =
938       XmUbCreateArrowLabel( (Widget) md, name_buffer, args, n );
939 
940     if( md -> md.year_label == NULL )
941       XmStringFree( xm );
942 
943     XtAddCallback( md -> md.internal_children[ XmUbMD_CHILD_YEAR_ARROW ],
944                    XmNactivateCallback,
945                    (XtCallbackProc) YearScrolledCB, (XtPointer) md );
946 
947     XtManageChild( md -> md.internal_children[ XmUbMD_CHILD_YEAR_ARROW ] );
948   }
949 
950   /* Create separator if there are any arrow buttons. */
951   if( ( md -> md.year_arrows || md -> md.month_arrows ) &&
952       md -> md.enable_separator ){
953     sprintf( name_buffer, "%sSp", wname );
954 
955     n = 0;
956     XtSetArg( args[ n ], XmNorientation, XmHORIZONTAL ); n++;
957 
958     md -> md.internal_children[ XmUbMD_CHILD_SEPARATOR ] =
959       XmCreateSeparator( (Widget) md, name_buffer, args, n );
960 
961     XtManageChild( md -> md.internal_children[ XmUbMD_CHILD_SEPARATOR ] );
962   }
963 
964 
965   XtFree( name_buffer );
966 
967 
968   return;
969 
970 } /* CreateInternalWidgets */
971 
972 
973 /*----------------------------------------------------------------------*/
974 
975 static void
CreateMonthRowColumns(XmUbMonthDisplayWidget md,String name)976   CreateMonthRowColumns( XmUbMonthDisplayWidget  md,
977                          String                  name )
978 {
979   /* Variables. */
980   Arg        args[ 6 ];
981   XmString   empty_xm;
982   Dimension  height, max_height;
983   int        index;
984   Cardinal   n;
985   char       *name_buffer;
986   Widget     rc;
987   Dimension  width, max_width;
988   XmString   xm;
989 
990   /* Code. */
991 
992   name_buffer = XtMalloc( strlen( name ) + 5 );
993 
994   sprintf( name_buffer, "%sRc", name );
995 
996   n = 0;
997   XtSetArg( args[ n ], XmNorientation, XmHORIZONTAL ); n++;
998   XtSetArg( args[ n ], XmNpacking, XmPACK_COLUMN ); n++;
999   XtSetArg( args[ n ], XmNnumColumns, 7 ); n++;
1000   XtSetArg( args[ n ], XmNspacing, 0 ); n++;
1001   rc = XmCreateRowColumn( (Widget) md, name_buffer, args, n );
1002 
1003   /* We have to start by setting the label empty, since we look for the
1004      biggest one and don't want ghosts. */
1005   empty_xm = XmStringCreateLtoR( "", XmSTRING_DEFAULT_CHARSET );
1006 
1007   /* Create the day name buttons. */
1008   n = 0;
1009   XtSetArg( args[ n ], XmNshadowThickness, 0 ); n++;
1010   XtSetArg( args[ n ], XmNtraversalOn, False ); n++;
1011   XtSetArg( args[ n ], XmNlabelString, empty_xm ); n++;
1012 
1013   for( index = 0; index < NO_DAY_NAME_BUTTONS; index ++ ){
1014     sprintf( name_buffer, "%sDn%d", name, index );
1015     md -> md.day_name_buttons[ index ] =
1016       XmCreateLabel( rc, name_buffer, args, n );
1017   }
1018 
1019   /* Create the day number buttons. */
1020   n = 0;
1021   XtSetArg( args[ n ], XmNshadowThickness, 1 ); n++;
1022   XtSetArg( args[ n ], XmNlabelString, empty_xm ); n++;
1023   XtSetArg( args[ n ], XmNalignment, XmALIGNMENT_END ); n++;
1024 
1025   for( index = 0; index < NO_DAY_BUTTONS; index ++ ){
1026     sprintf( name_buffer, "%sDb%d", name, index );
1027     md -> md.day_number_buttons[ index ] =
1028       XmCreatePushButton( rc, name_buffer, args, n );
1029 
1030     XtAddCallback( md -> md.day_number_buttons[ index ], XmNactivateCallback,
1031                    (XtCallbackProc) DayNumberButtonActivatedCB,
1032                    (XtPointer) md );
1033 
1034 #if XmVersion > 1001
1035     /* We have our own processing of drag. */
1036     XtOverrideTranslations( md -> md.day_number_buttons[ index ],
1037                             dateTranslations );
1038 #endif
1039   }
1040 
1041   /* Save the default shadow colors. */
1042   n = 0;
1043   XtSetArg( args[ n ], XmNtopShadowColor,
1044                        & md -> md.pushb_default_topshadow ); n++;
1045   XtSetArg( args[ n ], XmNbottomShadowColor,
1046                        & md -> md.pushb_default_bottomshadow ); n++;
1047   XtGetValues( md -> md.day_number_buttons[ 0 ], args, n );
1048 
1049 
1050   /* Create the week number row column if desired. */
1051   if( md -> md.week_numbers ){
1052 
1053     sprintf( name_buffer, "%sWrc", name );
1054 
1055     n = 0;
1056     XtSetArg( args[ n ], XmNorientation, XmHORIZONTAL ); n++;
1057     XtSetArg( args[ n ], XmNpacking, XmPACK_COLUMN ); n++;
1058     XtSetArg( args[ n ], XmNnumColumns, 7 ); n++;
1059     XtSetArg( args[ n ], XmNspacing, 0 ); n++;
1060     md -> md.internal_children[ XmUbMD_CHILD_WEEK_RC ] =
1061       XmCreateRowColumn( (Widget) md, name_buffer, args, n );
1062 
1063     for( index = 0; index < NO_WEEK_NUMBER_BUTTONS; index ++ ){
1064       sprintf( name_buffer, "%sWb%d", name, index );
1065 
1066       n = 0;
1067       XtSetArg( args[ n ], XmNlabelString, empty_xm ); n++;
1068       XtSetArg( args[ n ], XmNuserData, 0 ); n++;
1069       if( index == 0 ){
1070         XtSetArg( args[ n ], XmNshadowThickness, 0 ); n++;
1071       } else {
1072         XtSetArg( args[ n ], XmNshadowThickness, 1 ); n++;
1073       }
1074       XtSetArg( args[ n ], XmNalignment, XmALIGNMENT_END ); n++;
1075 
1076       if( index == 0 )
1077         md -> md.week_number_buttons[ index ] =
1078           XmCreateLabel( md -> md.internal_children[ XmUbMD_CHILD_WEEK_RC ],
1079                          name_buffer, args, n );
1080       else {
1081         md -> md.week_number_buttons[ index ] = XmCreatePushButton(
1082           md -> md.internal_children[ XmUbMD_CHILD_WEEK_RC ],
1083           name_buffer, args, n );
1084 
1085         XtAddCallback( md -> md.week_number_buttons[ index ],
1086                        XmNactivateCallback,
1087                        (XtCallbackProc) WeekNumberButtonActivatedCB,
1088                        (XtPointer) md );
1089 
1090 #if XmVersion > 1001
1091         /* We have our own processing of drag. */
1092         XtOverrideTranslations( md -> md.week_number_buttons[ index ],
1093                                 dateTranslations );
1094 #endif
1095       }
1096     }
1097 
1098     /* Set the week number "title". */
1099     if( md -> md.week_number_label == NULL )
1100       xm = XmStringCreateLtoR( "W", XmSTRING_DEFAULT_CHARSET );
1101     else
1102       xm = md -> md.week_number_label;
1103 
1104     n = 0;
1105     XtSetArg( args[ n ], XmNlabelString, xm ); n++;
1106     XtSetArg( args[ n ], XmNalignment, XmALIGNMENT_CENTER ); n++;
1107     XtSetValues( md -> md.week_number_buttons[ 0 ], args, n );
1108 
1109     if( md -> md.week_number_label == NULL )
1110       XmStringFree( xm );
1111   }
1112 
1113   /* Set the texts of the buttons and the title. */
1114   UpdateNewMonth( md );
1115 
1116   /* Manage the created internal buttons. */
1117   XtManageChildren( md -> md.day_name_buttons, NO_DAY_NAME_BUTTONS );
1118   XtManageChildren( md -> md.day_number_buttons, NO_DAY_BUTTONS );
1119   if( md -> md.week_numbers )
1120     XtManageChildren( md -> md.week_number_buttons, NO_WEEK_NUMBER_BUTTONS );
1121 
1122   /* Find out biggest button and set all to that size. */
1123 
1124   max_height = 0;
1125   max_width  = 0;
1126 
1127   n = 0;
1128   XtSetArg( args[ n ], XmNwidth, &width ); n++;
1129   XtSetArg( args[ n ], XmNheight, &height ); n++;
1130 
1131   for( index = 0; index < NO_DAY_NAME_BUTTONS; index ++ ){
1132     XtGetValues( md -> md.day_name_buttons[ index ], args, n );
1133 
1134     if( height > max_height )
1135       max_height = height;
1136     if( width > max_width )
1137       max_width = width;
1138 
1139   } /* for */
1140 
1141   for( index = 0; index < NO_DAY_BUTTONS; index ++ ){
1142     XtGetValues( md -> md.day_number_buttons[ index ], args, n );
1143 
1144     if( height > max_height )
1145       max_height = height;
1146     if( width > max_width )
1147       max_width = width;
1148 
1149   } /* for */
1150 
1151   if( md -> md.week_numbers ){
1152     for( index = 0; index < NO_WEEK_NUMBER_BUTTONS; index ++ ){
1153       XtGetValues( md -> md.week_number_buttons[ index ], args, n );
1154 
1155       if( height > max_height )
1156         max_height = height;
1157       if( width > max_width )
1158         max_width = width;
1159 
1160     } /* for */
1161   }
1162 
1163   /* Set all to max size and hint not to resize again. */
1164   n = 0;
1165   XtSetArg( args[ n ], XmNwidth, max_width ); n++;
1166   XtSetArg( args[ n ], XmNheight, max_height ); n++;
1167   XtSetArg( args[ n ], XmNrecomputeSize, False ); n++;
1168   XtSetArg( args[ n ], XmNalignment, XmALIGNMENT_END ); n++;
1169 
1170   for( index = 0; index < NO_DAY_NAME_BUTTONS; index ++ )
1171     XtSetValues( md -> md.day_name_buttons[ index ], args, n );
1172   for( index = 0; index < NO_DAY_BUTTONS; index ++ )
1173     XtSetValues( md -> md.day_number_buttons[ index ], args, n );
1174 
1175   if( md -> md.week_numbers ){
1176     for( index = 0; index < NO_WEEK_NUMBER_BUTTONS; index ++ )
1177       XtSetValues( md -> md.week_number_buttons[ index ], args, n );
1178   }
1179 
1180   /* Set row column geometry explicitly. */
1181 #if XmVersion < 1002
1182   {
1183     Dimension  margin_height;
1184     Dimension  margin_width;
1185     Widget     wrc;
1186 
1187     /* Code. */
1188 
1189     n = 0;
1190     XtSetArg( args[ n ], XmNmarginWidth, &margin_width ); n++;
1191     XtSetArg( args[ n ], XmNmarginHeight, &margin_height ); n++;
1192     XtGetValues( rc, args, n );
1193 
1194     n = 0;
1195     XtSetArg( args[ n ], XmNwidth, max_width * 7 + 2 * margin_width ); n++;
1196     XtSetArg( args[ n ], XmNheight, max_height * 7 + 2 * margin_height ); n++;
1197     XtSetArg( args[ n ], XmNnumColumns, 7 ); n++;
1198     XtSetArg( args[ n ], XmNpacking, XmPACK_COLUMN ); n++;
1199     XtSetArg( args[ n ], XmNresizeHeight, False ); n++;
1200     XtSetArg( args[ n ], XmNresizeWidth, False ); n++;
1201     XtSetValues( rc, args, n );
1202 
1203     if( md -> md.week_numbers ){
1204       wrc = md -> md.internal_children[ XmUbMD_CHILD_WEEK_RC ];
1205       n = 0;
1206       XtSetArg( args[ n ], XmNmarginWidth, &margin_width ); n++;
1207       XtSetArg( args[ n ], XmNmarginHeight, &margin_height ); n++;
1208       XtGetValues( wrc, args, n );
1209 
1210       n = 0;
1211       XtSetArg( args[ n ], XmNwidth, max_width + 2 * margin_width ); n++;
1212       XtSetArg( args[ n ], XmNheight,
1213                            max_height * 7 + 2 * margin_height ); n++;
1214       XtSetArg( args[ n ], XmNnumColumns, 7 ); n++;
1215       XtSetArg( args[ n ], XmNpacking, XmPACK_COLUMN ); n++;
1216       XtSetArg( args[ n ], XmNresizeHeight, False ); n++;
1217       XtSetArg( args[ n ], XmNresizeWidth, False ); n++;
1218       XtSetValues( wrc, args, n );
1219     }
1220   }
1221 #endif
1222 
1223   /* Cleanup. */
1224   XtFree( name_buffer );
1225   XmStringFree( empty_xm );
1226 
1227 
1228   md -> md.internal_children[ XmUbMD_CHILD_ROW_COLUMN ] = rc;
1229 
1230 
1231   return;
1232 
1233 } /* CreateMonthRowColumns */
1234 
1235 
1236 /*----------------------------------------------------------------------*/
1237 
1238 static Widget
DateButton(XmUbMonthDisplayWidget md,int day_number)1239   DateButton( XmUbMonthDisplayWidget  md,
1240               int                     day_number )
1241 {
1242   /* Variables. */
1243   int  day_index;
1244 
1245   /* Code. */
1246 
1247   day_index = DateButtonIndex( md, day_number );
1248 
1249   if( day_index > ( NO_DAY_BUTTONS - 1 ) )
1250     return( NULL );
1251 
1252   else
1253     return( md -> md.day_number_buttons[ day_index ] );
1254 
1255 
1256 } /* DateButton */
1257 
1258 
1259 /*----------------------------------------------------------------------*/
1260 
1261 static int
DateButtonIndex(XmUbMonthDisplayWidget md,int day_number)1262   DateButtonIndex( XmUbMonthDisplayWidget  md,
1263                    int                     day_number )
1264 {
1265   /* Code. */
1266 
1267   return( md -> md.first_date_index + day_number - 1 );
1268 
1269 } /* DateButtonIndex */
1270 
1271 
1272 /*----------------------------------------------------------------------*/
1273 
1274 #if XmVersion > 1001
1275 
1276 static Boolean
DateDragConvertProc(Widget w,Atom * selection,Atom * target,Atom * typeRtn,XtPointer * valueRtn,unsigned long * lengthRtn,int * formatRtn,unsigned long * max_lengthRtn,XtPointer client_data,XtRequestId * request_id)1277   DateDragConvertProc( Widget         w,
1278                        Atom           *selection,
1279                        Atom           *target,
1280                        Atom           *typeRtn,
1281                        XtPointer      *valueRtn,
1282                        unsigned long  *lengthRtn,
1283                        int            *formatRtn,
1284                        unsigned long  *max_lengthRtn,
1285                        XtPointer      client_data,
1286                        XtRequestId    *request_id )
1287 {
1288   /* Variables. */
1289   Arg                     args[ 5 ];
1290   Widget                  button;
1291   Atom                    compound_text_atom;
1292   char                    *ctext;
1293   Atom                    date_transfer_atom;
1294   int                     day;
1295   int                     index;
1296   XmUbMonthDisplayWidget  md;
1297   int                     month;
1298   Cardinal                n;
1299   char                    *passtext;
1300   TIM_TIME_REF            time;
1301   Widget                  tmp_widget;
1302   XmUbDateTransfer        *transfer_data;
1303   Boolean                 week;
1304   int                     week_index = -1;
1305   XmString                xm;
1306   int                     year;
1307 
1308   /* Code. */
1309 
1310   compound_text_atom = XmInternAtom( XtDisplay( w ), "COMPOUND_TEXT", False );
1311   date_transfer_atom = XmInternAtom( XtDisplay( w ), XmUbDATE_TRANSFER,
1312                                      False );
1313 
1314   /* Refuse incompatible transfer. */
1315   if( ! ( ( *target == compound_text_atom ) ||
1316           ( *target == date_transfer_atom ) ) )
1317     return( False );
1318 
1319   /* The id of the button widget is set in the clientData resource of the
1320      DragContext widget. */
1321   n = 0;
1322   XtSetArg( args[ n ], XmNclientData, &button ); n++;
1323   XtGetValues( w, args, n );
1324 
1325   /* Find month display widget. */
1326   tmp_widget = XtParent( button );
1327   while( ! XtIsSubclass( tmp_widget, xmUbMonthDisplayWidgetClass ) )
1328     tmp_widget = XtParent( tmp_widget );
1329 
1330   md = (XmUbMonthDisplayWidget) tmp_widget;
1331 
1332   if( *target == date_transfer_atom ){
1333 
1334     /* Transfer in special date format. */
1335     transfer_data =
1336       (XmUbDateTransfer*) XtMalloc( sizeof( XmUbDateTransfer ) );
1337 
1338     /* The type of transfer depends on which type of button was pressed. */
1339     if( button == md -> md.internal_children[ XmUbMD_CHILD_TITLE ] ){
1340       /* Dragging a month. */
1341       transfer_data -> type = XmUbTRANSFER_RANGE;
1342 
1343       transfer_data -> year  = md -> md.current_year;
1344       transfer_data -> month = md -> md.current_month;
1345       transfer_data -> day   = 1;
1346 
1347       time = TimMakeTime( md -> md.current_year, md -> md.current_month, 1,
1348                           0, 0, 0 );
1349 
1350       transfer_data -> end_year  = md -> md.current_year;
1351       transfer_data -> end_month = md -> md.current_month;
1352       transfer_data -> end_day   = TimDaysInMonth( time );
1353 
1354     } else {
1355 
1356       /* This could be a week number or a date button. Faster to loop through
1357          the week numbers. */
1358       week = False;
1359       if( md -> md.week_numbers ){
1360         for( index = 0; index < NO_WEEK_NUMBER_BUTTONS; index ++ ){
1361           if( button == md -> md.week_number_buttons[ index ] ){
1362             week = True;
1363             week_index = index;
1364             break;
1365           }
1366         }
1367       }
1368       assert( week_index != -1 );
1369 
1370       if( week ){
1371         /* Find the first date button for the week. */
1372         index = ( week_index - 1 ) * 7;
1373 
1374         ButtonDate( md, md -> md.day_number_buttons[ index ],
1375                     &year, &month, &day );
1376 
1377         transfer_data -> type  = XmUbTRANSFER_RANGE;
1378         transfer_data -> year  = year;
1379         transfer_data -> month = month;
1380         transfer_data -> day   = day;
1381 
1382         /* End date. */
1383         index += 6;
1384 
1385         ButtonDate( md, md -> md.day_number_buttons[ index ],
1386                     &year, &month, &day );
1387 
1388         transfer_data -> end_year  = year;
1389         transfer_data -> end_month = month;
1390         transfer_data -> end_day   = day;
1391 
1392       } else {
1393         /* Date transfer. */
1394 
1395         /* Get current month and year and construct string with date. */
1396         ButtonDate( md, button, &year, &month, &day );
1397 
1398         transfer_data -> type  = XmUbTRANSFER_DATE;
1399         transfer_data -> year  = year;
1400         transfer_data -> month = month;
1401         transfer_data -> day   = day;
1402       }
1403     }
1404 
1405     /* Set up the transfer values. */
1406     *typeRtn   = date_transfer_atom;
1407     *valueRtn  = (XtPointer) transfer_data;
1408     *lengthRtn = sizeof( XmUbDateTransfer );
1409     *formatRtn = 8;
1410 
1411   } else {
1412     /* We should just transfer the label string. */
1413 
1414     n = 0;
1415     XtSetArg( args[ n ], XmNlabelString, &xm ); n++;
1416     XtGetValues( button, args, n );
1417 
1418     ctext = XmCvtXmStringToCT( xm );
1419 
1420     /* We must copy the string for transfer. */
1421     passtext = XtMalloc( strlen( ctext ) + 1 );
1422     memcpy( passtext, ctext, strlen( ctext ) + 1 );
1423 
1424     /* Free what has been allocated here. passtext will be freed by Xt. */
1425     XmStringFree( xm );
1426     XtFree( ctext );
1427 
1428     /* Set up the transfer values. */
1429     *typeRtn   = compound_text_atom;
1430     *valueRtn  = (XtPointer) passtext;
1431     *lengthRtn = strlen( passtext );
1432     *formatRtn = 8;
1433 
1434   }
1435 
1436   return( True );
1437 
1438 } /* DateDragConvertProc */
1439 
1440 #endif
1441 
1442 /*----------------------------------------------------------------------*/
1443 
1444 #if XmVersion > 1001
1445 
1446 static void
DateEnterDropSiteCB(Widget drag_context,XmUbMonthDisplayWidget md,XmDropSiteEnterCallbackStruct * call_data)1447   DateEnterDropSiteCB( Widget                         drag_context,
1448                        XmUbMonthDisplayWidget         md,
1449                        XmDropSiteEnterCallbackStruct  *call_data )
1450 {
1451   /* Variables. */
1452   Arg       args[ 2 ];
1453   Cardinal  n;
1454 
1455   /* Code. */
1456 
1457   n = 0;
1458 
1459   if( call_data -> dropSiteStatus == XmVALID_DROP_SITE ){
1460     XtSetArg( args[ n ], XmNsourcePixmapIcon, md -> md.date_icon ); n++;
1461     XtSetArg( args[ n ], XmNsourceCursorIcon, md -> md.date_icon ); n++;
1462 
1463   } else {
1464     XtSetArg( args[ n ], XmNsourcePixmapIcon, md -> md.inv_date_icon ); n++;
1465     XtSetArg( args[ n ], XmNsourceCursorIcon, md -> md.inv_date_icon ); n++;
1466   }
1467 
1468   XtSetValues( drag_context, args, n );
1469 
1470 
1471   return;
1472 
1473 } /* DateEnterDropSiteCB */
1474 
1475 
1476 #endif
1477 
1478 /*----------------------------------------------------------------------*/
1479 
1480 #if XmVersion > 1001
1481 
1482 static void
DateLeaveDropSiteCB(Widget drag_context,XmUbMonthDisplayWidget md,XmDropSiteLeaveCallbackStruct * call_data)1483   DateLeaveDropSiteCB( Widget                         drag_context,
1484                        XmUbMonthDisplayWidget         md,
1485                        XmDropSiteLeaveCallbackStruct  *call_data )
1486 {
1487   /* Variables. */
1488   Arg       args[ 2 ];
1489   Cardinal  n;
1490 
1491   /* Code. */
1492 
1493   n = 0;
1494   XtSetArg( args[ n ], XmNsourcePixmapIcon, md -> md.inv_date_icon ); n++;
1495   XtSetArg( args[ n ], XmNsourceCursorIcon, md -> md.inv_date_icon ); n++;
1496   XtSetValues( drag_context, args, n );
1497 
1498 
1499   return;
1500 
1501 } /* DateLeaveDropSiteCB */
1502 
1503 #endif
1504 
1505 /*----------------------------------------------------------------------*/
1506 
1507 static void
DayNumberButtonActivatedCB(Widget pb,XmUbMonthDisplayWidget md,XmPushButtonCallbackStruct * call_data)1508   DayNumberButtonActivatedCB( Widget                      pb,
1509                               XmUbMonthDisplayWidget      md,
1510                               XmPushButtonCallbackStruct  *call_data )
1511 {
1512   /* Variables. */
1513   XmUbMonthDisplayCallbackStruct  cb;
1514   int                             day_number;
1515   int                             month_number;
1516   int                             year_number;
1517 
1518   /* Code. */
1519 
1520   /* Get the day number for the button. */
1521   ButtonDate( md, pb, &year_number, &month_number, &day_number );
1522 
1523   cb.selected_year  = year_number;
1524   cb.selected_month = month_number;
1525   cb.selected_day   = day_number;
1526 
1527   /* Invoke the callbacks. */
1528 
1529   cb.reason = XmUbCR_DATE_SELECTED;
1530   cb.event  = call_data -> event;
1531   cb.child  = pb;
1532   cb.range  = False;
1533 
1534   XtCallCallbackList( (Widget) md, md -> md.date_selected_callback,
1535                       (XtPointer) &cb );
1536 
1537 
1538   return;
1539 
1540 } /* DayNumberButtonActivatedCB */
1541 
1542 
1543 /*----------------------------------------------------------------------*/
1544 
1545 static void
DeleteChild(Widget widget)1546   DeleteChild( Widget  widget )
1547 {
1548 
1549   /* Variables. */
1550   int                     index;
1551   XmUbMonthDisplayWidget  md;
1552 
1553   /* Code. */
1554 
1555   md = (XmUbMonthDisplayWidget) XtParent( widget );
1556 
1557   /* Clear the internal reference. */
1558   for( index = 0; index < NO_INTERNAL_CHILDREN; index ++ ){
1559     if( md -> md.internal_children[ index ] == widget ){
1560       md -> md.internal_children[ index ] = NULL;
1561       break;
1562     }
1563   }
1564 
1565   /* Perform the actual operation */
1566   (* ( (CompositeWidgetClass) (xmUbMonthDisplayWidgetClass ->
1567      core_class.superclass) ) -> composite_class.delete_child ) ( widget );
1568 
1569 
1570   return;
1571 
1572 } /* DeleteChild */
1573 
1574 
1575 /*----------------------------------------------------------------------*/
1576 
1577 static void
Destroy(Widget widget)1578   Destroy( Widget   widget )
1579 {
1580   /* Variables. */
1581   XmUbMonthDisplayWidget  md;
1582 
1583   /* Code. */
1584   md = (XmUbMonthDisplayWidget) widget;
1585 
1586   /* Free XmStrings. */
1587   if( md -> md.week_number_label != NULL )
1588     XmStringFree( md -> md.week_number_label );
1589   if( md -> md.month_label != NULL )
1590     XmStringFree( md -> md.month_label );
1591   if( md -> md.year_label != NULL )
1592     XmStringFree( md -> md.year_label );
1593 
1594   /* Remove callbacks. */
1595   XtRemoveAllCallbacks( widget, XmUbNmdiDateSelectedCallback );
1596   XtRemoveAllCallbacks( widget, XmUbNmdiNewMonthCallback );
1597   XtRemoveAllCallbacks( widget, XmUbNmdiTitleCallback );
1598   XtRemoveAllCallbacks( widget, XmUbNmdiUpdateDayCallback );
1599 
1600   /* Remove pixmaps if created. */
1601   if( md -> md.date_icon_bm != None )
1602     XFreePixmap( XtDisplay( widget ), md -> md.date_icon_bm );
1603   if( md -> md.date_icon_mask != None )
1604     XFreePixmap( XtDisplay( widget ), md -> md.date_icon_mask );
1605   if( md -> md.inv_date_icon_bm != None )
1606     XFreePixmap( XtDisplay( widget ), md -> md.inv_date_icon_bm );
1607   if( md -> md.inv_date_icon_mask != None )
1608     XFreePixmap( XtDisplay( widget ), md -> md.inv_date_icon_mask );
1609 
1610 
1611   return;
1612 
1613 } /* Destroy */
1614 
1615 
1616 /*----------------------------------------------------------------------*/
1617 
1618 static void
DoLayout(XmUbMonthDisplayWidget md,Widget initiator,XtWidgetGeometry * request,KidDimensionRec sizes[])1619   DoLayout( XmUbMonthDisplayWidget  md,
1620             Widget                  initiator,
1621             XtWidgetGeometry        *request,
1622             KidDimensionRec         sizes[] )
1623 {
1624   /* Variables. */
1625   int                arrow_index;
1626   Position           arrow_y_pos;
1627   int                index;
1628   Widget             kid;
1629   Dimension          label_offset;
1630   Position           rc_lowest_pos;
1631   Dimension          rc_offset;
1632   Dimension          rc_width;
1633 
1634   /* Code. */
1635 
1636   /* Let the children keep their sizes. They will be clipped if window is too
1637      small. */
1638   /* Let the week number rc be part of the calculations. Its width and
1639      height will be zero anyway if it is not enabled. */
1640 
1641   /* Y positions. */
1642   sizes[ XmUbMD_CHILD_TITLE ].y       = (Position) md -> md.margin_height;
1643   sizes[ XmUbMD_CHILD_ROW_COLUMN ].y  = sizes[ XmUbMD_CHILD_TITLE ].y +
1644     (Position) ( sizes[ XmUbMD_CHILD_TITLE ].height + md -> md.margin_height );
1645   sizes[ XmUbMD_CHILD_WEEK_RC ].y     = sizes[ XmUbMD_CHILD_ROW_COLUMN ].y;
1646 
1647   rc_lowest_pos = MAX( sizes[ XmUbMD_CHILD_ROW_COLUMN ].y +
1648                        (Position) sizes[ XmUbMD_CHILD_ROW_COLUMN ].height,
1649                        sizes[ XmUbMD_CHILD_WEEK_RC ].y +
1650                        (Position) sizes[ XmUbMD_CHILD_WEEK_RC ].height );
1651 
1652   sizes[ XmUbMD_CHILD_SEPARATOR ].y = rc_lowest_pos;
1653 
1654   arrow_y_pos = sizes[ XmUbMD_CHILD_SEPARATOR ].y +
1655     (Position) sizes[ XmUbMD_CHILD_SEPARATOR ].height +
1656     (Position) md -> md.arrow_spacing;
1657 
1658   if( md -> md.month_arrows )
1659     sizes[ XmUbMD_CHILD_MONTH_ARROW ].y = arrow_y_pos;
1660 
1661   if( md -> md.year_arrows )
1662     sizes[ XmUbMD_CHILD_YEAR_ARROW ].y = arrow_y_pos;
1663 
1664   /* X positions. */
1665 
1666   /* The separator should extend to the edge of the widget. */
1667   sizes[ XmUbMD_CHILD_SEPARATOR ].x     = 0;
1668   sizes[ XmUbMD_CHILD_SEPARATOR ].width = md -> core.width;
1669 
1670   rc_width = sizes[ XmUbMD_CHILD_ROW_COLUMN ].width +
1671              sizes[ XmUbMD_CHILD_WEEK_RC ].width;
1672 
1673   if( md -> md.title_alignment == XmALIGNMENT_CENTER ){
1674 
1675     /* The label and row column should be centered. */
1676     if( sizes[ XmUbMD_CHILD_TITLE ].width > rc_width ){
1677       label_offset = 0;
1678       rc_offset    = ( sizes[ XmUbMD_CHILD_TITLE ].width - rc_width ) / 2;
1679     } else {
1680       label_offset = ( rc_width - sizes[ XmUbMD_CHILD_TITLE ].width ) / 2;
1681       rc_offset    = 0;
1682     }
1683 
1684     sizes[ XmUbMD_CHILD_TITLE ].x = (Position) ( md -> md.margin_width +
1685       label_offset );
1686     sizes[ XmUbMD_CHILD_WEEK_RC ].x = (Position) ( md -> md.margin_width +
1687       rc_offset );
1688     sizes[ XmUbMD_CHILD_ROW_COLUMN ].x = sizes[ XmUbMD_CHILD_WEEK_RC ].x +
1689       (Position) sizes[ XmUbMD_CHILD_WEEK_RC ].width;
1690 
1691   } else {
1692 
1693     /* The row column should be centered in the widget and the title should
1694        be placed according to its alignment. */
1695 
1696     if( rc_width < md -> core. width )
1697       sizes[ XmUbMD_CHILD_WEEK_RC ].x = (Position) ( md -> core.width -
1698         rc_width ) / 2;
1699     else
1700       sizes[ XmUbMD_CHILD_WEEK_RC ].x = 0;
1701 
1702     sizes[ XmUbMD_CHILD_ROW_COLUMN ].x = sizes[ XmUbMD_CHILD_WEEK_RC ].x +
1703       (Position) sizes[ XmUbMD_CHILD_WEEK_RC ].width;
1704 
1705     /* Place the label according to its defined alignment. */
1706     if( md -> md.title_alignment == XmALIGNMENT_BEGINNING )
1707       sizes[ XmUbMD_CHILD_TITLE ].x = (Position) md -> md.margin_width;
1708     else {
1709       if( sizes[ XmUbMD_CHILD_TITLE ].width <
1710           ( md -> core.width - md -> md.margin_width ) )
1711         sizes[ XmUbMD_CHILD_TITLE ].x = (Position) ( md -> core.width -
1712           md -> md.margin_width - sizes[ XmUbMD_CHILD_TITLE ].width );
1713       else
1714         sizes[ XmUbMD_CHILD_TITLE ].x = 0;
1715     }
1716   }
1717 
1718   /* If both arrow buttons are enabled, they should be glued to the left
1719      and right of the bottom side of the row column.
1720      Month to the left, year to the right. */
1721   /* The Y positions have already been set. */
1722 
1723   if( md -> md.month_arrows && md -> md.year_arrows ){
1724 
1725     sizes[ XmUbMD_CHILD_MONTH_ARROW ].x = sizes[ XmUbMD_CHILD_WEEK_RC ].x;
1726 
1727     if( rc_width > sizes[ XmUbMD_CHILD_YEAR_ARROW ].width )
1728       sizes[ XmUbMD_CHILD_YEAR_ARROW ].x = sizes[ XmUbMD_CHILD_ROW_COLUMN ].x +
1729         (Position) sizes[ XmUbMD_CHILD_ROW_COLUMN ].width -
1730         (Position) sizes[ XmUbMD_CHILD_YEAR_ARROW ].width;
1731     else
1732       sizes[ XmUbMD_CHILD_YEAR_ARROW ].x = sizes[ XmUbMD_CHILD_WEEK_RC ].x;
1733 
1734   } else if ( md -> md.month_arrows || md -> md.year_arrows ){
1735     /* One of the arrows is enabled. Center it. */
1736     if( md -> md.month_arrows )
1737       arrow_index = XmUbMD_CHILD_MONTH_ARROW;
1738     else
1739       arrow_index = XmUbMD_CHILD_YEAR_ARROW;
1740 
1741     if( sizes[ arrow_index ].width > rc_width + 2 * md -> md.margin_width )
1742       sizes[ arrow_index ].x = 0;
1743     else
1744       sizes[ arrow_index ].x = (Position) ( rc_width +
1745         2 * md -> md.margin_width - sizes[ arrow_index ].width ) / 2;
1746   }
1747 
1748   /* Configure the children. */
1749   /* All positions and dimensions are now in the sizes array. */
1750   for( index = XmUbMD_FIRST_CHILD; index < NO_INTERNAL_CHILDREN; index ++ ){
1751 
1752     kid = md -> md.internal_children[ index ];
1753 
1754     if( ( kid != NULL ) && XtIsManaged( kid ) )
1755       XtConfigureWidget( kid, sizes[ index ].x, sizes[ index ].y,
1756         sizes[ index ].width, sizes[ index ].height,
1757         kid -> core.border_width );
1758   }
1759 
1760 
1761   return;
1762 
1763 } /* DoLayout */
1764 
1765 
1766 /*----------------------------------------------------------------------*/
1767 
1768 static void
ExposeMonthDisplay(Widget widget,XEvent * event,Region region)1769   ExposeMonthDisplay( Widget  widget,
1770                       XEvent  *event,
1771                       Region  region )
1772 {
1773   /* Variables. */
1774   XmUbMonthDisplayWidget  md;
1775 
1776   /* Code. */
1777 
1778   md = (XmUbMonthDisplayWidget) widget;
1779 
1780   /* We don't need to draw anything, just call the month update callback the
1781      first time the widget is exposed. */
1782 
1783   if( !md -> md.exposed ){
1784     CallNewMonthCallbacks( md );
1785     md -> md.exposed = True;
1786   }
1787 
1788 
1789   return;
1790 
1791 } /* ExposeMonthDisplay */
1792 
1793 
1794 /*----------------------------------------------------------------------*/
1795 
1796 static XtGeometryResult
GeometryManager(Widget widget,XtWidgetGeometry * request,XtWidgetGeometry * reply)1797   GeometryManager( Widget            widget,
1798                    XtWidgetGeometry  *request,
1799                    XtWidgetGeometry  *reply )
1800 {
1801 
1802   XmUbMonthDisplayWidget  md;
1803   XtWidgetGeometry        own_request;
1804   Dimension               old_width, old_height;
1805   Dimension               pref_height;
1806   Dimension               pref_width;
1807   KidDimensionRec         kids_sizes[ NO_INTERNAL_CHILDREN ];
1808   XtGeometryResult        result;
1809 
1810   /* Code. */
1811 
1812   md = (XmUbMonthDisplayWidget) XtParent( widget );
1813 
1814   /* Find out how big the widget would be if the resize were allowed. */
1815   GetChildPrefSizes( md, NULL, request, kids_sizes );
1816   GetOwnPreferredSize( md, kids_sizes, &pref_width, &pref_height );
1817 
1818   /* If no change in dimensions, allow the request. */
1819   if( ( pref_width == md -> core.width ) &&
1820       ( pref_height == md -> core.height )){
1821     DoLayout( md, widget, request, kids_sizes );
1822     return XtGeometryYes;
1823   }
1824 
1825   /* We must ask our parent to resize us. */
1826   own_request.request_mode = CWWidth | CWHeight;
1827   own_request.width  = pref_width;
1828   own_request.height = pref_height;
1829 
1830   /* Save dimensions. */
1831   old_width  = md -> core.width;
1832   old_height = md -> core.height;
1833 
1834   md -> md.resize_called = False;
1835 
1836   /* We are not interested in any compromise geometry. */
1837   result = XtMakeGeometryRequest( (Widget) md, &own_request, NULL );
1838 
1839   /* Reset to old dimensions if request not granted. */
1840   if( result != XtGeometryYes ){
1841     md -> core.width  = old_width;
1842     md -> core.height = old_height;
1843 
1844   } else {
1845     if( !md -> md.resize_called )
1846       Resize( (Widget) md );
1847   }
1848 
1849 /* !!!!!!!!!!!!!!!!!!!!!! */
1850   /* Always grant child's request. */
1851   return XtGeometryYes;
1852 
1853 } /* GeometryManager */
1854 
1855 
1856 /*----------------------------------------------------------------------*/
1857 
1858 static void
GetChildPrefSizes(XmUbMonthDisplayWidget md,Widget initiator,XtWidgetGeometry * request,KidDimensionRec sizes[])1859   GetChildPrefSizes( XmUbMonthDisplayWidget  md,
1860                      Widget                  initiator,
1861                      XtWidgetGeometry        *request,
1862                      KidDimensionRec         sizes[] )
1863 {
1864   /* Variables. */
1865   XtWidgetGeometry  desired;
1866   int               index;
1867   Widget            kid;
1868 
1869   /* Code. */
1870 
1871   /* Initialize. */
1872   for( index = 0; index < NO_INTERNAL_CHILDREN; index ++ ){
1873     sizes[ index ].width  = 0;
1874     sizes[ index ].height = 0;
1875     sizes[ index ].x      = 0;
1876     sizes[ index ].y      = 0;
1877   }
1878 
1879   /* Get the preferred sizes for the children. */
1880   for( index = XmUbMD_FIRST_CHILD; index < NO_INTERNAL_CHILDREN; index ++ ){
1881 
1882     kid = md -> md.internal_children[ index ];
1883 
1884     if( ( kid != NULL ) && XtIsManaged( kid ) ){
1885 
1886       KidsPreferredGeometry( kid, initiator, request, &desired );
1887 
1888       sizes[ index ].width  = desired.width;
1889       sizes[ index ].height = desired.height;
1890 
1891     }
1892 
1893   } /* for */
1894 
1895 
1896   return;
1897 
1898 } /* GetChildPrefSizes */
1899 
1900 
1901 /*----------------------------------------------------------------------*/
1902 
1903 static void
GetOwnPreferredSize(XmUbMonthDisplayWidget md,KidDimensionRec sizes[],Dimension * pref_width,Dimension * pref_height)1904   GetOwnPreferredSize( XmUbMonthDisplayWidget  md,
1905                        KidDimensionRec         sizes[],
1906                        Dimension               *pref_width,
1907                        Dimension               *pref_height )
1908 {
1909   /* Code. */
1910 
1911   *pref_height = sizes[ XmUbMD_CHILD_TITLE ].height +
1912                  MAX( sizes[ XmUbMD_CHILD_ROW_COLUMN ].height,
1913                       sizes[ XmUbMD_CHILD_WEEK_RC ].height ) +
1914                  MAX( sizes[ XmUbMD_CHILD_YEAR_ARROW ].height,
1915                       sizes[ XmUbMD_CHILD_MONTH_ARROW ].height ) +
1916                  2 * md -> md.margin_height + md -> md.label_spacing +
1917                  ( ( md -> md.month_arrows || md -> md.year_arrows ) ?
1918                    ( sizes[ XmUbMD_CHILD_SEPARATOR ].height +
1919                      md -> md.arrow_spacing ) : 0 );
1920 
1921   *pref_width = MAX( MAX( sizes[ XmUbMD_CHILD_TITLE ].width,
1922                           sizes[ XmUbMD_CHILD_ROW_COLUMN ].width +
1923                           sizes[ XmUbMD_CHILD_WEEK_RC ].width ),
1924                      MAX( sizes[ XmUbMD_CHILD_YEAR_ARROW ].width,
1925                           sizes[ XmUbMD_CHILD_MONTH_ARROW ].width ) ) +
1926                 2 * md -> md.margin_width;
1927 
1928 
1929   return;
1930 
1931 } /* GetOwnPreferredSize */
1932 
1933 
1934 /*----------------------------------------------------------------------*/
1935 
1936 static void
GetValuesHook(Widget w,ArgList args,Cardinal * num_args)1937   GetValuesHook( Widget    w,
1938                  ArgList   args,
1939                  Cardinal  *num_args )
1940 {
1941   /* Variables. */
1942   int                     index;
1943   XmUbMonthDisplayWidget  md;
1944 
1945   /* Code. */
1946 
1947   md = (XmUbMonthDisplayWidget) w;
1948 
1949   /* Copy the XmStrings. */
1950   for( index = 0; index < *num_args; index ++ ){
1951 
1952     if( strcmp( args[ index ].name, XmUbNmdiMonthLabel ) == 0 ){
1953       * ( XmString *) ( args[ index ].value ) =
1954         XmStringCopy( md -> md.month_label );
1955 
1956     } else if( strcmp( args[ index ].name, XmUbNmdiWeekLabel ) == 0 ){
1957       * ( XmString *) ( args[ index ].value ) =
1958         XmStringCopy( md -> md.week_number_label );
1959 
1960     } else if( strcmp( args[ index ].name, XmUbNmdiYearLabel ) == 0 ){
1961       * ( XmString *) ( args[ index ].value ) =
1962         XmStringCopy( md -> md.year_label );
1963     }
1964 
1965   }
1966 
1967 
1968   return;
1969 
1970 } /* GetValuesHook */
1971 
1972 
1973 /*----------------------------------------------------------------------*/
1974 
1975 static void
Initialize(Widget treq,Widget tnew,ArgList args,Cardinal * num_args)1976   Initialize( Widget     treq,
1977               Widget     tnew,
1978               ArgList    args,
1979               Cardinal   *num_args )
1980 {
1981   /* Variables. */
1982   int                     index;
1983   KidDimensionRec         kids_sizes[ NO_INTERNAL_CHILDREN ];
1984   XmUbMonthDisplayWidget  new;
1985   Dimension               pref_height;
1986   Dimension               pref_width;
1987   XmString                xm;
1988 
1989   /* Code. */
1990 
1991   new = (XmUbMonthDisplayWidget) tnew;
1992 
1993   /* Initialize private fields. */
1994   /* Nullify all widget ids. */
1995   for( index = XmUbMD_FIRST_CHILD; index < NO_INTERNAL_CHILDREN; index ++ )
1996     new -> md.internal_children[ index ] = NULL;
1997   for( index = 0; index < NO_DAY_NAME_BUTTONS; index ++ )
1998     new -> md.day_name_buttons[ index ] = NULL;
1999   for( index = 0; index < NO_DAY_BUTTONS; index ++ )
2000     new -> md.day_number_buttons[ index ] = NULL;
2001   for( index = 0; index < NO_WEEK_NUMBER_BUTTONS; index ++ )
2002     new -> md.week_number_buttons[ index ] = NULL;
2003 
2004   new -> md.date_icon          = NULL;
2005   new -> md.date_icon_bm       = None;
2006   new -> md.date_icon_mask     = None;
2007   new -> md.inv_date_icon      = NULL;
2008   new -> md.inv_date_icon_bm   = None;
2009   new -> md.inv_date_icon_mask = None;
2010 
2011   new -> md.exposed = False;
2012 
2013   /* Start size if none supplied. */
2014   if( new -> core.width == 0 )
2015     new -> core.width = 300;
2016   else
2017     new -> md.recompute_width = False;
2018 
2019   if( new -> core.height == 0 )
2020     new -> core.height = 100;
2021   else
2022     new -> md.recompute_height = False;
2023 
2024   /* Copy XmStrings. */
2025   if( new -> md.month_label != NULL ){
2026     xm = XmStringCopy( new -> md.month_label );
2027     new -> md.month_label = xm;
2028   }
2029   if( new -> md.year_label != NULL ){
2030     xm = XmStringCopy( new -> md.year_label );
2031     new -> md.year_label = xm;
2032   }
2033   if( new -> md.week_number_label != NULL ){
2034     xm = XmStringCopy( new -> md.week_number_label );
2035     new -> md.week_number_label = xm;
2036   }
2037 
2038 
2039   /* Set defaults for current year and month. */
2040   if( new -> md.current_month == 0 )
2041     new -> md.current_month =
2042       TimIndexOfMonth( TimLocalTime( TimMakeTimeNow() ) );
2043 
2044   if( new -> md.current_year == 0 )
2045     new -> md.current_year =
2046       TimIndexOfYear( TimLocalTime( TimMakeTimeNow() ) );
2047 
2048   new -> md.first_date_index = 0;
2049 
2050 
2051   /* Create the internal widgets. */
2052   new -> md.internal_widgets_created = False;
2053 
2054   CreateInternalWidgets( new );
2055 
2056   new -> md.internal_widgets_created = True;
2057 
2058   /* Get the preferred dimensions of the widget. */
2059   GetChildPrefSizes( new, NULL, NULL, kids_sizes );
2060   GetOwnPreferredSize( new, kids_sizes, &pref_width, &pref_height );
2061 
2062   /* Set the desired size in the height and width fields. */
2063   new -> core.width  = pref_width;
2064   new -> core.height = pref_height;
2065 
2066 
2067   return;
2068 
2069 } /* Initialize */
2070 
2071 
2072 /*----------------------------------------------------------------------*/
2073 
2074 static void
InsertChild(Widget widget)2075   InsertChild( Widget  widget )
2076 {
2077 
2078   /* Variables. */
2079   Cardinal                num_params;
2080   String                  params[ 1 ];
2081   XmUbMonthDisplayWidget  md;
2082 
2083   /* Code. */
2084 
2085   md = (XmUbMonthDisplayWidget) XtParent( widget );
2086 
2087   /* We do not allow the application to create children. */
2088   if( md -> md.internal_widgets_created ){
2089 
2090     params[ 0 ] = XtClass( (Widget) md ) -> core_class.class_name;
2091     num_params  = 1;
2092     XtAppErrorMsg( XtWidgetToApplicationContext( widget ),
2093                    "childError", "number", "WidgetError",
2094                    "Applications cannot add children to %s widgets.",
2095                    params, &num_params );
2096   }
2097 
2098   /* This is an internal child. Adding it is OK. */
2099   (* ( (CompositeWidgetClass) (xmUbMonthDisplayWidgetClass ->
2100      core_class.superclass) ) -> composite_class.insert_child ) ( widget );
2101 
2102 
2103   return;
2104 
2105 } /* InsertChild */
2106 
2107 
2108 /*----------------------------------------------------------------------*/
2109 
2110 static void
KidsPreferredGeometry(Widget kid,Widget initiator,XtWidgetGeometry * request,XtWidgetGeometry * desired)2111   KidsPreferredGeometry( Widget            kid,
2112                          Widget            initiator,
2113                          XtWidgetGeometry  *request,
2114                          XtWidgetGeometry  *desired )
2115 {
2116 
2117   /* Code. */
2118 
2119   if( ( kid == initiator ) && ( request != NULL ) ){
2120     /* The initiator should not be queried. */
2121     if( request -> request_mode & CWWidth )
2122       desired -> width = request -> width;
2123     else
2124       desired -> width = (Dimension) kid -> core.width;
2125 
2126     if( request -> request_mode & CWHeight )
2127       desired -> height = request -> height;
2128     else
2129       desired -> height = (Dimension) kid -> core.height;
2130 
2131   } else
2132     (void) XtQueryGeometry( kid, NULL, desired );
2133 
2134 
2135   return;
2136 
2137 } /* KidsPreferredGeometry */
2138 
2139 
2140 /*----------------------------------------------------------------------*/
2141 
2142 static void
MonthScrolledCB(Widget pb,XmUbMonthDisplayWidget md,XmUbArrowLabelCallbackStruct * call_data)2143   MonthScrolledCB( Widget                        pb,
2144                    XmUbMonthDisplayWidget        md,
2145                    XmUbArrowLabelCallbackStruct  *call_data )
2146 {
2147   /* Variables. */
2148 
2149   /* Code. */
2150 
2151   switch( call_data -> reason ){
2152 
2153     case XmUbCR_BACK_ARROW_ACTIVATED:
2154       md -> md.current_month --;
2155       break;
2156 
2157     case XmUbCR_FORWARD_ARROW_ACTIVATED:
2158       md -> md.current_month ++;
2159       break;
2160 
2161     default:
2162       return;
2163   }
2164 
2165   if( md -> md.current_month > 12 ){
2166     md -> md.current_month = 1;
2167     md -> md.current_year ++;
2168 
2169   } else if(  md -> md.current_month < 1 ){
2170     md -> md.current_month = 12;
2171     md -> md.current_year --;
2172 
2173     if( md -> md.current_year < 1970 ){
2174       md -> md.current_year  = 1970;
2175       md -> md.current_month = 1;
2176     }
2177   }
2178 
2179 
2180   UpdateNewMonth( md );
2181   CallNewMonthCallbacks( md );
2182 
2183 
2184   return;
2185 
2186 } /* MonthScrolledCB */
2187 
2188 
2189 /*----------------------------------------------------------------------*/
2190 
2191 static void
Resize(Widget widget)2192   Resize( Widget    widget )
2193 {
2194   /* Variables. */
2195   KidDimensionRec         kids_sizes[ NO_INTERNAL_CHILDREN ];
2196   XmUbMonthDisplayWidget  md;
2197 
2198   /* Code. */
2199 
2200   md = (XmUbMonthDisplayWidget) widget;
2201 
2202   md -> md.resize_called = True;
2203 
2204   /* We have to get the preferred size of the children before we organize
2205      the layout. */
2206   GetChildPrefSizes( md, NULL, NULL, kids_sizes );
2207   DoLayout( md, NULL, NULL, kids_sizes );
2208 
2209 
2210   return;
2211 
2212 } /* Resize */
2213 
2214 
2215 /*----------------------------------------------------------------------*/
2216 
2217 static Boolean
ResizeIfNeeded(XmUbMonthDisplayWidget md,KidDimensionRec sizes[])2218   ResizeIfNeeded( XmUbMonthDisplayWidget  md,
2219                   KidDimensionRec         sizes[] )
2220 {
2221 
2222   /* Variables. */
2223   Boolean           layout_done;
2224   Dimension         pref_height;
2225   Dimension         pref_width;
2226   XtWidgetGeometry  request;
2227   XtGeometryResult  result;
2228 
2229   /* Code. */
2230 
2231   /* Initialize. */
2232   layout_done = False;
2233 
2234   /* Get the preferred dimensions of the widget. */
2235   GetChildPrefSizes( md, NULL, NULL, sizes );
2236   GetOwnPreferredSize( md, sizes, &pref_width, &pref_height );
2237 
2238   /* If we want the same dimensions, no resizing is needed. */
2239   if(( pref_width  == md -> core.width ) &&
2240      ( pref_height == md -> core.height ))
2241     return False;
2242 
2243   /* Dimensions are different. Try to resize. */
2244   request.request_mode = CWWidth | CWHeight;
2245 
2246   request.width  = pref_width;
2247   request.height = pref_height;
2248 
2249   md -> md.resize_called = False;
2250 
2251   do {
2252 
2253     result = XtMakeGeometryRequest( (Widget) md, &request, &request );
2254 
2255   } while( result == XtGeometryAlmost );
2256 
2257   if( result == XtGeometryNo )
2258     return False;
2259 
2260   /* Resize done. Core fields have already been updated. */
2261   return( md -> md.resize_called );
2262 
2263 } /* ResizeIfNeeded */
2264 
2265 
2266 /*----------------------------------------------------------------------*/
2267 
2268 static XtGeometryResult
QueryGeometry(Widget widget,XtWidgetGeometry * proposed,XtWidgetGeometry * answer)2269   QueryGeometry( Widget             widget,
2270                  XtWidgetGeometry  *proposed,
2271                  XtWidgetGeometry  *answer )
2272 {
2273 
2274   KidDimensionRec         kids_sizes[ NO_INTERNAL_CHILDREN ];
2275   XmUbMonthDisplayWidget  md;
2276   Dimension               pref_height;
2277   Dimension               pref_width;
2278 
2279   /* Code. */
2280 
2281   md = (XmUbMonthDisplayWidget) widget;
2282 
2283   /* Get dimensions that we *really* want. */
2284   GetChildPrefSizes( md, NULL, NULL, kids_sizes );
2285   GetOwnPreferredSize( md, kids_sizes, &pref_width, &pref_height );
2286 
2287   answer -> request_mode = CWWidth | CWHeight;
2288   answer -> width  = pref_width;
2289   answer -> height = pref_height;
2290 
2291 
2292   if( proposed == NULL ){
2293     /* This is a query for the requested geometry. */
2294 
2295     if(( answer -> height == (int) md -> core.height ) &&
2296        ( answer -> width  == (int) md -> core.width ))
2297       return XtGeometryNo;
2298     else
2299       return XtGeometryAlmost;
2300   }
2301 
2302   /* The parent supplied a geometry suggestion. */
2303   if(( answer -> height == proposed -> height ) &&
2304      ( answer -> width  == proposed -> width ))
2305     return XtGeometryYes;
2306 
2307   if( ( proposed -> height <= 1 ) ||
2308       ( proposed -> width  <= 1 ) )
2309     /* That's too small ! */
2310     return XtGeometryNo;
2311 
2312 
2313   /* Only a compromise left. */
2314   return XtGeometryAlmost;
2315 
2316 } /* QueryGeometry */
2317 
2318 
2319 /*----------------------------------------------------------------------*/
2320 
2321 static void
SetDayNames(XmUbMonthDisplayWidget md)2322   SetDayNames( XmUbMonthDisplayWidget  md )
2323 {
2324   /* Variables. */
2325   Arg           args[ 2 ];
2326   char          day_name_buffer[ LABEL_BUFFER_LENGTH ];
2327   int           first_day_index;
2328   int           index;
2329   char          label_buffer[ LABEL_BUFFER_LENGTH ];
2330   Cardinal      n;
2331   XmString      old_xm;
2332   TIM_TIME_REF  time;
2333   XmString      xm;
2334 
2335   /* Code. */
2336 
2337   /* The week title. */
2338   if( md -> md.week_numbers ){
2339 
2340     n = 0;
2341     XtSetArg( args[ n ], XmNlabelString, &old_xm ); n++;
2342     XtGetValues( md -> md.week_number_buttons[ 0 ], args, n );
2343 
2344     if( ! XmStringCompare( old_xm, md -> md.week_number_label ) ){
2345       n = 0;
2346       XtSetArg( args[ n ], XmNlabelString, md -> md.week_number_label ); n++;
2347       XtSetArg( args[ n ], XmNalignment, XmALIGNMENT_CENTER ); n++;
2348       XtSetValues( md -> md.week_number_buttons[ 0 ], args, n );
2349     }
2350   }
2351 
2352 
2353   /* The day names. */
2354 
2355   first_day_index = TimIndexOfFirstDayInWeek();
2356 
2357   /* We need day names from the locale, so create a real time we can
2358      play with. */
2359 
2360   time = TimMakeTimeNow();
2361 
2362   /* first_day_index     : 0 = Sunday, 1 = Monday. */
2363   /* TimIndexOfDayInWeek : first day in week = 1. */
2364 
2365   /* Step forwards until we are on the first day of the week. */
2366   while( TimIndexOfDayInWeek( time ) != 1 )
2367     TimAddDays( &time, 1 );
2368 
2369   /* We are on the first day of a week. */
2370   for( index = 0; index < NO_DAY_NAME_BUTTONS; index ++ ){
2371 
2372     TimFormatStrTime( time, "%a", label_buffer, LABEL_BUFFER_LENGTH - 1 );
2373 
2374     if( md -> md.day_name_characters > 0 ){
2375       strncpy( day_name_buffer, label_buffer,
2376                MIN( md -> md.day_name_characters, LABEL_BUFFER_LENGTH ) );
2377       day_name_buffer[
2378         MIN( md -> md.day_name_characters, LABEL_BUFFER_LENGTH ) ] = '\0';
2379     } else
2380       strcpy( day_name_buffer, label_buffer );
2381 
2382     xm = XmStringCreateLtoR( day_name_buffer, XmSTRING_DEFAULT_CHARSET );
2383 
2384     /* Get old string and compare to see if we need to change. */
2385     n = 0;
2386     XtSetArg( args[ n ], XmNlabelString, &old_xm ); n++;
2387     XtGetValues( md -> md.day_name_buttons[ index ], args, n );
2388 
2389     if( ! XmStringCompare( old_xm, xm ) ){
2390       n = 0;
2391       XtSetArg( args[ n ], XmNlabelString, xm ); n++;
2392       XtSetArg( args[ n ], XmNalignment, XmALIGNMENT_CENTER ); n++;
2393       XtSetValues( md -> md.day_name_buttons[ index ], args, n );
2394     }
2395 
2396     XmStringFree( xm );
2397 
2398     /* Next day. */
2399     TimAddDays( &time, 1 );
2400 
2401   }
2402 
2403 
2404   return;
2405 
2406 } /* SetDayNames */
2407 
2408 
2409 /*----------------------------------------------------------------------*/
2410 
2411 static Boolean
SetValues(Widget current,Widget request,Widget new,ArgList args,Cardinal * num_args)2412   SetValues( Widget     current,
2413              Widget     request,
2414              Widget     new,
2415              ArgList    args,
2416              Cardinal   *num_args )
2417 {
2418 #ifdef Differs
2419 #undef Differs
2420 #endif
2421 
2422 #define Differs( field )  ( curW -> field != newW -> field )
2423 
2424   /* Variables. */
2425   XmUbMonthDisplayWidget  curW;
2426   Boolean                 do_layout = False;
2427   Boolean                 fill;
2428   int                     index;
2429   Arg                     local_args[ 3 ];
2430   Cardinal                n;
2431   Boolean                 new_fill;
2432   XmUbMonthDisplayWidget  newW;
2433   Boolean                 redisplay = False;
2434   Cardinal                saved_n;
2435   Boolean                 update_month = False;
2436   Boolean                 visual_changed = False;
2437   XmString                xm;
2438 
2439   /* Code. */
2440 
2441   curW = (XmUbMonthDisplayWidget) current;
2442   newW = (XmUbMonthDisplayWidget) new;
2443 
2444   /* Width and height. */
2445   /* Resizing is handled higher up. */
2446 
2447   if( Differs( md.recompute_width ) && newW -> md.recompute_width )
2448     visual_changed = True;
2449   else if( Differs( core.width ) )
2450     newW -> md.recompute_width = False;
2451 
2452   if( Differs( md.recompute_height ) && newW -> md.recompute_height )
2453     visual_changed = True;
2454   else if( Differs( core.height ) )
2455     newW -> md.recompute_height = False;
2456 
2457   /* Margins and spacings. */
2458   if( Differs( md.margin_width )  ||
2459       Differs( md.margin_height ) ||
2460       Differs( md.label_spacing ) ||
2461       Differs( md.arrow_spacing ) )
2462     visual_changed = True;
2463 
2464   /* These resources may only be set at creation. */
2465   if( Differs( md.enable_separator ) ){
2466     WarningNoResourceChange( newW, "XmUbNmdiEnableSeparator" );
2467     newW -> md.enable_separator = curW -> md.enable_separator;
2468   }
2469   if( Differs( md.month_arrows ) ){
2470     WarningNoResourceChange( newW, "XmUbNmdiMonthArrows" );
2471     newW -> md.month_arrows = curW -> md.month_arrows;
2472   }
2473   if( Differs( md.year_arrows ) ){
2474     WarningNoResourceChange( newW, "XmUbNmdiYearArrows" );
2475     newW -> md.year_arrows = curW -> md.year_arrows;
2476   }
2477   if( Differs( md.week_numbers ) ){
2478     WarningNoResourceChange( newW, "XmUbNmdiWeekNumbers" );
2479     newW -> md.week_numbers = curW -> md.week_numbers;
2480   }
2481   if( Differs( md.day_name_characters ) ){
2482     WarningNoResourceChange( newW, "XmUbNmdiDayChars" );
2483     newW -> md.day_name_characters = curW -> md.day_name_characters;
2484   }
2485   if( Differs( md.week_number_label ) ){
2486     WarningNoResourceChange( newW, "XmUbNmdiWeekLabel" );
2487     newW -> md.week_number_label = curW -> md.week_number_label;
2488   }
2489 
2490   /* These resources affect child widgets. */
2491   if( Differs( md.use_default_title_callback ) ||
2492       Differs( md.title_callback ) ){
2493 
2494     /* We may have to change the resources for the title bar. */
2495     n = 0;
2496     XtSetArg( local_args[ n ], XmNfillOnArm, &fill ); n++;
2497     XtGetValues( newW -> md.internal_children[ XmUbMD_CHILD_TITLE ],
2498                  local_args, n );
2499 
2500     new_fill = newW -> md.use_default_title_callback ||
2501                ( newW -> md.title_callback != NULL );
2502 
2503     if( fill != new_fill ){
2504       n = 0;
2505       XtSetArg( local_args[ n ], XmNfillOnArm, new_fill ); n++;
2506       XtSetValues( newW -> md.internal_children[ XmUbMD_CHILD_TITLE ],
2507                    local_args, n );
2508     }
2509   }
2510 
2511   if( Differs( md.week_number_label ) ){
2512 
2513     if( curW -> md.week_number_label != NULL )
2514       XmStringFree( curW -> md.week_number_label );
2515 
2516     if( newW -> md.week_number_label != NULL ){
2517       xm = XmStringCopy( newW -> md.week_number_label );
2518       newW -> md.week_number_label = xm;
2519     }
2520 
2521     update_month = True;
2522   }
2523 
2524   if( Differs( md.month_label )     ||
2525       Differs( md.year_label )      ||
2526       Differs( manager.foreground ) ||
2527       Differs( core.background_pixel ) ){
2528 
2529     n = 0;
2530 
2531     if( Differs( manager.foreground ) ){
2532       XtSetArg( local_args[ n ], XmNforeground,
2533                                  newW -> manager.foreground ); n++;
2534     }
2535     if( Differs( core.background_pixel ) ){
2536       XtSetArg( local_args[ n ], XmNbackground,
2537                                  newW -> core.background_pixel ); n++;
2538 
2539       /* The background was changed. We must recalculate shadow colors. */
2540       XmGetColors( XtScreen( (Widget) newW ), newW -> core.colormap,
2541                    newW -> core.background_pixel, NULL,
2542                    & newW -> md.pushb_default_topshadow,
2543                    & newW -> md.pushb_default_bottomshadow, NULL );
2544     }
2545 
2546     /* The pushbuttons are only affected by the change in colors. */
2547     if( n != 0 ){
2548       XtSetValues( newW -> md.internal_children[ XmUbMD_CHILD_TITLE ],
2549                    local_args, n );
2550       if( newW -> md.week_numbers )
2551         XtSetValues( newW -> md.week_number_buttons[ 0 ], local_args, n );
2552 
2553       for( index = 0; index < NO_DAY_NAME_BUTTONS; index ++ )
2554         XtSetValues( newW -> md.day_name_buttons[ index ], local_args, n );
2555 
2556       update_month = True;
2557     }
2558 
2559     saved_n = n;
2560 
2561     if( Differs( md.month_label ) ){
2562       if( curW -> md.month_label != NULL )
2563         XmStringFree( curW -> md.month_label );
2564 
2565       if( newW -> md.month_label != NULL ){
2566         xm = XmStringCopy( newW -> md.month_label );
2567         newW -> md.month_label = xm;
2568       }
2569 
2570       XtSetArg( local_args[ n ], XmNlabelString, newW -> md.month_label ); n++;
2571     }
2572     if( n != 0 )
2573       XtSetValues( newW -> md.internal_children[ XmUbMD_CHILD_MONTH_ARROW ],
2574                    local_args, n );
2575 
2576     n = saved_n;
2577     if( Differs( md.year_label ) ){
2578 
2579       if( curW -> md.year_label != NULL )
2580         XmStringFree( curW -> md.year_label );
2581 
2582       if( newW -> md.year_label != NULL ){
2583         xm = XmStringCopy( newW -> md.year_label );
2584         newW -> md.year_label = xm;
2585       }
2586 
2587       XtSetArg( local_args[ n ], XmNlabelString, newW -> md.year_label ); n++;
2588     }
2589     if( n != 0 )
2590       XtSetValues( newW -> md.internal_children[ XmUbMD_CHILD_YEAR_ARROW ],
2591                    local_args, n );
2592 
2593   }
2594 
2595 
2596   if( Differs( md.current_year )           ||
2597       Differs( md.current_month )          ||
2598       Differs( md.fill_out_week )          ||
2599       Differs( md.weekday_foreground )     ||
2600       Differs( md.sun_foreground )         ||
2601       Differs( md.sat_foreground )         ||
2602       Differs( md.today_foreground )       ||
2603       Differs( md.other_month_foreground ) ||
2604       Differs( md.week_number_foreground ) )
2605     update_month = True;
2606 
2607   if( Differs( md.title_alignment ) )
2608     do_layout = True;
2609 
2610 
2611   if( update_month ){
2612     UpdateNewMonth( newW );
2613     CallNewMonthCallbacks( newW );
2614   }
2615 
2616   if( visual_changed || do_layout ){
2617 
2618     KidDimensionRec  kids_sizes[ NO_INTERNAL_CHILDREN ];
2619     Boolean          resized;
2620 
2621     /* Code. */
2622 
2623     if( visual_changed )
2624       resized = ResizeIfNeeded( newW, kids_sizes );
2625     else
2626       resized = False;
2627 
2628     /* If the widget was resized, the layout has already been done. */
2629     if( !resized )
2630       DoLayout( newW, NULL, NULL, kids_sizes );
2631 
2632   }
2633 
2634   return( redisplay || visual_changed || do_layout || update_month );
2635 
2636 #undef Differs
2637 
2638 } /* SetValues */
2639 
2640 
2641 /*----------------------------------------------------------------------*/
2642 
2643 #if XmVersion > 1001
2644 
2645 static void
StartDateDrag(Widget w,XEvent * event,String * params,Cardinal num_params)2646   StartDateDrag( Widget    w,
2647                  XEvent    *event,
2648                  String    *params,
2649                  Cardinal  num_params )
2650 {
2651   /* Variables. */
2652   Arg                     args[ 8 ];
2653   Atom                    compound_text_atom;
2654   Atom                    date_transfer_atom;
2655   Widget                  drag_context;
2656   Atom                    exportList[ 2 ];
2657   XmUbMonthDisplayWidget  md;
2658   Cardinal                n;
2659   Widget                  tmp_widget;
2660 
2661   /* Code. */
2662 
2663   compound_text_atom = XmInternAtom( XtDisplay( w ), "COMPOUND_TEXT", False );
2664   date_transfer_atom = XmInternAtom( XtDisplay( w ), XmUbDATE_TRANSFER,
2665                                      False );
2666 
2667   /* Establish the list of valid target types. */
2668   exportList[ 0 ] = date_transfer_atom;
2669   exportList[ 1 ] = compound_text_atom;
2670 
2671   tmp_widget = XtParent( w );
2672   while( ! XtIsSubclass( tmp_widget, xmUbMonthDisplayWidgetClass ) )
2673     tmp_widget = XtParent( tmp_widget );
2674   md = (XmUbMonthDisplayWidget) tmp_widget;
2675 
2676   /* Create the drag icon if it doesn't exist. */
2677   md -> md.internal_widgets_created = False;
2678 
2679   if( md -> md.date_icon == NULL ){
2680 
2681     if( md -> md.date_icon_bm == None )
2682       md -> md.date_icon_bm = XCreateBitmapFromData(
2683         XtDisplay( w ), XtWindow( w ),
2684         (char*) DateDragIcon_bits, DateDragIcon_width, DateDragIcon_height );
2685 
2686     if( md -> md.date_icon_mask == None )
2687       md -> md.date_icon_mask = XCreateBitmapFromData(
2688         XtDisplay( w ), XtWindow( w ),
2689         (char*) DateDragMask_bits, DateDragMask_width, DateDragMask_height );
2690 
2691     n = 0;
2692     XtSetArg( args[ n ], XmNmask, md -> md.date_icon_mask ); n++;
2693     XtSetArg( args[ n ], XmNpixmap, md -> md.date_icon_bm ); n++;
2694     XtSetArg( args[ n ], XmNdepth, 1 ); n++;
2695     XtSetArg( args[ n ], XmNwidth, DateDragIcon_width ); n++;
2696     XtSetArg( args[ n ], XmNheight, DateDragIcon_height ); n++;
2697     md -> md.date_icon = XmCreateDragIcon( (Widget) md, "dragIcon", args, n );
2698   }
2699 
2700   if( md -> md.inv_date_icon == NULL ){
2701 
2702     if( md -> md.inv_date_icon_bm == None )
2703       md -> md.inv_date_icon_bm = XCreateBitmapFromData(
2704         XtDisplay( w ), XtWindow( w ),
2705         (char*) DateDragInvIcon_bits, DateDragInvIcon_width,
2706         DateDragInvIcon_height );
2707 
2708     if( md -> md.inv_date_icon_mask == None )
2709       md -> md.inv_date_icon_mask = XCreateBitmapFromData(
2710         XtDisplay( w ), XtWindow( w ),
2711         (char*) DateDragInvIconMask_bits, DateDragInvIconMask_width,
2712         DateDragInvIconMask_height );
2713 
2714     n = 0;
2715     XtSetArg( args[ n ], XmNmask, md -> md.inv_date_icon_mask ); n++;
2716     XtSetArg( args[ n ], XmNpixmap, md -> md.inv_date_icon_bm ); n++;
2717     XtSetArg( args[ n ], XmNdepth, 1 ); n++;
2718     XtSetArg( args[ n ], XmNwidth, DateDragInvIcon_width ); n++;
2719     XtSetArg( args[ n ], XmNheight, DateDragInvIcon_height ); n++;
2720     md -> md.inv_date_icon = XmCreateDragIcon( (Widget) md, "invDragIcon",
2721                                                args, n );
2722   }
2723 
2724   md -> md.internal_widgets_created = True;
2725 
2726   n = 0;
2727   XtSetArg( args[ n ], XmNexportTargets, exportList ); n++;
2728   XtSetArg( args[ n ], XmNnumExportTargets, 2 ); n++;
2729   XtSetArg( args[ n ], XmNdragOperations, XmDROP_COPY ); n++;
2730   XtSetArg( args[ n ], XmNconvertProc, DateDragConvertProc ); n++;
2731   XtSetArg( args[ n ], XmNclientData, (XtPointer) w ); n++;
2732   XtSetArg( args[ n ], XmNsourcePixmapIcon, md -> md.inv_date_icon ); n++;
2733   XtSetArg( args[ n ], XmNsourceCursorIcon, md -> md.inv_date_icon ); n++;
2734 
2735   drag_context = XmDragStart( w, event, args, n );
2736 
2737   /* Handle custom visual effects. */
2738   XtAddCallback( drag_context, XmNdropSiteEnterCallback,
2739                  (XtCallbackProc) DateEnterDropSiteCB, (XtPointer) md );
2740   XtAddCallback( drag_context, XmNdropSiteLeaveCallback,
2741                  (XtCallbackProc) DateLeaveDropSiteCB, (XtPointer) md );
2742 
2743 
2744   return;
2745 
2746 } /* StartDateDrag */
2747 
2748 #endif
2749 
2750 /*----------------------------------------------------------------------*/
2751 
2752 static void
TitleBarPressedCB(Widget pb,XmUbMonthDisplayWidget md,XmPushButtonCallbackStruct * call_data)2753   TitleBarPressedCB( Widget                      pb,
2754                      XmUbMonthDisplayWidget      md,
2755                      XmPushButtonCallbackStruct  *call_data )
2756 {
2757   /* Variables. */
2758   XmUbMonthDisplayCallbackStruct  cb;
2759   int                             old_month;
2760   int                             old_year;
2761   TIM_TIME_REF                    time;
2762 
2763   /* Code. */
2764 
2765   /* Save current year and month for later. */
2766   old_month = md -> md.current_month;
2767   old_year  = md -> md.current_year;
2768 
2769   /* Default action ? */
2770   if( md -> md.use_default_title_callback ){
2771 
2772     /* Set current year and month. */
2773 
2774     time = TimLocalTime( TimMakeTimeNow() );
2775 
2776     /* Set the current year and month. */
2777     md -> md.current_month = TimIndexOfMonth( time );
2778     md -> md.current_year  = TimIndexOfYear( time );
2779   }
2780 
2781   /* Call user's callbacks. */
2782   if( md -> md.title_callback != NULL ){
2783 
2784     /* Callbacks are defined. */
2785     /* Set up the callback structure. */
2786     cb.reason         = XmUbCR_TITLE_PRESSED;
2787     cb.event          = call_data -> event;
2788     cb.selected_month = md -> md.current_month;
2789     cb.selected_year  = md -> md.current_year;
2790 
2791     /* Call the user callbacks. */
2792     XtCallCallbackList( (Widget) md, md -> md.title_callback,
2793                         (XtPointer) &cb );
2794   }
2795 
2796   /* If the month or year was changed, we should update the display. */
2797   if( ( old_month != md -> md.current_month ) ||
2798       ( old_year  != md -> md.current_year ) ){
2799     UpdateNewMonth( md );
2800     CallNewMonthCallbacks( md );
2801   }
2802 
2803 
2804   return;
2805 
2806 } /* TitleBarPressedCB */
2807 
2808 
2809 /*----------------------------------------------------------------------*/
2810 
2811 static void
UpdateDayButton(XmUbMonthDisplayWidget md,int index,int date,XmUbWhichMonth which_month)2812   UpdateDayButton( XmUbMonthDisplayWidget  md,
2813                    int                     index,
2814                    int                     date,
2815                    XmUbWhichMonth          which_month )
2816 {
2817   /* Variables. */
2818   Arg                             args[ 10 ];
2819   XmUbMdiUpdateDayCallbackStruct  cb;
2820   char                            label_buffer[ 20 ];
2821   Cardinal                        n;
2822   TIM_TIME_REF                    now;
2823   int                             old_date;
2824   Pixel                           old_fg, old_bg, old_top, old_bottom;
2825   Boolean                         old_mapped;
2826   TIM_TIME_REF                    time;
2827   int                             user_data = -1;
2828   Widget                          w;
2829   XmString                        xm = NULL;
2830 
2831   /* Code. */
2832 
2833   w = md -> md.day_number_buttons[ index ];
2834 
2835   /* Get the current values. */
2836 
2837   n = 0;
2838   XtSetArg( args[ n ], XmNuserData, &old_date ); n++;
2839   XtSetArg( args[ n ], XmNforeground, &old_fg ); n++;
2840   XtSetArg( args[ n ], XmNbackground, &old_bg ); n++;
2841   XtSetArg( args[ n ], XmNtopShadowColor, &old_top ); n++;
2842   XtSetArg( args[ n ], XmNbottomShadowColor, &old_bottom ); n++;
2843   XtSetArg( args[ n ], XmNmappedWhenManaged, &old_mapped ); n++;
2844   XtGetValues( w, args, n );
2845 
2846   /* Fill in the callback structure. Can be used also if no callback. */
2847   cb.reason     = XmUbCR_UPDATE_DAY;
2848   cb.event      = NULL;
2849   cb.day        = date;
2850   cb.loop_index = index;
2851 
2852   switch( which_month ){
2853 
2854     case XmUbCURRENT_MONTH:
2855       cb.month = md -> md.current_month;
2856       cb.year  = md -> md.current_year;
2857       break;
2858 
2859     case XmUbPREVIOUS_MONTH:
2860       cb.month = md -> md.current_month - 1;
2861       cb.year  = md -> md.current_year;
2862 
2863       if( cb.month < 1 ){
2864         cb.month = 12;
2865         cb.year --;
2866       }
2867 
2868       break;
2869 
2870     case XmUbNEXT_MONTH:
2871       cb.month = md -> md.current_month + 1;
2872       cb.year  = md -> md.current_year;
2873 
2874       if( cb.month > 12 ){
2875         cb.month = 1;
2876         cb.year ++;
2877       }
2878 
2879       break;
2880   }
2881 
2882   time = TimMakeTime( cb.year, cb.month, cb.day, 0, 0, 0 );
2883 
2884   cb.weekday = TimIndexOfDayInWeek( time );
2885   if( TimIndexOfFirstDayInWeek() == 0 )
2886     cb.weekday --;
2887   if( cb.weekday == 0 )
2888     cb.weekday = 7;
2889 
2890   cb.day_num_in_year = TimIndexOfDayInYear( time );
2891   cb.week_number     = TimIndexOfWeek( time );
2892   cb.foreground      = old_fg;
2893   cb.background      = old_bg;
2894   cb.frame           = old_top;
2895   cb.mapped          = old_mapped;
2896   cb.use_shadows     = False;
2897 
2898   /* Check if the day displayed is "today". */
2899   now = TimLocalTime( TimMakeTimeNow() );
2900   if( ( TimIndexOfDay( time )   == TimIndexOfDay( now ) ) &&
2901       ( TimIndexOfMonth( time ) == TimIndexOfMonth( now ) ) &&
2902       ( TimIndexOfYear( time )  == TimIndexOfYear( now ) ) )
2903     cb.today = True;
2904   else
2905     cb.today = False;
2906 
2907 
2908   /* For dates outside the current month, other_month resource overrides. */
2909   if( which_month != XmUbCURRENT_MONTH ){
2910 
2911     cb.default_foreground = md -> md.other_month_foreground;
2912     cb.default_background = md -> core.background_pixel;
2913     cb.default_frame      = md -> core.background_pixel;
2914     cb.default_mapped     = md -> md.fill_out_week;
2915 
2916   } else {
2917     /* This is a date in the current month. */
2918 
2919     if( cb.today )
2920       cb.default_foreground = md -> md.today_foreground;
2921 
2922     else if( cb.weekday == 7 )
2923       cb.default_foreground = md -> md.sun_foreground;
2924 
2925     else if( cb.weekday == 6 )
2926       cb.default_foreground = md -> md.sat_foreground;
2927 
2928     else
2929       cb.default_foreground = md -> md.weekday_foreground;
2930 
2931     cb.default_mapped = True;
2932   }
2933 
2934   cb.default_background = md -> core.background_pixel;
2935   cb.default_frame      = md -> core.background_pixel;
2936   cb.which_month        = which_month;
2937 
2938   if( md -> md.update_day_callback ){
2939     /* Let the user determine what should be displayed. */
2940 
2941     XtCallCallbackList( (Widget) md, md -> md.update_day_callback,
2942                         (XtPointer) &cb );
2943 
2944   } else {
2945     /* We should display the defaults. */
2946     cb.foreground = cb.default_foreground;
2947     cb.background = cb.default_background;
2948     cb.frame      = cb.default_frame;
2949     cb.mapped     = cb.default_mapped;
2950   }
2951 
2952   /* Set the values. */
2953   n = 0;
2954 
2955   if( cb.foreground != old_fg ){
2956     XtSetArg( args[ n ], XmNforeground, cb.foreground ); n++;
2957   }
2958   if( cb.background != old_bg ){
2959     XtSetArg( args[ n ], XmNbackground, cb.background ); n++;
2960   }
2961 
2962   if( ! cb.use_shadows ){
2963     if( cb.frame != old_top ){
2964       XtSetArg( args[ n ], XmNtopShadowColor, cb.frame ); n++;
2965       XtSetArg( args[ n ], XmNbottomShadowColor, cb.frame ); n++;
2966     }
2967 
2968   } else {
2969     /* Pushbutton shadows on button. */
2970 
2971     if( old_top != md -> md.pushb_default_topshadow ){
2972       XtSetArg( args[ n ], XmNtopShadowColor,
2973                            md -> md.pushb_default_topshadow ); n++;
2974     }
2975     if( old_bottom != md -> md.pushb_default_bottomshadow ){
2976       XtSetArg( args[ n ], XmNbottomShadowColor,
2977                            md -> md.pushb_default_bottomshadow ); n++;
2978     }
2979   }
2980 
2981   if( cb.mapped != old_mapped ){
2982     XtSetArg( args[ n ], XmNmappedWhenManaged, cb.mapped ); n++;
2983   }
2984 
2985   /* If we are lucky, we don't need to change the text... */
2986   if( ( old_date % 100 ) != date ){
2987     sprintf( label_buffer, "%d", date );
2988     xm = XmStringCreateLtoR( label_buffer, XmSTRING_DEFAULT_CHARSET );
2989 
2990     XtSetArg( args[ n ], XmNlabelString, xm ); n++;
2991 
2992     switch( which_month ){
2993 
2994       case XmUbCURRENT_MONTH:
2995         user_data = date;
2996         break;
2997 
2998       case XmUbPREVIOUS_MONTH:
2999         user_data = date + PREVIOUS_MONTH_OFFSET;
3000         break;
3001 
3002       case XmUbNEXT_MONTH:
3003         user_data = date + NEXT_MONTH_OFFSET;
3004         break;
3005     }
3006     assert( user_data != -1 );
3007 
3008     XtSetArg( args[ n ], XmNuserData, user_data ); n++;
3009   }
3010 
3011   /* Update the button. */
3012   if( n > 0 )
3013     XtSetValues( w, args, n );
3014 
3015   /* Cleanup. */
3016   if( xm != NULL )
3017     XmStringFree( xm );
3018 
3019 
3020   return;
3021 
3022 } /* UpdateDayButton */
3023 
3024 
3025 /*----------------------------------------------------------------------*/
3026 
3027 static void
UpdateNewMonth(XmUbMonthDisplayWidget md)3028   UpdateNewMonth( XmUbMonthDisplayWidget  md )
3029 {
3030   /* Variables. */
3031   Arg           args[ 8 ];
3032   int           day_number;
3033   int           days_in_month;
3034   int           first_date_index;
3035   int           index;
3036   char          label_buffer[ LABEL_BUFFER_LENGTH ];
3037   Boolean       mapped;
3038   int           month_number;
3039   Cardinal      n;
3040   TIM_TIME_REF  time;
3041   TIM_TIME_REF  time_of_first_date;
3042   int           year_number;
3043   XmString      xm;
3044 
3045   /* Code. */
3046 
3047   /* Title text. */
3048 
3049   time_of_first_date = TimMakeTime( md -> md.current_year,
3050                                     md -> md.current_month, 1, 0, 0, 0 );
3051 
3052   TimFormatStrTime( time_of_first_date, "%B %Y", label_buffer,
3053                     LABEL_BUFFER_LENGTH - 1 );
3054 
3055   xm = XmStringCreateLtoR( label_buffer, XmSTRING_DEFAULT_CHARSET );
3056 
3057   n = 0;
3058   XtSetArg( args[ n ], XmNlabelString, xm ); n++;
3059   XtSetValues( md -> md.internal_children[ XmUbMD_CHILD_TITLE ], args, n );
3060   XmStringFree( xm );
3061 
3062   /* The day names or the week title may have to be changed. */
3063   SetDayNames( md );
3064 
3065   /* Set the day numbers. */
3066 
3067   /* Find out on which index we should start. */
3068   /* first_day_index     : 0 = Sunday, 1 = Monday. */
3069   /* TimIndexOfDayInWeek : 1 for the first day of the week. */
3070 
3071   first_date_index = TimIndexOfDayInWeek( time_of_first_date ) - 1;
3072 
3073   /* If no days from the previous month are displayed, we should step back a
3074      week and display the last week of the previous month. */
3075   if( ( md -> md.fill_out_week ) && ( first_date_index == 0 ) )
3076     first_date_index += 7;
3077 
3078   md -> md.first_date_index = first_date_index;
3079 
3080   /* Set the days in the preceding month. */
3081   time = time_of_first_date;
3082   TimAddDays( &time, -1 );
3083   days_in_month = TimDaysInMonth( time );
3084 
3085   for( index = 0, day_number = days_in_month - first_date_index + 1;
3086        index < first_date_index;
3087        index ++, day_number ++ )
3088     UpdateDayButton( md, index, day_number, XmUbPREVIOUS_MONTH );
3089 
3090 
3091   /* The current month. */
3092   time = time_of_first_date;
3093   days_in_month = TimDaysInMonth( time );
3094 
3095   for( index = first_date_index, day_number = 1;
3096        day_number <= days_in_month;
3097        index ++, day_number ++ )
3098     UpdateDayButton( md, index, day_number, XmUbCURRENT_MONTH );
3099 
3100   /* Fill out with the following month. */
3101   for( day_number = 1; index < NO_DAY_BUTTONS; index ++, day_number ++ )
3102     UpdateDayButton( md, index, day_number, XmUbNEXT_MONTH );
3103 
3104   /* Update the week numbers. */
3105   if( md -> md.week_numbers ){
3106 
3107     /* For every week, display the week number of the first day. */
3108     /* Converting to the time handles all problems when switching year. */
3109     for( index = 1; index < NO_WEEK_NUMBER_BUTTONS; index ++ ){
3110 
3111       ButtonDate( md, md -> md.day_number_buttons[ ( index - 1 ) * 7 ],
3112                   &year_number, &month_number, &day_number );
3113 
3114       time = TimMakeTime( year_number, month_number, day_number, 0, 0, 0 );
3115 
3116       /* We don't want to display week numbers for empty weeks. */
3117       if( ! md -> md.fill_out_week &&
3118           ( month_number != md -> md.current_month ) &&
3119           ( year_number >= md -> md.current_year ) &&
3120           ( time > time_of_first_date ) )
3121         mapped = False;
3122       else
3123         mapped = True;
3124 
3125       UpdateWeekButton( md, index, time, mapped );
3126     }
3127   }
3128 
3129 
3130   return;
3131 
3132 } /* UpdateNewMonth */
3133 
3134 
3135 /*----------------------------------------------------------------------*/
3136 
3137 static void
UpdateWeekButton(XmUbMonthDisplayWidget md,int index,TIM_TIME_REF time_of_first_day,Boolean mapped)3138   UpdateWeekButton( XmUbMonthDisplayWidget  md,
3139                     int                     index,
3140                     TIM_TIME_REF            time_of_first_day,
3141                     Boolean                 mapped )
3142 {
3143   /* Variables. */
3144   Arg                             args[ 10 ];
3145   XmUbMdiUpdateDayCallbackStruct  cb;
3146   char                            label_buffer[ 20 ];
3147   Cardinal                        n;
3148   Pixel                           old_fg, old_bg, old_top, old_bottom;
3149   Boolean                         old_mapped;
3150   int                             user_data;
3151   Widget                          w;
3152   XmString                        xm = NULL;
3153 
3154   /* Code. */
3155 
3156   w = md -> md.week_number_buttons[ index ];
3157 
3158   /* Get the current values. */
3159 
3160   n = 0;
3161   XtSetArg( args[ n ], XmNuserData, &user_data ); n++;
3162   XtSetArg( args[ n ], XmNforeground, &old_fg ); n++;
3163   XtSetArg( args[ n ], XmNbackground, &old_bg ); n++;
3164   XtSetArg( args[ n ], XmNtopShadowColor, &old_top ); n++;
3165   XtSetArg( args[ n ], XmNbottomShadowColor, &old_bottom ); n++;
3166   XtSetArg( args[ n ], XmNmappedWhenManaged, &old_mapped ); n++;
3167   XtGetValues( w, args, n );
3168 
3169   /* Fill in the callback structure. Can be used also if no callback. */
3170   cb.reason      = XmUbCR_UPDATE_WEEK;
3171   cb.event       = NULL;
3172   cb.day         = TimIndexOfDay( time_of_first_day );
3173   cb.month       = TimIndexOfMonth( time_of_first_day );
3174   cb.year        = TimIndexOfYear( time_of_first_day );
3175   cb.week_number = TimIndexOfWeek( time_of_first_day );
3176   cb.foreground  = old_fg;
3177   cb.background  = old_bg;
3178   cb.frame       = old_top;
3179   cb.use_shadows = False;
3180   cb.mapped      = old_mapped;
3181 
3182   cb.default_foreground = md -> md.week_number_foreground;
3183   cb.default_background = md -> core.background_pixel;
3184   cb.default_frame      = md -> core.background_pixel;
3185   cb.default_mapped     = mapped;
3186   cb.loop_index         = index - 1;
3187 
3188   if( md -> md.update_day_callback ){
3189     /* Let the user determine what should be displayed. */
3190 
3191     XtCallCallbackList( (Widget) md, md -> md.update_day_callback,
3192                         (XtPointer) &cb );
3193 
3194   } else {
3195     /* We should display the defaults. */
3196     cb.foreground = cb.default_foreground;
3197     cb.background = cb.default_background;
3198     cb.frame      = cb.default_frame;
3199     cb.mapped     = cb.default_mapped;
3200   }
3201 
3202   /* Set the values. */
3203   n = 0;
3204 
3205   if( cb.foreground != old_fg ){
3206     XtSetArg( args[ n ], XmNforeground, cb.foreground ); n++;
3207   }
3208   if( cb.background != old_bg ){
3209     XtSetArg( args[ n ], XmNbackground, cb.background ); n++;
3210   }
3211 
3212   if( ! cb.use_shadows ){
3213     if( cb.frame != old_top ){
3214       XtSetArg( args[ n ], XmNtopShadowColor, cb.frame ); n++;
3215       XtSetArg( args[ n ], XmNbottomShadowColor, cb.frame ); n++;
3216     }
3217 
3218   } else {
3219     /* Pushbutton shadows on button. */
3220 
3221     if( old_top != md -> md.pushb_default_topshadow ){
3222       XtSetArg( args[ n ], XmNtopShadowColor,
3223                            md -> md.pushb_default_topshadow ); n++;
3224     }
3225     if( old_bottom != md -> md.pushb_default_bottomshadow ){
3226       XtSetArg( args[ n ], XmNbottomShadowColor,
3227                            md -> md.pushb_default_bottomshadow ); n++;
3228     }
3229   }
3230 
3231   /* If we are lucky, we don't need to change the text... */
3232   if( user_data != cb.week_number ){
3233     sprintf( label_buffer, "%d", cb.week_number );
3234     xm = XmStringCreateLtoR( label_buffer, XmSTRING_DEFAULT_CHARSET );
3235 
3236     XtSetArg( args[ n ], XmNlabelString, xm ); n++;
3237     XtSetArg( args[ n ], XmNuserData, cb.week_number ); n++;
3238   }
3239 
3240   /* Mapped or not? */
3241   if( old_mapped != cb.mapped ){
3242     XtSetArg( args[ n ], XmNmappedWhenManaged, cb.mapped ); n++;
3243   }
3244 
3245   /* Update the button. */
3246   if( n > 0 )
3247     XtSetValues( w, args, n );
3248 
3249   /* Cleanup. */
3250   if( xm != NULL )
3251     XmStringFree( xm );
3252 
3253 
3254   return;
3255 
3256 } /* UpdateWeekButton */
3257 
3258 
3259 /*----------------------------------------------------------------------*/
3260 
3261 static void
WarningNoResourceChange(XmUbMonthDisplayWidget md,String resource)3262   WarningNoResourceChange( XmUbMonthDisplayWidget  md,
3263                            String                  resource )
3264 {
3265   /* Variables. */
3266   Cardinal  num_params;
3267   String    params[ 2 ];
3268 
3269   /* Code. */
3270 
3271   params[ 0 ] = resource;
3272   params[ 1 ] = XtClass( md ) -> core_class.class_name;
3273   num_params  = 2;
3274   XtAppWarningMsg( XtWidgetToApplicationContext( (Widget) md ),
3275 		   "resourceError", "setValues", "WidgetError",
3276 		   "Resource %s may not be changed in %s widgets.",
3277 		   params, &num_params );
3278 
3279   return;
3280 
3281 } /* WarningNoResourceChange */
3282 
3283 
3284 /*----------------------------------------------------------------------*/
3285 
3286 static void
WeekNumberButtonActivatedCB(Widget pb,XmUbMonthDisplayWidget md,XmPushButtonCallbackStruct * call_data)3287   WeekNumberButtonActivatedCB( Widget                      pb,
3288                                XmUbMonthDisplayWidget      md,
3289                                XmPushButtonCallbackStruct  *call_data )
3290 {
3291   /* Variables. */
3292   XmUbMonthDisplayCallbackStruct  cb;
3293   int                             date_index;
3294   int                             day_number;
3295   int                             index;
3296   int                             month_number;
3297   int                             year_number;
3298 
3299   /* Code. */
3300 
3301   /* Get the index of the week button. */
3302   for( index = 0; index < NO_WEEK_NUMBER_BUTTONS; index ++ ){
3303     if( pb == md -> md.week_number_buttons[ index ] )
3304       break;
3305   }
3306 
3307   /* The first day of that week. */
3308   date_index = ( index - 1 ) * 7;
3309 
3310   /* Get the day number for the week start button. */
3311   ButtonDate( md, md -> md.day_number_buttons[ date_index ],
3312               &year_number, &month_number, &day_number );
3313 
3314   cb.selected_year  = year_number;
3315   cb.selected_month = month_number;
3316   cb.selected_day   = day_number;
3317 
3318   /* End date. */
3319   date_index += 6;
3320 
3321   ButtonDate( md, md -> md.day_number_buttons[ date_index ],
3322               &year_number, &month_number, &day_number );
3323 
3324   cb.end_year  = year_number;
3325   cb.end_month = month_number;
3326   cb.end_day   = day_number;
3327 
3328   /* Invoke the callbacks. */
3329 
3330   cb.reason = XmUbCR_DATE_SELECTED;
3331   cb.event  = call_data -> event;
3332   cb.child  = pb;
3333   cb.range  = True;
3334 
3335   XtCallCallbackList( (Widget) md, md -> md.date_selected_callback,
3336                       (XtPointer) &cb );
3337 
3338 
3339   return;
3340 
3341 } /* WeekNumberButtonActivatedCB */
3342 
3343 
3344 /*----------------------------------------------------------------------*/
3345 
3346 Widget
XmUbCreateMonthDisplay(Widget parent,String name,ArgList arglist,Cardinal argcount)3347   XmUbCreateMonthDisplay( Widget    parent,
3348                           String    name,
3349                           ArgList   arglist,
3350                           Cardinal  argcount )
3351 {
3352 
3353   /* Code. */
3354 
3355   return XtCreateWidget( name, xmUbMonthDisplayWidgetClass,
3356                          parent, arglist, argcount );
3357 
3358 } /* XmUbCreateMonthDisplay */
3359 
3360 
3361 /*----------------------------------------------------------------------*/
3362 
3363 Widget
XmUbMonthDisplayGetChild(Widget widget,int child)3364   XmUbMonthDisplayGetChild( Widget  widget,
3365                             int     child )
3366 {
3367   /* Variables. */
3368   XmUbMonthDisplayWidget  md;
3369 
3370   /* Code. */
3371 
3372   md = (XmUbMonthDisplayWidget) widget;
3373 
3374 
3375   return( md -> md.internal_children[ child ] );
3376 
3377 } /* XmUbMonthDisplayGetChild */
3378 
3379 
3380 /*----------------------------------------------------------------------*/
3381 
3382 void
XmUbMonthDisplaySetFocusToDay(Widget widget,int day_number)3383   XmUbMonthDisplaySetFocusToDay( Widget  widget,
3384                                  int     day_number )
3385 {
3386   /* Variables. */
3387   Widget                  button;
3388   XmUbMonthDisplayWidget  md;
3389 
3390   /* Code. */
3391 
3392   md = (XmUbMonthDisplayWidget) widget;
3393 
3394   /* Find the widget id of the button. */
3395   button = DateButton( md, day_number );
3396 
3397   if( button != NULL )
3398     XmProcessTraversal( button, XmTRAVERSE_CURRENT );
3399 
3400 
3401   return;
3402 
3403 } /* XmUbMonthDisplaySetFocusToDay */
3404 
3405 
3406 /*----------------------------------------------------------------------*/
3407 
3408 void
XmUbMonthDisplaySetDateBackground(Widget widget,int day_number,Pixel bg)3409   XmUbMonthDisplaySetDateBackground( Widget  widget,
3410                                      int     day_number,
3411                                      Pixel   bg )
3412 {
3413   /* Variables. */
3414   Arg                     args[ 2 ];
3415   Widget                  button;
3416   XmUbMonthDisplayWidget  md;
3417   Cardinal                n;
3418 
3419   /* Code. */
3420 
3421   md = (XmUbMonthDisplayWidget) widget;
3422 
3423   /* Find the widget id of the button. */
3424   button = DateButton( md, day_number );
3425 
3426   if( button != NULL ){
3427     n = 0;
3428     XtSetArg( args[ n ], XmNbackground, bg ); n++;
3429     XtSetValues( button, args, n );
3430   }
3431 
3432 
3433   return;
3434 
3435 } /* XmUbMonthDisplaySetDateBackground */
3436 
3437 
3438 /*----------------------------------------------------------------------*/
3439 
3440 void
XmUbMonthDisplaySetDateForeground(Widget widget,int day_number,Pixel fg)3441   XmUbMonthDisplaySetDateForeground( Widget  widget,
3442                                      int     day_number,
3443                                      Pixel   fg )
3444 {
3445   /* Variables. */
3446   Arg                     args[ 2 ];
3447   Widget                  button;
3448   XmUbMonthDisplayWidget  md;
3449   Cardinal                n;
3450 
3451   /* Code. */
3452 
3453   md = (XmUbMonthDisplayWidget) widget;
3454 
3455   /* Find the widget id of the button. */
3456   button = DateButton( md, day_number );
3457 
3458   if( button != NULL ){
3459     n = 0;
3460     XtSetArg( args[ n ], XmNforeground, fg ); n++;
3461     XtSetValues( button, args, n );
3462   }
3463 
3464 
3465   return;
3466 
3467 } /* XmUbMonthDisplaySetDateForeground */
3468 
3469 
3470 /*----------------------------------------------------------------------*/
3471 
3472 void
XmUbMonthDisplaySetDateFrame(Widget widget,int day_number,Pixel color)3473   XmUbMonthDisplaySetDateFrame( Widget  widget,
3474                                 int     day_number,
3475                                 Pixel   color )
3476 {
3477   /* Variables. */
3478   Arg                     args[ 2 ];
3479   Widget                  button;
3480   XmUbMonthDisplayWidget  md;
3481   Cardinal                n;
3482 
3483   /* Code. */
3484 
3485   md = (XmUbMonthDisplayWidget) widget;
3486 
3487   /* Find the widget id of the button. */
3488   button = DateButton( md, day_number );
3489 
3490   if( button != NULL ){
3491     n = 0;
3492     XtSetArg( args[ n ], XmNtopShadowColor, color ); n++;
3493     XtSetArg( args[ n ], XmNbottomShadowColor, color ); n++;
3494     XtSetValues( button, args, n );
3495   }
3496 
3497 
3498   return;
3499 
3500 } /* XmUbMonthDisplaySetDateFrame */
3501 
3502 
3503 /*----------------------------------------------------------------------*/
3504 
3505 void
XmUbMonthDisplaySetMonth(Widget widget,int year,int month)3506   XmUbMonthDisplaySetMonth( Widget  widget,
3507                             int     year,
3508                             int     month )
3509 {
3510   /* Variables. */
3511   XmUbMonthDisplayWidget  md;
3512 
3513   /* Code. */
3514 
3515   md = (XmUbMonthDisplayWidget) widget;
3516 
3517   if( year != 0 )
3518     md -> md.current_year  = year;
3519   if( month != 0 )
3520     md -> md.current_month = month;
3521 
3522 
3523   UpdateNewMonth( md );
3524 
3525 
3526   return;
3527 
3528 } /* XmUbMonthDisplaySetMonth */
3529 
3530 
3531 /*----------------------------------------------------------------------*/
3532 
3533 static void
YearScrolledCB(Widget pb,XmUbMonthDisplayWidget md,XmUbArrowLabelCallbackStruct * call_data)3534   YearScrolledCB( Widget                        pb,
3535                   XmUbMonthDisplayWidget        md,
3536                   XmUbArrowLabelCallbackStruct  *call_data )
3537 {
3538   /* Variables. */
3539 
3540   /* Code. */
3541 
3542   switch( call_data -> reason ){
3543 
3544     case XmUbCR_BACK_ARROW_ACTIVATED:
3545       if( md -> md.current_year > 1970 )
3546         md -> md.current_year --;
3547       else
3548         md -> md.current_month = 1;
3549       break;
3550 
3551     case XmUbCR_FORWARD_ARROW_ACTIVATED:
3552       md -> md.current_year ++;
3553       break;
3554 
3555     default:
3556       return;
3557   }
3558 
3559   UpdateNewMonth( md );
3560   CallNewMonthCallbacks( md );
3561 
3562   return;
3563 
3564 } /* YearScrolledCB */
3565