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