dtcm: Resolve 303 compiler warnings.
[oweals/cde.git] / cde / programs / dtcm / dtcm / MonthPanel.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*********************************************************************************
24 **  MonthPanel.c
25 **
26 **  $XConsortium: MonthPanel.c /main/7 1996/11/21 19:41:55 drk $
27 **
28 **  RESTRICTED CONFIDENTIAL INFORMATION:
29 **
30 **  The information in this document is subject to special
31 **  restrictions in a confidential disclosure agreement between
32 **  HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
33 **  document outside HP, IBM, Sun, USL, SCO, or Univel without
34 **  Sun's specific written approval.  This document and all copies
35 **  and derivative works thereof must be returned or destroyed at
36 **  Sun's request.
37 **
38 **  Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
39 **
40 *******************************************************************************/
41
42 /*                                                                      *
43  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
44  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
45  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
46  * (c) Copyright 1993, 1994 Novell, Inc.                                *
47  */
48
49 /*
50  * Month Panel widget implementation (class XmMonthPanel)
51  *
52  * The XmMonthPanel widget is rigged with the Motif widget binary
53  * compatibility mechanism.  All Motif-specific changes for this mechanism
54  * are preceded by a comment including the string "MotifBc"
55  *
56  * For a description of the Motif widget binary compatibility mechanism
57  * see the reference manual entry on XmResolvePartOffsets().
58  *
59  */
60 #include <EUSCompat.h>
61 #include <stdio.h>
62 #include <Xm/ManagerP.h>
63 #include <Xm/PushBG.h>
64 #include <Xm/SeparatoG.h>
65 #include <Xm/LabelG.h>
66 #include "MonthPanelP.h"
67 #include "timeops.h"
68 #include "misc.h"
69
70 #define XOS_USE_XT_LOCKING
71 #define X_INCLUDE_TIME_H
72 #if defined(linux)
73 #undef SVR4
74 #endif
75 #include <X11/Xos_r.h>
76
77 /*
78  * MotifBc - index value for this class is superclass' value + 1
79  */
80 #ifdef MOTIF_BC
81 #define XmMonthPanelIndex (XmManagerIndex + 1)
82 #endif /* MOTIF_BC */
83
84 /*
85  * MotifBc - dynamic offset tables
86  */
87 #ifdef MOTIF_BC
88 static XmOffsetPtr ipot;        /* Instance part offset table */
89 static XmOffsetPtr cpot;        /* Constraint part offset table */
90 #endif /* MOTIF_BC */
91
92 /*
93  * MotifBc - macros for accessing instance and constraint fields
94  */
95 #ifdef MOTIF_BC
96 #define Year(w)         XmField(w, ipot, XmMonthPanel, year, int)
97 #define Month(w)        XmField(w, ipot, XmMonthPanel, month, int)
98 #define Callback(w)     XmField(w, ipot, XmMonthPanel, callback, XtCallbackList)
99 #define TitleFormat(w)  XmField(w, ipot, XmMonthPanel, title_format, String)
100 #define Header(w)       XmField(w, ipot, XmMonthPanel, header, Widget)
101 #define DayLabels(w)    XmField(w, ipot, XmMonthPanel, day_labels, Widget *)
102 #define Days(w)         XmField(w, ipot, XmMonthPanel, days, Widget *)
103 #endif /* MOTIF_BC */
104
105
106 /********    Static Function Declarations    ********/
107 static void scale_components(XmMonthPanelWidget);
108
109 static void ClassPartInitialize(WidgetClass) ;
110 static void Initialize(Widget, Widget, ArgList, Cardinal *) ;
111 static void Redisplay(Widget, XEvent *, Region);
112 static void DoLayout(XmMonthPanelWidget) ;
113 static void Resize(Widget) ;
114 static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *) ;
115 static XtGeometryResult QueryProc(Widget, XtWidgetGeometry*, XtWidgetGeometry*);
116 static XtGeometryResult GeometryManager( Widget, XtWidgetGeometry *, XtWidgetGeometry *);
117 static void DayCallback(Widget, XtPointer, XtPointer);
118 static void MonthCallback(Widget, XtPointer, XtPointer);
119 static void set_header_string(XmMonthPanelWidget);
120 static Boolean clipped(Widget);
121 /********    End Static Function Declarations    ********/
122
123
124 /*
125  * These arrays are implemented in calendarA.c.  They are arrays
126  * of the local strings for day names and month names.  The day
127  * arrays start from 0, the month array starts from 1; no particular
128  * reason for this difference that I can see.
129  */
130 extern char *days3[];           /* eg: "S"   */
131 extern char *months[];          /* eg: "January" */
132
133 /*
134  * widget instance names for column header labels in panel
135  */
136 static char *col_hdr[] = { "sunday", "monday", "tuesday", "wednesday",
137                            "thursday", "friday", "saturday" };
138
139 \f
140 /************************************************************************
141  *                                                                      *
142  * Month Panel Resources                                                *
143  *                                                                      *
144  ************************************************************************/
145
146 static XtResource resources[] = 
147 {
148     { XmNyear, XmCYear, XmRInt, sizeof(int),
149         XtOffsetOf( struct _XmMonthPanelRec, month_panel.year),
150         XmRImmediate, (XtPointer)NULL },
151     { XmNmonth, XmCMonth, XmRInt, sizeof(int),
152         XtOffsetOf( struct _XmMonthPanelRec, month_panel.month),
153         XmRImmediate, (XtPointer)NULL },
154     { XmNactivateCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
155         XtOffsetOf( struct _XmMonthPanelRec, month_panel.callback),
156         XmRImmediate, (XtPointer)NULL },
157     { XmNtitleFormat, XmCTitleFormat, XmRString, sizeof(char *),
158         XtOffsetOf( struct _XmMonthPanelRec, month_panel.title_format),
159         XtRString, (XtPointer)"%B %Y" },
160     { XmNactiveHeader, XmCActiveHeader, XmRBoolean, sizeof(Boolean),
161         XtOffsetOf( struct _XmMonthPanelRec, month_panel.active_header),
162         XtRImmediate, (XtPointer)False },
163     { XmNactiveDays, XmCActiveDays, XmRBoolean, sizeof(Boolean),
164         XtOffsetOf( struct _XmMonthPanelRec, month_panel.active_days),
165         XtRImmediate, (XtPointer)False },
166     { XmNshowPanelHeader, XmCShowPanelHeader, XmRBoolean, sizeof(Boolean),
167         XtOffsetOf( struct _XmMonthPanelRec, month_panel.show_panel_header),
168         XtRImmediate, (XtPointer)True },
169     { XmNshowColumnHeaders, XmCShowColumnHeaders, XmRBoolean, sizeof(Boolean),
170         XtOffsetOf( struct _XmMonthPanelRec, month_panel.show_column_headers),
171         XtRImmediate, (XtPointer)True },
172     { XmNshowSeparator, XmCShowSeparator, XmRBoolean, sizeof(Boolean),
173         XtOffsetOf( struct _XmMonthPanelRec, month_panel.show_separator),
174         XtRImmediate, (XtPointer)True }
175 };
176
177
178 \f
179 /****************************************************************
180  *
181  * Full class record constant
182  *
183  ****************************************************************/
184
185 externaldef(xmmonthpanelclassrec) XmMonthPanelClassRec
186              xmMonthPanelClassRec = {
187   {
188 /* core_class fields      */
189     /* superclass         */    (WidgetClass) &xmManagerClassRec,
190     /* class_name         */    "XmMonthPanel",
191     /* widget_size        */    sizeof(XmMonthPanelRec),
192     /* class_initialize   */    NULL,
193     /* class_partinit     */    ClassPartInitialize,
194     /* class_inited       */    FALSE,
195     /* initialize         */    Initialize,
196     /* Init hook          */    NULL,
197     /* realize            */    XtInheritRealize,
198     /* actions            */    NULL,
199     /* num_actions        */    0,
200     /* resources          */    resources,
201     /* num_resources      */    XtNumber(resources),
202     /* xrm_class          */    NULLQUARK,
203     /* compress_motion    */    TRUE,
204     /* compress_exposure  */    XtExposeCompressMaximal,
205     /* compress_enterleave*/    TRUE,
206     /* visible_interest   */    FALSE,
207     /* destroy            */    NULL,
208     /* resize             */    Resize,
209     /* expose             */    Redisplay,
210     /* set_values         */    SetValues,
211     /* set values hook    */    NULL,
212     /* set values almost  */    XtInheritSetValuesAlmost,
213     /* get values hook    */    NULL,
214     /* accept_focus       */    NULL,
215     /* Version            */    XtVersion,
216     /* PRIVATE cb list    */    NULL,
217     /* tm_table           */    XtInheritTranslations,
218     /* query_geometry     */    XtInheritQueryGeometry,
219     /* display_accelerator*/    NULL,
220     /* extension          */    NULL,
221   },
222   {
223 /* composite_class fields */
224     /* geometry_manager   */    GeometryManager,
225     /* change_managed     */    XtInheritChangeManaged,
226     /* insert_child       */    XtInheritInsertChild,
227     /* delete_child       */    XtInheritDeleteChild,   /* Inherit from superclass */
228     /* Extension          */    NULL,
229   },{
230 /* Constraint class Init */
231     NULL,
232     0,
233     0,
234     NULL,
235     NULL,
236     NULL,
237     NULL
238       
239   },
240 /* Manager Class */
241    {            
242       XtInheritTranslations,                    /* translations        */    
243       NULL,                                     /* get resources          */
244       0,                                        /* num get_resources      */
245       NULL,                                     /* get_cont_resources     */
246       0,                                        /* num_get_cont_resources */
247       XmInheritParentProcess,                   /* parent_process         */
248       NULL,                                     /* extension           */    
249    },
250
251  {
252 /* Month Panel class - none */     
253      /* mumble */               0
254  }      
255 };
256
257 externaldef(xmmonthpanelwidgetclass) WidgetClass
258              xmMonthPanelWidgetClass = (WidgetClass)&xmMonthPanelClassRec;
259
260
261 \f
262
263 /************************************************************************
264  *                                                                      *
265  *  ClassPartInitialize - Set up the fast subclassing.                  *
266  *                                                                      *
267  ************************************************************************/
268 static void 
269 ClassPartInitialize( WidgetClass wc )
270 {
271 /*
272    _XmFastSubclassInit (wc, XmMONTH_PANEL_BIT);
273 */
274 }
275
276 \f
277 /************************************************************************
278  *                                                                      *
279  *  Initialize                                                          *
280  *                                                                      *
281  ************************************************************************/
282 /* ARGSUSED */
283 static void 
284 Initialize( Widget rw, Widget nw, ArgList args, Cardinal *num_args )
285 {
286         int i=0;
287         Arg wargs[5];
288         Widget header;
289         XmString str;
290         struct tm *tm_ret;
291         time_t timer;
292         Tick tmptick;
293         _Xltimeparams localtime_buf;
294         
295         XmMonthPanelWidget request = (XmMonthPanelWidget) rw ;
296         XmMonthPanelWidget new_w = (XmMonthPanelWidget) nw ;
297
298         char buf[BUFSIZ];
299
300         new_w->month_panel.display_rows = 6;  /* minimum to show all days */
301
302 /*
303  * create and cache panel header ( eg. "January") (depends on format resource)
304  *
305  * Whether XmLabels or XmPushButton gadgets are used is selectable via
306  * the boolean "activeDays" and "activeHeader" resource. True gets you buttons.
307  */
308
309         if (new_w->month_panel.active_header) {
310            new_w->month_panel.header =
311                 XmCreatePushButtonGadget((Widget)new_w, "header", NULL, 0);
312            XtAddCallback(new_w->month_panel.header, XmNactivateCallback,
313                 MonthCallback, NULL);
314            new_w->month_panel.separator = (Widget) NULL;
315         }
316         else {
317            new_w->month_panel.header =
318                 XmCreateLabelGadget((Widget)new_w, "header", NULL, 0);
319            new_w->month_panel.separator =
320                 XmCreateSeparatorGadget((Widget)new_w, "separator", NULL, 0); 
321            /* Managing of separator is switchable */
322            if (new_w->month_panel.show_separator) {
323               XtManageChild(new_w->month_panel.separator);
324               /* separator takes another row to display */
325               (new_w->month_panel.display_rows)++;
326            }
327         }
328
329         /* set header label */
330
331 /*
332 **  Problem in set_header_string.  It references month_panel.month
333 ** and month_panel.year, which aren't initialized in when it is called
334 ** in the Initialize function.  Set them to today.
335 */
336         time (&timer);
337         tm_ret = _XLocaltime(&timer, localtime_buf);
338         new_w->month_panel.month = tm_ret->tm_mon + 1;
339         new_w->month_panel.year = 1900 + tm_ret->tm_year;
340
341         set_header_string(new_w);
342
343         /* Managing of header is switchable */
344         if (new_w->month_panel.show_panel_header) {
345            XtManageChild(new_w->month_panel.header);
346            /* header takes another row to display */
347            (new_w->month_panel.display_rows)++;
348         }
349
350 /*
351  * create and cache id's of, column header day names
352  */
353         new_w->month_panel.day_labels =
354                 (Widget *) XtMalloc( 7 * sizeof(Widget) );
355         for (i=0; i < 7; i++) {
356            XmString str;
357            Widget label;
358
359            /* I18N:next line: wrap the string & fetch from catalog */
360            str = XmStringCreateLocalized(days3[i]);
361            XtSetArg(wargs[0], XmNlabelString, str);
362            label = XmCreateLabelGadget((Widget) new_w, col_hdr[i], wargs, 1);
363            /* Managing of column headers is switchable */
364            if (new_w->month_panel.show_column_headers)
365               XtManageChild(label);
366            new_w->month_panel.day_labels[i] = label; /* cache in panel inst. */
367            XmStringFree(str);
368         }
369
370         /* column headers take another row to display */
371         if (new_w->month_panel.show_column_headers)
372            (new_w->month_panel.display_rows)++;
373
374 /*
375  * create and cache id's of, 31 buttons for days
376  */
377         new_w->month_panel.days = (Widget *) XtMalloc( 31 * sizeof(Widget) );
378         for (i=0; i < 31; i++) {
379            char buf[BUFSIZ];
380            XmString str;
381            Widget btn;
382
383            sprintf(buf, "%d", i+1);
384            str = XmStringCreateLocalized(buf);
385            XtSetArg(wargs[0], XmNlabelString, str);
386            sprintf(buf, "day%d", i+1);
387
388 /* choose between buttons or labels for day objects */
389            if (new_w->month_panel.active_days) {
390                 btn = XmCreatePushButtonGadget((Widget)new_w, buf, wargs, 1);
391                 XtAddCallback(btn, XmNactivateCallback, DayCallback,
392                         (XtPointer) (intptr_t) (i+1));
393            }
394            else {
395                 btn = XmCreateLabelGadget((Widget) new_w, buf, wargs, 1);
396            }
397            new_w->month_panel.days[i] = btn;/* cache id in panel instance */
398            XmStringFree(str);
399         }
400         XtManageChildren((WidgetList)new_w->month_panel.days, 31);
401
402 /*
403  * Set all these components to the appropriate size for the container
404  * Then position them correctly.
405  */
406         scale_components(new_w);
407
408         DoLayout(new_w);
409 }
410
411 static void
412 Redisplay(Widget w, XEvent *ev, Region region)
413 {
414         XmMonthPanelWidget panel = (XmMonthPanelWidget) w;
415
416         XmeRedisplayGadgets( w, ev, region) ;
417 }
418
419 \f
420 /************************************************************************
421  *                                                                      *
422  * DoLayout - Layout the month panel.                                   *
423  *                                                                      *
424  ************************************************************************/
425 static void 
426 DoLayout( XmMonthPanelWidget mw )
427 {
428         XmMonthPanelPart *mpp = &(mw->month_panel);
429         Dimension w = mw->core.width;
430         Dimension h = mw->core.height;
431         int col_w = (int) w/7;
432         int row_h;
433         Boolean tall_header;
434         Position x=0;
435         Position y=0;
436         int days_in_month = monthlength(monthdayyear(mpp->month,1,mpp->year));
437         int first = fdom(monthdayyear(mpp->month,1,mpp->year));
438         Widget this_widget;
439         int i=0;
440
441         if (!mw->month_panel.active_days && mw->month_panel.active_header) {
442                 tall_header = True;
443                 row_h = (int) h/(mpp->display_rows + 1);
444         }
445         else {
446                 tall_header = False;
447                 row_h = (int) h/(mpp->display_rows);
448         }
449
450 /* 
451  * Make sure the variable buttons are correctly [un]managed.
452  * (the "variable" buttons are those for 29th, 30th and 31st)
453  */
454         for (i=28; i < 31; i++) {
455                 Widget this_widget = (mpp->days)[i];
456                 if (days_in_month > i) {
457                         if (!XtIsManaged(this_widget))
458                                 XtManageChild(this_widget);
459                 }
460                 else {
461                         if (XtIsManaged(this_widget))
462                                 XtUnmanageChild(this_widget);
463                 }
464         }
465
466 /*
467  * position the panel header
468  */
469         XtMoveWidget(mpp->header, 0, 0);
470
471 /*
472  * position the separator, if any
473  */
474         if (mpp->separator != NULL) {
475                 if (tall_header)
476                         XtMoveWidget(mpp->separator,
477                                 (Position) w/8, (Position) 2 * row_h);
478                 else
479                         XtMoveWidget(mpp->separator,
480                                 (Position) w/8, (Position)  row_h);
481         }
482
483 /*
484  * position the day labels
485  */
486         x = (Position) 0;
487         y = (Position) (mw->month_panel.display_rows -
488                         (tall_header ? 6 : 7)) * row_h;
489
490         i=0;
491         while (i < 7) {
492                 this_widget = mw->month_panel.day_labels[i];
493                 XtMoveWidget(this_widget, x, y);
494                 x += col_w;
495                 i++;
496         }
497
498 /*
499  * position the day buttons
500  */
501         x = (Position) first * col_w;
502         y = (Position) (mw->month_panel.display_rows -
503                         (tall_header ? 5 : 6)) * row_h;
504
505         i=0;
506         while (i < 31){
507                 this_widget = mw->month_panel.days[i];
508
509                 /* don't bother with unmanaged buttons */
510                 if (XtIsManaged(this_widget))
511                         XtMoveWidget(this_widget, x, y);
512                 i++;
513
514                 /* take new row after each 7 buttons */
515                 if ( ( (i+first) % 7 ) == 0 ) {
516                         x = 0;
517                         y += row_h;
518                 }
519                 else
520                         x += col_w;
521         }
522
523 }
524 \f
525
526 /************************************************************************
527  *
528  * scale_components - Make all the labels, buttons correct size for this
529  *                    size space.
530  *
531  *                    [4/12/94] - Check whether new size causes labels
532  *                                to be clipped.  If it does, set labelType
533  *                                to PIXMAP.  A suitable labelPixmap should be
534  *                                set to indicate "label too small".
535  ************************************************************************/
536
537 static void
538 scale_components(XmMonthPanelWidget mw) {
539
540         XmMonthPanelPart *mpp = &(mw->month_panel);
541         Dimension w=mw->core.width;
542         Dimension h=mw->core.height;
543         int row_h;
544         Boolean tall_header;
545         int col_w = (int) w/7;
546         int i=0;
547         Widget this_widget;
548         unsigned char ltype;
549         Pixel fg, bg;
550         Pixmap head_pm, col_head_pm, btn_pm;
551
552         if (!mw->month_panel.active_days && mw->month_panel.active_header) {
553                 tall_header = True;
554                 row_h = (int) h/(mpp->display_rows + 1);
555         }
556         else {
557                 tall_header = False;
558                 row_h = (int) h/(mpp->display_rows);
559         }
560
561         /******************************************************************
562          * get pixmap in colors needed - used to replace text when clipped.
563          *
564          * NOTE1: Don't need to release the pixmaps, because they come from
565          * the Motif-owned image cache.
566          * 
567          * NOTE2: setting the pixmaps should be in redisplay rather than
568          * here - only done here because this is where labelType is toggled.
569          ******************************************************************/
570         XtVaGetValues(XtParent(mw), XmNforeground, &fg, XmNbackground, &bg, NULL);
571         head_pm = XmGetPixmap(XtScreen(mw), "slant_right", fg, bg);
572         col_head_pm = XmGetPixmap(XtScreen(mw), "slant_left", fg, bg);
573         btn_pm = XmGetPixmap(XtScreen(mw), "50_foreground", fg, bg);
574
575
576         /*********************************************************************
577          * This algorithm allocates equal header, label and button heights;
578          * equal label and button widths; header spans container width.
579          *********************************************************************/
580
581         /**************************
582          * set panel header size
583          **************************/
584         
585         if (tall_header)
586                 XtResizeWidget(mpp->header, w, 2 * row_h, mpp->header->core.border_width);
587         else
588                 XtResizeWidget(mpp->header, w, row_h, mpp->header->core.border_width);
589
590         if (clipped(mpp->header)) {
591                 XtVaSetValues(mpp->header,
592                         XmNlabelType, XmPIXMAP,
593                         XmNlabelPixmap, head_pm,
594                         NULL);
595         }
596         else
597                 XtVaSetValues(mpp->header,
598                         XmNlabelType, XmSTRING,
599                         NULL);
600
601         /**************************
602          * separator
603          **************************/
604         if (mpp->separator != NULL) {
605                 XtResizeWidget(mpp->separator, 3*(int)w/4, row_h, 0);
606         }
607         
608         /**************************
609          * set column-heading label sizes
610          **************************/
611         for (i=0; i<7; i++) {
612                 this_widget = (mpp->day_labels)[i];
613                 XtResizeWidget(this_widget, col_w, row_h, 0);
614         }       
615         /* display pixmap if clipped, string otherwise */
616         this_widget = (mpp->day_labels)[6];
617         XtVaGetValues(this_widget, XmNlabelType, &ltype, NULL);
618         if (clipped(this_widget)) {
619            if (ltype == XmSTRING) {
620                 for (i=0; i<7; i++) {
621                    XtVaSetValues((mpp->day_labels)[i],
622                         XmNlabelType, XmPIXMAP,
623                         XmNlabelPixmap, col_head_pm,
624                         NULL);
625                 }       
626            }
627         }
628         else {
629            if (ltype == XmPIXMAP) {
630                 for (i=0; i<7; i++) {
631                    XtVaSetValues((mpp->day_labels)[i], XmNlabelType, XmSTRING, NULL);
632                 }       
633            }
634         }
635
636         /**************************
637          * Day buttons
638          **************************/
639         for (i=0; i<31; i++) {
640                 this_widget = (mpp->days)[i];
641                 XtResizeWidget(this_widget, col_w, row_h, 0);
642         }       
643
644         /*************************************************************
645          * If any of the button labels are clipped, replace the
646          * entire set with their pixmap equivalents.  The labelPixmap
647          * resource should be set to something that means "not big enough"
648          * (like a dot!)
649          *   This check should really be done in above loop, but it
650          * slows things down to catch the edge case (different fonts
651          * in different labels, so this is thought "good enough".
652          *   28th button picked at random for test - at least it's always a
653          * 2-digit label.
654          *************************************************************/
655         this_widget = (mpp->days)[27];
656         XtVaGetValues(this_widget, XmNlabelType, &ltype, NULL);
657         if (clipped(this_widget)) {
658            if (ltype == XmSTRING) {
659                 for (i=0; i<31; i++) {
660                    XtVaSetValues((mpp->days)[i],
661                         XmNlabelType, XmPIXMAP,
662                         XmNlabelPixmap, btn_pm,
663                         NULL);
664                 }       
665            }
666         }
667         else {
668            if (ltype == XmPIXMAP) {
669                 for (i=0; i<31; i++) {
670                    XtVaSetValues((mpp->days)[i], XmNlabelType, XmSTRING, NULL);
671                 }       
672            }
673         }
674 }
675
676 /*
677  * Determine whether labelString requires more space
678  * than its widget currently has.  This information
679  * can be used to display clipped information differently
680  */
681 static Boolean
682 clipped(Widget w) 
683 {
684         XmString str;
685         XmFontList fl;
686         Dimension req_w, req_h, act_w, act_h, shd_w, hlt_w;
687
688         return(False);
689
690         XtVaGetValues(w,
691                 XmNlabelString, &str,
692                 XmNfontList, &fl,
693                 XmNhighlightThickness, &hlt_w,
694                 XmNshadowThickness, &shd_w,
695                 XmNwidth, &act_w,
696                 XmNheight, &act_h,
697                 NULL);
698
699         XmStringExtent(fl, str, &req_w, &req_h);
700
701         /* adjust actual width/height available for shadow and highlight */
702         act_w -= ( (2*hlt_w) + (2*shd_w) );
703         act_h -= ( (2*hlt_w) + (2*shd_w) );
704
705         if ((req_w > act_w) || (req_h > act_h))
706                 return (True);
707         else
708                 return(False);
709 }
710
711 /************************************************************************
712  *                                                                      *
713  *  Recompute the size of the month panel.                              * 
714  *                                                                      *
715  ************************************************************************/
716 static void 
717 Resize( Widget wid )
718 {
719     XmMonthPanelWidget mw = (XmMonthPanelWidget) wid ;
720     XmManagerWidgetClass super = (XmManagerWidgetClass) xmManagerWidgetClass;
721
722     scale_components(mw);
723     DoLayout(mw);
724     (*super->core_class.resize)((Widget) mw);
725 }
726 \f
727 /***************************************************************************
728  *                                                                         *
729  *  Geometry Manager
730  *                                                                         *
731  ***************************************************************************/
732 static XtGeometryResult
733 GeometryManager( Widget w, XtWidgetGeometry *request, XtWidgetGeometry *reply )
734 {
735         return (XtGeometryYes);
736 }
737 \f
738 /***************************************************************************
739  *                                                                         *
740  *  QueryProc (stub for now)                                               *
741  *                                                                         *
742  ***************************************************************************/
743 static XtGeometryResult 
744 QueryProc( Widget w, XtWidgetGeometry *request, XtWidgetGeometry *reply )
745 {
746 /*    XmMonthPanelWidget mw = (XmMonthPanelWidget) w;*/
747     return(XtGeometryYes);
748 }
749 \f
750
751 #if 0
752 /***************************************************************************
753  *                                                                         *
754  *  CalcSize (stub for now- to be called by QueryProc)                     *
755  *                                                                         *
756  ***************************************************************************/
757 static void
758 CalcSize(XmMonthPanelWidget mw, Dimension *replyWidth , Dimension *replyHeight)
759 {
760     *replyWidth = mw->core.width;
761     *replyHeight = mw->core.height;
762
763 }
764 #endif
765 \f
766 /************************************************************************
767  *                                                                      *
768  *  SetValues                                                           *
769  *                                                                      *
770  ************************************************************************/
771 static Boolean 
772 SetValues( Widget cw, Widget rw, Widget nw, ArgList args, Cardinal *num_args )
773 {
774         XmMonthPanelWidget current = (XmMonthPanelWidget) cw ;
775         XmMonthPanelWidget request = (XmMonthPanelWidget) rw ;
776         XmMonthPanelWidget new_w = (XmMonthPanelWidget) nw ;
777     Boolean relayout = FALSE;
778     Boolean new_date = FALSE;
779
780     if (request->month_panel.show_panel_header != current->month_panel.show_panel_header) {
781        if (request->month_panel.show_panel_header) {
782           XtManageChild(request->month_panel.header);
783           (request->month_panel.display_rows)++;
784        }
785        else {
786           XtUnmanageChild(request->month_panel.header);
787           (request->month_panel.display_rows)--;
788        }
789        relayout = TRUE;
790     }
791
792     if (request->month_panel.show_column_headers != current->month_panel.show_column_headers) {
793        if (request->month_panel.show_column_headers) {
794           int col=0;
795           while (col < 7) {
796              XtManageChild(request->month_panel.day_labels[col]);
797              col++;
798           }
799           (request->month_panel.display_rows)++;
800        }
801        else {
802           int col=0;
803           while (col < 7) {
804              XtUnmanageChild(request->month_panel.day_labels[col]);
805              col++;
806           }
807           (request->month_panel.display_rows)--;
808        }
809        relayout = TRUE;
810     }
811        
812     if (request->month_panel.show_separator != current->month_panel.show_separator) {
813        if (request->month_panel.show_separator) {
814           XtManageChild(request->month_panel.separator);
815           (request->month_panel.display_rows)++;
816        }
817        else {
818           XtUnmanageChild(request->month_panel.separator);
819           (request->month_panel.display_rows)--;
820        }
821        relayout = TRUE;
822     }
823
824     if (request->month_panel.month != current->month_panel.month) {
825
826         /* range check - quietly force to nearest valid value */
827         if (request->month_panel.month < 1)
828                 new_w->month_panel.month = 1;
829         else if (request->month_panel.month > 12)
830                 new_w->month_panel.month = 12;
831
832         new_date = TRUE;
833     }
834
835     if (request->month_panel.year != current->month_panel.year) {
836
837         /* range check - quietly force to nearest valid value */
838         if (request->month_panel.year < 1)
839                 new_w->month_panel.year = 1970;
840         else if (request->month_panel.year > 2037)
841                 new_w->month_panel.year = 2037;
842  
843         new_date = TRUE;
844     }
845
846     if ((request->core.width != current->core.width) ||
847         (request->core.height != current->core.height)) {
848                 relayout = TRUE;
849     }
850
851     if (strcmp(request->month_panel.title_format,
852                 new_w->month_panel.title_format) != 0) {
853         set_header_string(new_w);
854     }
855
856     if (new_date) {
857         set_header_string(new_w);
858         relayout = TRUE;
859     }
860
861     if (relayout)
862         DoLayout(new_w);
863
864     return (relayout);
865 }
866
867 /*
868  * set_header_string
869  *
870  * Sets label in month button of panel, according to the
871  * setting of the titleFormat resource, which is assumed to
872  * be a valid format string for stftime(3)
873  */
874 static void
875 set_header_string(XmMonthPanelWidget mw)
876 {
877         XmString str;
878         struct tm *tm_ret;
879         Tick tmptick;
880         Arg wargs[3];
881         char buf[BUFSIZ];
882         _Xltimeparams localtime_buf;
883
884         tmptick =
885            monthdayyear(mw->month_panel.month, 1 ,mw->month_panel.year);
886         tm_ret = _XLocaltime(&tmptick, localtime_buf);
887         (void) strftime(buf, BUFSIZ, mw->month_panel.title_format, tm_ret);
888
889         str = XmStringCreateLocalized(buf);
890         XtSetArg(wargs[0], XmNlabelString, str);
891         XtSetValues(mw->month_panel.header, wargs, 1);
892         XmStringFree(str);
893 }
894
895 \f
896 /************************************************************************
897  * DayCallback is invoked from day button children.
898  * It invokes MonthPanel's own callbac list, setting the type in the
899  * callback struct to DAY_SELECTION, and the day field to the index of the
900  * button that was pressed.
901  *
902  ************************************************************************/
903 static void DayCallback(Widget w, XtPointer client, XtPointer call)
904 {
905    XmMonthPanelWidget mp = (XmMonthPanelWidget) XtParent(w);
906    XmMonthPanelCallbackStruct data;
907
908    data.type = DAY_SELECTION;
909    data.day = (intptr_t) client;
910
911    XtCallCallbackList((Widget) mp, mp->month_panel.callback, &data);
912 }
913
914 /************************************************************************
915  * MonthCallback is invoked from the header button.
916  * It invokes MonthPanel's own callback list, setting the type in the
917  * callback struct to MONTH_SELECTION, and zeroing out the day field.
918  ************************************************************************/
919 static void MonthCallback(Widget w, XtPointer client, XtPointer call)
920 {
921    XmMonthPanelWidget mp = (XmMonthPanelWidget) XtParent(w);
922    XmMonthPanelCallbackStruct data;
923
924    data.type = MONTH_SELECTION;
925    data.day = 0;
926
927    XtCallCallbackList((Widget) mp, mp->month_panel.callback, &data);
928 }
929
930 /************************************************************************
931  *                                                                      *
932  * XmCreateMonthPanel - convenience interface to XtCreateWidget.        *
933  *                                                                      *
934  ************************************************************************/
935 Widget 
936 XmCreateMonthPanel( Widget parent, char *name, ArgList args, Cardinal argCount )
937 {
938
939     return ( XtCreateWidget( name, 
940                              xmMonthPanelWidgetClass, 
941                              parent, 
942                              args, 
943                              argCount ) );
944 }