gtkcalendar.c 75.9 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* GTK - The GIMP Toolkit
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * GTK Calendar Widget
 * Copyright (C) 1998 Cesar Miquel, Shawn T. Amundson and Mattias Grnlund
 * 
 * lib_date routines
 * Copyright (c) 1995, 1996, 1997, 1998 by Steffen Beyer
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <sys/time.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include "gtkcalendar.h"
#include "gdk/gdkkeysyms.h"

/***************************************************************************/
/* The following date routines are taken from the lib_date package.  Keep
 * them seperate in case we want to update them if a newer lib_date comes
 * out with fixes.  */

38
39
40
typedef	 unsigned   int	    N_int;
typedef	 unsigned   long    N_long;
typedef	 signed	    long    Z_long;
41
42
typedef enum { false = FALSE , true = TRUE } boolean;

43
44
#define and	    &&	    /* logical (boolean) operators: lower case */
#define or	    ||
45
46
47

static N_int month_length[2][13] =
{
48
49
  { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
  { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
50
51
52
53
};

static N_int days_in_months[2][14] =
{
54
55
  { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
  { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
56
57
58
59
60
};

static Z_long  calc_days(N_int year, N_int mm, N_int dd);
static N_int   day_of_week(N_int year, N_int mm, N_int dd);
static Z_long  dates_difference(N_int year1, N_int mm1, N_int dd1,
61
				N_int year2, N_int mm2, N_int dd2);
62
63
64
65
66
static N_int   weeks_in_year(N_int year);

static boolean 
leap(N_int year)
{
67
  return((((year % 4) == 0) and ((year % 100) != 0)) or ((year % 400) == 0));
68
69
70
71
72
}

static N_int 
day_of_week(N_int year, N_int mm, N_int dd)
{
73
74
75
76
  Z_long  days;
  
  days = calc_days(year, mm, dd);
  if (days > 0L)
77
    {
78
79
80
      days--;
      days %= 7L;
      days++;
81
    }
82
  return( (N_int) days );
83
84
85
86
}

static N_int weeks_in_year(N_int year)
{
87
  return(52 + ((day_of_week(year,1,1)==4) or (day_of_week(year,12,31)==4)));
88
89
90
91
92
}

static boolean 
check_date(N_int year, N_int mm, N_int dd)
{
93
94
95
96
  if (year < 1) return(false);
  if ((mm < 1) or (mm > 12)) return(false);
  if ((dd < 1) or (dd > month_length[leap(year)][mm])) return(false);
  return(true);
97
98
99
100
101
}

static N_int 
week_number(N_int year, N_int mm, N_int dd)
{
102
103
104
105
106
  N_int first;
  
  first = day_of_week(year,1,1) - 1;
  return( (N_int) ( (dates_difference(year,1,1, year,mm,dd) + first) / 7L ) +
	  (first < 4) );
107
108
109
110
111
}

static Z_long 
year_to_days(N_int year)
{
112
  return( year * 365L + (year / 4) - (year / 100) + (year / 400) );
113
114
115
116
117
118
}


static Z_long 
calc_days(N_int year, N_int mm, N_int dd)
{
119
120
121
122
123
124
  boolean lp;
  
  if (year < 1) return(0L);
  if ((mm < 1) or (mm > 12)) return(0L);
  if ((dd < 1) or (dd > month_length[(lp = leap(year))][mm])) return(0L);
  return( year_to_days(--year) + days_in_months[lp][mm] + dd );
125
126
127
128
129
}

static boolean 
week_of_year(N_int *week, N_int *year, N_int mm, N_int dd)
{
130
131
132
133
134
135
136
137
138
139
140
141
142
  if (check_date(*year,mm,dd))
    {
      *week = week_number(*year,mm,dd);
      if (*week == 0) 
	*week = weeks_in_year(--(*year));
      else if (*week > weeks_in_year(*year))
	{
	  *week = 1;
	  (*year)++;
	}
      return(true);
    }
  return(false);
143
144
145
146
}

static Z_long 
dates_difference(N_int year1, N_int mm1, N_int dd1,
147
		 N_int year2, N_int mm2, N_int dd2)
148
{
149
  return( calc_days(year2, mm2, dd2) - calc_days(year1, mm1, dd1) );
150
151
152
153
}

/** END OF lib_date routines ************************************************/

154
155
156
157
#define CALENDAR_MARGIN		 0
#define CALENDAR_YSEP		 4
#define CALENDAR_XSEP		 4
#define INNER_BORDER		 4
158
159
160

#define DAY_XPAD		 2
#define DAY_YPAD		 2
161
#define DAY_XSEP		 0 /* not really good for small calendar */
162
163
164
#define DAY_YSEP		 0 /* not really good for small calendar */

/* Color usage */
165
166
167
168
169
#define HEADER_FG_COLOR(widget)		 (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
#define HEADER_BG_COLOR(widget)		 (& (widget)->style->bg[GTK_WIDGET_STATE (widget)])
#define DAY_NAME_COLOR(widget)		 (& (widget)->style->dark[GTK_WIDGET_STATE (widget)])
#define NORMAL_DAY_COLOR(widget)	 (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
#define SELECTION_FOCUS_COLOR(widget)	 (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
170
#define SELECTION_NO_FOCUS_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
171
172
173
174
175
176
#define PREV_MONTH_COLOR(widget)	 (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
#define NEXT_MONTH_COLOR(widget)	 (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
#define MARKED_COLOR(widget)		 (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
#define FOREGROUND_COLOR(widget)	 (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
#define BACKGROUND_COLOR(widget)	 (& (widget)->style->base[GTK_WIDGET_STATE (widget)])
#define HIGHLIGHT_BACK_COLOR(widget)	 (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207

#define HEADER_FONT(widget) ((widget)->style->font)
#define LABEL_FONT(widget)   ((widget)->style->font)
#define DAY_FONT(widget)     ((widget)->style->font)

enum {
  ARROW_YEAR_LEFT,
  ARROW_YEAR_RIGHT,
  ARROW_MONTH_LEFT,
  ARROW_MONTH_RIGHT
};

enum {
  MONTH_PREV,
  MONTH_CURRENT,
  MONTH_NEXT
};

enum {
  MONTH_CHANGED_SIGNAL,
  DAY_SELECTED_SIGNAL,
  DAY_SELECTED_DOUBLE_CLICK_SIGNAL,
  PREV_MONTH_SIGNAL,
  NEXT_MONTH_SIGNAL,
  PREV_YEAR_SIGNAL,
  NEXT_YEAR_SIGNAL,
  LAST_SIGNAL
};

static gint gtk_calendar_signals[LAST_SIGNAL] = { 0 };

208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
static GtkWidgetClass *parent_class = NULL;

typedef struct _GtkCalendarPrivateData GtkCalendarPrivateData;
struct _GtkCalendarPrivateData
{
  GdkWindow *header_win;
  GdkWindow *day_name_win;
  GdkWindow *main_win;
  GdkWindow *week_win;
  GdkWindow *arrow_win[4];

  guint header_h, day_name_h, main_h;

  guint	     arrow_state[4];
  guint	     arrow_width;
  guint	     max_month_width;
  guint	     max_year_width;
  
  guint day_width;
  guint week_width;

  guint min_day_width;
  guint max_day_char_width;
  guint max_day_char_ascent;
  guint max_day_char_descent;
  guint max_label_char_ascent;
  guint max_label_char_descent;
  guint max_week_char_width;
  
  /* flags */
  unsigned int dirty_header:1;
  unsigned int dirty_day_names:1;
  unsigned int dirty_main:1;
  unsigned int dirty_week:1;
  unsigned int frozen;
};

#define GTK_CALENDAR_PRIVATE_DATA(widget)  (((GtkCalendarPrivateData*)(GTK_CALENDAR (widget)->private_data)))

247
248
typedef void (*GtkCalendarSignalDate) (GtkObject *object, guint arg1, guint arg2, guint arg3, gpointer data);

249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
static void gtk_calendar_class_init	(GtkCalendarClass *class);
static void gtk_calendar_init		(GtkCalendar *calendar);
static void gtk_calendar_realize	(GtkWidget *widget);
static void gtk_calendar_unrealize	(GtkWidget *widget);
static void gtk_calendar_draw_focus	(GtkWidget *widget);
static void gtk_calendar_size_request	(GtkWidget *widget,
					 GtkRequisition *requisition);
static void gtk_calendar_size_allocate	(GtkWidget *widget,
					 GtkAllocation *allocation);
static gint gtk_calendar_expose		(GtkWidget *widget,
					 GdkEventExpose *event);
static gint gtk_calendar_button_press	(GtkWidget *widget,
					 GdkEventButton *event);
static void gtk_calendar_main_button	(GtkWidget *widget,
					 GdkEventButton *event);
static gint gtk_calendar_motion_notify	(GtkWidget *widget,
					 GdkEventMotion *event);
static gint gtk_calendar_enter_notify	(GtkWidget *widget,
					 GdkEventCrossing *event);
static gint gtk_calendar_leave_notify	(GtkWidget *widget,
					 GdkEventCrossing *event);
static gint gtk_calendar_key_press	(GtkWidget	   *widget,
					 GdkEventKey	   *event);
static gint gtk_calendar_focus_in	(GtkWidget *widget,
					 GdkEventFocus *event);
static gint gtk_calendar_focus_out	(GtkWidget *widget,
					 GdkEventFocus *event);
static void gtk_calendar_state_changed	(GtkWidget *widget,
277
					 GtkStateType previous_state);
278
static void gtk_calendar_style_set	(GtkWidget *widget,
279
					 GtkStyle  *previous_style);
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
static void gtk_calendar_paint_header	    (GtkWidget *widget);
static void gtk_calendar_paint_day_names    (GtkWidget *widget);
static void gtk_calendar_paint_week_numbers (GtkWidget *widget);
static void gtk_calendar_paint_main	    (GtkWidget *widget);


static void gtk_calendar_paint		(GtkWidget    *widget,
					 GdkRectangle *area);
static void gtk_calendar_paint_arrow	(GtkWidget    *widget,
					 guint	       arrow);
static void gtk_calendar_paint_day_num	(GtkWidget    *widget,
					 gint	       day);
static void gtk_calendar_paint_day	(GtkWidget    *widget,
					 gint	       row,
					 gint	       col);
static void gtk_calendar_draw		(GtkWidget    *widget,
					 GdkRectangle *area);
static void gtk_calendar_compute_days	(GtkCalendar  *calendar);
static gint left_x_for_column		(GtkCalendar  *calendar,
					 gint	       column);
static gint top_y_for_row		(GtkCalendar  *calendar,
					 gint	       row);
302
303
304
305

static char    *default_abbreviated_dayname[7];
static char    *default_monthname[12];

306
307
GtkType
gtk_calendar_get_type (void)
308
{
309
310
  static GtkType calendar_type = 0;
  
311
312
313
314
315
316
317
318
319
320
321
322
  if (!calendar_type)
    {
      GtkTypeInfo calendar_info =
      {
	"GtkCalendar",
	sizeof (GtkCalendar),
	sizeof (GtkCalendarClass),
	(GtkClassInitFunc) gtk_calendar_class_init,
	(GtkObjectInitFunc) gtk_calendar_init,
	(GtkArgSetFunc) NULL,
	(GtkArgGetFunc) NULL,
      };
323
324
      
      calendar_type = gtk_type_unique (GTK_TYPE_WIDGET, &calendar_info);
325
    }
326
  
327
328
329
330
331
332
333
334
  return calendar_type;
}

static void
gtk_calendar_class_init (GtkCalendarClass *class)
{
  GtkObjectClass *object_class;
  GtkWidgetClass *widget_class;
335
  
336
337
  object_class = (GtkObjectClass*) class;
  widget_class = (GtkWidgetClass*) class;
338
339
340
  
  parent_class = gtk_type_class (GTK_TYPE_WIDGET);
  
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
  widget_class->realize = gtk_calendar_realize;
  widget_class->unrealize = gtk_calendar_unrealize;
  widget_class->expose_event = gtk_calendar_expose;
  widget_class->draw = gtk_calendar_draw;
  widget_class->draw_focus = gtk_calendar_draw_focus;
  widget_class->size_request = gtk_calendar_size_request;
  widget_class->size_allocate = gtk_calendar_size_allocate;
  widget_class->button_press_event = gtk_calendar_button_press;
  widget_class->motion_notify_event = gtk_calendar_motion_notify;
  widget_class->enter_notify_event = gtk_calendar_enter_notify;
  widget_class->leave_notify_event = gtk_calendar_leave_notify;
  widget_class->key_press_event = gtk_calendar_key_press;
  widget_class->focus_in_event = gtk_calendar_focus_in;
  widget_class->focus_out_event = gtk_calendar_focus_out;
  widget_class->style_set = gtk_calendar_style_set;
  widget_class->state_changed = gtk_calendar_state_changed;
357
  
358
359
360
  gtk_calendar_signals[MONTH_CHANGED_SIGNAL] =
    gtk_signal_new ("month_changed",
		    GTK_RUN_FIRST, object_class->type,
361
		    GTK_SIGNAL_OFFSET (GtkCalendarClass, month_changed),
362
363
364
365
		    gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
  gtk_calendar_signals[DAY_SELECTED_SIGNAL] =
    gtk_signal_new ("day_selected",
		    GTK_RUN_FIRST, object_class->type,
366
		    GTK_SIGNAL_OFFSET (GtkCalendarClass, day_selected),
367
368
369
370
		    gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
  gtk_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL] =
    gtk_signal_new ("day_selected_double_click",
		    GTK_RUN_FIRST, object_class->type,
371
		    GTK_SIGNAL_OFFSET (GtkCalendarClass, day_selected_double_click),
372
373
374
375
		    gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
  gtk_calendar_signals[PREV_MONTH_SIGNAL] =
    gtk_signal_new ("prev_month",
		    GTK_RUN_FIRST, object_class->type,
376
		    GTK_SIGNAL_OFFSET (GtkCalendarClass, prev_month),
377
378
379
380
		    gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
  gtk_calendar_signals[NEXT_MONTH_SIGNAL] =
    gtk_signal_new ("next_month",
		    GTK_RUN_FIRST, object_class->type,
381
		    GTK_SIGNAL_OFFSET (GtkCalendarClass, next_month),
382
383
384
385
		    gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
  gtk_calendar_signals[PREV_YEAR_SIGNAL] =
    gtk_signal_new ("prev_year",
		    GTK_RUN_FIRST, object_class->type,
386
		    GTK_SIGNAL_OFFSET (GtkCalendarClass, prev_year),
387
388
389
390
		    gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
  gtk_calendar_signals[NEXT_YEAR_SIGNAL] =
    gtk_signal_new ("next_year",
		    GTK_RUN_FIRST, object_class->type,
391
		    GTK_SIGNAL_OFFSET (GtkCalendarClass, next_year),
392
		    gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
393
  
394
  gtk_object_class_add_signals (object_class, gtk_calendar_signals, LAST_SIGNAL);
395
396
397
398
399
400
401
402
  
  class->month_changed = NULL;
  class->day_selected = NULL;
  class->day_selected_double_click = NULL;
  class->prev_month = NULL;
  class->next_month = NULL;
  class->prev_year = NULL;
  class->next_year = NULL;
403
404
405
406
407
408
409
410
411
412
413
}

static void
gtk_calendar_init (GtkCalendar *calendar)
{
  time_t secs;
  struct tm *tm;
  gint i;
  char buffer[255];
  time_t tmp_time;
  GtkWidget *widget;
414
  GtkCalendarPrivateData *private_data;
415
  
416
417
  widget = GTK_WIDGET (calendar);
  GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
418
  
419
420
421
  calendar->private_data = (gpointer) malloc (sizeof (GtkCalendarPrivateData));
  private_data = GTK_CALENDAR_PRIVATE_DATA (calendar);

422
423
424
425
426
427
428
  if (!default_abbreviated_dayname[0])
    for (i=0; i<7; i++)
      {
	tmp_time= (i+3)*86400;
	strftime ( buffer, sizeof (buffer), "%a", gmtime (&tmp_time));
	default_abbreviated_dayname[i] = g_strdup (buffer);
      }
429
  
430
431
432
433
434
435
436
  if (!default_monthname[0])
    for (i=0; i<12; i++)
      {
	tmp_time=i*2764800;
	strftime ( buffer, sizeof (buffer), "%B", gmtime (&tmp_time));
	default_monthname[i] = g_strdup (buffer);
      }
437
  
438
439
440
441
442
  /* Set defaults */
  secs = time (NULL);
  tm = localtime (&secs);
  calendar->month = tm->tm_mon;
  calendar->year  = 1900 + tm->tm_year;
443
  
444
445
446
  for (i=0;i<31;i++)
    calendar->marked_date[i] = FALSE;
  calendar->selected_day = 1;
447
  
448
449
  calendar->display_flags = ( GTK_CALENDAR_SHOW_HEADING | 
			      GTK_CALENDAR_SHOW_DAY_NAMES );
450
  
451
452
  calendar->highlight_row = -1;
  calendar->highlight_col = -1;
453
  
454
455
456
457
458
459
460
461
462
463
464
  private_data->max_year_width = 0;
  private_data->max_month_width = 0;
  private_data->max_day_char_width = 0;
  private_data->max_week_char_width = 0;

  private_data->max_day_char_ascent = 0;
  private_data->max_day_char_descent = 0;
  private_data->max_label_char_ascent = 0;
  private_data->max_label_char_descent = 0;

  private_data->arrow_width = 10;
465
  
466
467
468
469
470
  private_data->dirty_header = 0;
  private_data->dirty_day_names = 0;
  private_data->dirty_week = 0;
  private_data->dirty_main = 0;
  private_data->frozen = 0;
471
472
473
}

GtkWidget*
474
gtk_calendar_new (void)
475
{
476
  return GTK_WIDGET (gtk_type_new (GTK_TYPE_CALENDAR));
477
478
479
480
481
}

/* column_from_x: returns the column 0-6 that the
 * x pixel of the xwindow is in */
static gint
482
483
column_from_x (GtkCalendar *calendar,
	       gint	    event_x)
484
485
486
{
  gint c, column;
  gint x_left, x_right;
487
  
488
  column = -1;
489
  
490
491
492
  for (c = 0; c < 7; c++)
    {
      x_left = left_x_for_column (calendar, c);
493
      x_right = x_left + GTK_CALENDAR_PRIVATE_DATA (calendar)->day_width;
494
      
495
496
497
498
499
500
      if (event_x > x_left && event_x < x_right)
	{
	  column = c;
	  break;
	}
    }
501
  
502
503
504
505
506
507
  return column;
}

static gint
row_height (GtkCalendar *calendar)
{
508
  return (GTK_CALENDAR_PRIVATE_DATA (calendar)->main_h - CALENDAR_MARGIN
509
510
511
512
513
514
515
516
	  - ((calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
	     ? CALENDAR_YSEP : CALENDAR_MARGIN)) / 6;
}


/* row_from_y: returns the row 0-5 that the
 * y pixel of the xwindow is in */
static gint
517
518
row_from_y (GtkCalendar *calendar,
	    gint	 event_y)
519
520
521
522
{
  gint r, row;
  gint height;
  gint y_top, y_bottom;
523
  
524
525
  height = row_height (calendar);
  row = -1;
526
  
527
528
529
530
  for (r = 0; r < 6; r++)
    {
      y_top = top_y_for_row (calendar, r);
      y_bottom = y_top + height;
531
      
532
533
534
535
536
537
      if (event_y > y_top && event_y < y_bottom)
	{
	  row = r;
	  break;
	}
    }
538
  
539
540
541
542
543
544
  return row;
}

/* left_x_for_column: returns the x coordinate
 * for the left of the column */
static gint
545
546
left_x_for_column (GtkCalendar *calendar,
		   gint		column)
547
548
549
{
  gint width;
  gint x_left;
550
  
551
  width = GTK_CALENDAR_PRIVATE_DATA (calendar)->day_width;
552
553
554
555
  if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
    x_left =  DAY_XSEP + (width + DAY_XSEP) * column;
  else
    x_left = CALENDAR_MARGIN + (width + DAY_XSEP) * column;
556
  
557
558
559
560
561
562
  return x_left;
}

/* top_y_for_row: returns the y coordinate
 * for the top of the row */
static gint
563
564
top_y_for_row (GtkCalendar *calendar,
	       gint	    row)
565
{
566
  
567
568
569
  return (GTK_CALENDAR_PRIVATE_DATA (calendar)->main_h 
	  - (CALENDAR_MARGIN + (6 - row)
	     * row_height (calendar)));
570
571
572
573
574
}

/* This function should be done by the toolkit, but we don't like the
 * GTK arrows because they don't look good on this widget */
static void
575
576
577
578
579
draw_arrow_right (GdkWindow *window,
		  GdkGC	    *gc,
		  gint	     x,
		  gint	     y,
		  gint	     size)
580
581
{
  gint i;
582
  
583
584
585
586
587
588
589
590
591
592
593
594
595
  for (i = 0; i <= size / 2; i++)
    {
      gdk_draw_line (window, gc,
		     x + i,
		     y + i,
		     x + i,
		     y + size - i);
    }
}

/* This function should be done by the toolkit, but we don't like the
 * GTK arrows because they don't look good on this widget */
static void
596
597
598
599
600
draw_arrow_left (GdkWindow *window,
		 GdkGC	   *gc,
		 gint	    x,
		 gint	    y,
		 gint	    size)
601
602
{
  gint i;
603
  
604
605
606
607
608
609
610
611
612
613
614
615
616
617
  for (i = 0; i <= size / 2; i++)
    {
      gdk_draw_line (window, gc,
		     x + size/2 - i,
		     y + i,
		     x + size/2 - i,
		     y + size - i);
    }
}

static void
gtk_calendar_set_month_prev (GtkCalendar *calendar)
{
  gint month_len;
618
  
619
620
  if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
    return;
621
  
622
623
624
625
626
627
628
  if (calendar->month == 0)
    {
      calendar->month = 11;
      calendar->year--;
    } 
  else 
    calendar->month--;
629
  
630
  month_len = month_length[leap (calendar->year)][calendar->month + 1];
631
  
632
633
  gtk_calendar_freeze (calendar);
  gtk_calendar_compute_days (calendar);
634
  
635
636
637
638
  gtk_signal_emit (GTK_OBJECT (calendar),
		   gtk_calendar_signals[PREV_MONTH_SIGNAL]);
  gtk_signal_emit (GTK_OBJECT (calendar),
		   gtk_calendar_signals[MONTH_CHANGED_SIGNAL]);
639
  
640
641
642
643
644
645
646
647
648
649
650
651
  if (month_len < calendar->selected_day)
    {
      calendar->selected_day = 0;
      gtk_calendar_select_day (calendar, month_len);
    }
  else
    {
      if (calendar->selected_day < 0)
	calendar->selected_day = calendar->selected_day + 1 + month_length[leap (calendar->year)][calendar->month + 1];
      else
	gtk_calendar_select_day (calendar, calendar->selected_day);
    }
652
  
653
654
655
656
657
658
659
660
661
662
  gtk_calendar_select_day (calendar, calendar->selected_day);
  gtk_calendar_paint (GTK_WIDGET (calendar), NULL);
  gtk_calendar_thaw (calendar);
}


static void
gtk_calendar_set_month_next (GtkCalendar *calendar)
{
  gint month_len;
663
  
664
665
  g_return_if_fail (calendar != NULL);
  g_return_if_fail (GTK_IS_WIDGET (calendar));
666
  
667
668
  if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
    return;
669
670
  
  
671
672
673
674
675
676
677
  if (calendar->month == 11)
    {
      calendar->month = 0;
      calendar->year++;
    } 
  else 
    calendar->month++;
678
  
679
680
681
682
683
684
  gtk_calendar_freeze (calendar);
  gtk_calendar_compute_days (calendar);
  gtk_signal_emit (GTK_OBJECT (calendar),
		   gtk_calendar_signals[NEXT_MONTH_SIGNAL]);
  gtk_signal_emit (GTK_OBJECT (calendar),
		   gtk_calendar_signals[MONTH_CHANGED_SIGNAL]);
685
  
686
  month_len = month_length[leap (calendar->year)][calendar->month + 1];
687
  
688
689
690
691
692
693
694
  if (month_len < calendar->selected_day)
    {
      calendar->selected_day = 0;
      gtk_calendar_select_day (calendar, month_len);
    }
  else
    gtk_calendar_select_day (calendar, calendar->selected_day);
695
  
696
697
698
699
700
701
702
703
  gtk_calendar_paint (GTK_WIDGET(calendar), NULL);
  gtk_calendar_thaw (calendar);
}

static void
gtk_calendar_set_year_prev (GtkCalendar *calendar)
{
  gint month_len;
704
  
705
706
  g_return_if_fail (calendar != NULL);
  g_return_if_fail (GTK_IS_WIDGET (calendar));
707
  
708
709
710
711
712
713
714
  calendar->year--;
  gtk_calendar_freeze (calendar);
  gtk_calendar_compute_days (calendar);
  gtk_signal_emit (GTK_OBJECT (calendar),
		   gtk_calendar_signals[PREV_YEAR_SIGNAL]);
  gtk_signal_emit (GTK_OBJECT (calendar),
		   gtk_calendar_signals[MONTH_CHANGED_SIGNAL]);
715
  
716
  month_len = month_length[leap (calendar->year)][calendar->month + 1];
717
  
718
719
720
721
722
723
724
  if (month_len < calendar->selected_day)
    {
      calendar->selected_day = 0;
      gtk_calendar_select_day (calendar, month_len);
    }
  else
    gtk_calendar_select_day (calendar, calendar->selected_day);
725
  
726
727
728
729
730
731
732
733
734
  gtk_calendar_paint (GTK_WIDGET (calendar), NULL);
  gtk_calendar_thaw (calendar);
}

static void
gtk_calendar_set_year_next (GtkCalendar *calendar)
{
  gint month_len;
  GtkWidget *widget;
735
  
736
737
  g_return_if_fail (calendar != NULL);
  g_return_if_fail (GTK_IS_WIDGET (calendar));
738
  
739
  widget = GTK_WIDGET (calendar);
740
  
741
  gtk_calendar_freeze (calendar);
742
  
743
744
745
746
747
748
  calendar->year++;
  gtk_calendar_compute_days (calendar);
  gtk_signal_emit (GTK_OBJECT (calendar),
		   gtk_calendar_signals[NEXT_YEAR_SIGNAL]);
  gtk_signal_emit (GTK_OBJECT (calendar),
		   gtk_calendar_signals[MONTH_CHANGED_SIGNAL]);
749
  
750
  month_len = month_length[leap (calendar->year)][calendar->month + 1];
751
  
752
753
754
755
756
757
758
  if (month_len < calendar->selected_day)
    {
      calendar->selected_day = 0;
      gtk_calendar_select_day (calendar, month_len);
    }
  else
    gtk_calendar_select_day (calendar, calendar->selected_day);
759
  
760
761
762
763
764
  gtk_calendar_paint (GTK_WIDGET (calendar), NULL);
  gtk_calendar_thaw (calendar);
}

static void
765
gtk_calendar_main_button (GtkWidget	 *widget,
766
767
768
769
770
771
			  GdkEventButton *event)
{
  GtkCalendar *calendar;
  gint x, y;
  gint row, col;
  gint day_month;
772
  
773
  calendar = GTK_CALENDAR (widget);
774
  
775
776
  x = (gint) (event->x);
  y = (gint) (event->y);
777
  
778
779
  row = row_from_y (calendar, y);
  col = column_from_x (calendar, x);
780
  
781
  day_month = calendar->day_month[row][col];
782
  
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
  if (day_month == MONTH_CURRENT)
    {
      if (event->type == GDK_2BUTTON_PRESS)
	gtk_signal_emit (GTK_OBJECT (calendar),
			 gtk_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL]);
      else
	{
	  if (!GTK_WIDGET_HAS_FOCUS (widget))
	    gtk_widget_grab_focus (widget);
	  gtk_calendar_select_day (calendar, calendar->day[row][col]);
	}
    }
  else if (day_month == MONTH_PREV)
    gtk_calendar_set_month_prev (calendar);
  else if (day_month == MONTH_NEXT)
    gtk_calendar_set_month_next (calendar);
}

static void
gtk_calendar_realize_arrows (GtkWidget *widget)
{
  GtkCalendar *calendar;
805
  GtkCalendarPrivateData *private_data;
806
807
808
  GdkWindowAttr attributes;
  gint attributes_mask;
  gint i;
809
  
810
811
  g_return_if_fail (widget != NULL);
  g_return_if_fail (GTK_IS_CALENDAR (widget));
812
  
813
  calendar = GTK_CALENDAR (widget);
814
815
  private_data = GTK_CALENDAR_PRIVATE_DATA (widget);

816
817
818
819
820
821
822
823
824
825
826
827
828
  /* Arrow windows ------------------------------------- */
  if (! (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
      && (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING))
    {
      attributes.wclass = GDK_INPUT_OUTPUT;
      attributes.window_type = GDK_WINDOW_CHILD;
      attributes.visual = gtk_widget_get_visual (widget);
      attributes.colormap = gtk_widget_get_colormap (widget);
      attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK
			       | GDK_BUTTON_PRESS_MASK	| GDK_BUTTON_RELEASE_MASK
			       | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
      attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
      attributes.y = 3;
829
830
      attributes.width = private_data->arrow_width;
      attributes.height = private_data->header_h - 7;
831
832
833
834
835
836
837
838
      for (i = 0; i < 4; i++)
	{
	  switch (i)
	    {
	    case ARROW_MONTH_LEFT:
	      attributes.x = 3;
	      break;
	    case ARROW_MONTH_RIGHT:
839
840
	      attributes.x = (private_data->arrow_width 
			      + private_data->max_month_width);
841
842
	      break;
	    case ARROW_YEAR_LEFT:
843
844
845
	      attributes.x = (widget->allocation.width - 4
			      - (3 + 2*private_data->arrow_width 
				 + private_data->max_year_width));
846
847
	      break;
	    case ARROW_YEAR_RIGHT:
848
849
	      attributes.x = (widget->allocation.width - 4 
			      - 3 - private_data->arrow_width);
850
851
	      break;
	    }
852
853
854
855
856
	  private_data->arrow_win[i] = gdk_window_new (private_data->header_win,
						       &attributes, 
						       attributes_mask);
	  private_data->arrow_state[i] = GTK_STATE_NORMAL;
	  gdk_window_set_background (private_data->arrow_win[i],
857
				     HEADER_BG_COLOR (GTK_WIDGET (calendar)));
858
859
	  gdk_window_show (private_data->arrow_win[i]);
	  gdk_window_set_user_data (private_data->arrow_win[i], widget);
860
861
862
	}
    }
  else
863
864
865
866
    {
      for (i = 0; i < 4; i++)
	private_data->arrow_win[i] = NULL;
    }
867
868
869
870
871
872
}

static void
gtk_calendar_realize_header (GtkWidget *widget)
{
  GtkCalendar *calendar;
873
  GtkCalendarPrivateData *private_data;
874
875
  GdkWindowAttr attributes;
  gint attributes_mask;
876
  
877
878
  g_return_if_fail (widget != NULL);
  g_return_if_fail (GTK_IS_CALENDAR (widget));
879
  
880
  calendar = GTK_CALENDAR (widget);
881
882
  private_data = GTK_CALENDAR_PRIVATE_DATA (widget);

883
884
885
886
887
888
889
890
891
  /* Header window ------------------------------------- */
  if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)
    {
      attributes.wclass = GDK_INPUT_OUTPUT;
      attributes.window_type = GDK_WINDOW_CHILD;
      attributes.visual = gtk_widget_get_visual (widget);
      attributes.colormap = gtk_widget_get_colormap (widget);
      attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
      attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
892
893
894
895
896
      attributes.x = 2;
      attributes.y = 2;
      attributes.width = widget->allocation.width - 4;
      attributes.height = private_data->header_h;
      private_data->header_win = gdk_window_new (widget->window,
897
					     &attributes, attributes_mask);
898
      
899
      gdk_window_set_background (private_data->header_win,
900
				 HEADER_BG_COLOR (GTK_WIDGET (calendar)));
901
902
      gdk_window_show (private_data->header_win);
      gdk_window_set_user_data (private_data->header_win, widget);
903
      
904
905
    }
  else
906
907
908
    {
      private_data->header_win = NULL;
    }
909
910
911
912
913
914
915
  gtk_calendar_realize_arrows (widget);
}

static void
gtk_calendar_realize_day_names (GtkWidget *widget)
{
  GtkCalendar *calendar;
916
  GtkCalendarPrivateData *private_data;
917
918
  GdkWindowAttr attributes;
  gint attributes_mask;
919
  
920
921
  g_return_if_fail (widget != NULL);
  g_return_if_fail (GTK_IS_CALENDAR (widget));
922
  
923
  calendar = GTK_CALENDAR (widget);
924
925
  private_data = GTK_CALENDAR_PRIVATE_DATA (widget);

926
  /* Day names	window --------------------------------- */
927
928
929
930
931
932
933
934
935
  if ( calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
    {
      attributes.wclass = GDK_INPUT_OUTPUT;
      attributes.window_type = GDK_WINDOW_CHILD;
      attributes.visual = gtk_widget_get_visual (widget);
      attributes.colormap = gtk_widget_get_colormap (widget);
      attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
      attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
      attributes.x = (widget->style->klass->xthickness + INNER_BORDER);
936
937
938
939
940
941
942
943
944
945
946
947
948
      attributes.y = private_data->header_h + (widget->style->klass->ythickness 
					   + INNER_BORDER);
      attributes.width = (widget->allocation.width 
			  - (widget->style->klass->xthickness + INNER_BORDER) 
			  * 2);
      attributes.height = private_data->day_name_h;
      private_data->day_name_win = gdk_window_new (widget->window,
						   &attributes, 
						   attributes_mask);
      gdk_window_set_background (private_data->day_name_win, 
				 BACKGROUND_COLOR ( GTK_WIDGET ( calendar)));
      gdk_window_show (private_data->day_name_win);
      gdk_window_set_user_data (private_data->day_name_win, widget);
949
950
    }
  else
951
952
953
    {
      private_data->day_name_win = NULL;
    }
954
955
956
957
958
959
}

static void
gtk_calendar_realize_week_numbers (GtkWidget *widget)
{
  GtkCalendar *calendar;
960
  GtkCalendarPrivateData *private_data;
961
962
  GdkWindowAttr attributes;
  gint attributes_mask;
963
  
964
965
  g_return_if_fail (widget != NULL);
  g_return_if_fail (GTK_IS_CALENDAR (widget));
966
  
967
  calendar = GTK_CALENDAR (widget);
968
969
  private_data = GTK_CALENDAR_PRIVATE_DATA (widget);

970
971
972
973
974
975
976
977
  /* Week number window -------------------------------- */
  if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
    {
      attributes.wclass = GDK_INPUT_OUTPUT;
      attributes.window_type = GDK_WINDOW_CHILD;
      attributes.visual = gtk_widget_get_visual (widget);
      attributes.colormap = gtk_widget_get_colormap (widget);
      attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
978
      
979
980
      attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
      attributes.x = + (widget->style->klass->xthickness + INNER_BORDER);
981
      attributes.y = (private_data->header_h + private_data->day_name_h 
982
		      + (widget->style->klass->ythickness + INNER_BORDER));
983
984
985
986
987
988
989
990
      attributes.width = private_data->week_width;
      attributes.height = private_data->main_h;
      private_data->week_win = gdk_window_new (widget->window,
					       &attributes, attributes_mask);
      gdk_window_set_background (private_data->week_win,  
				 BACKGROUND_COLOR (GTK_WIDGET (calendar)));
      gdk_window_show (private_data->week_win);
      gdk_window_set_user_data (private_data->week_win, widget);
991
992
    } 
  else
993
994
995
    {
      private_data->week_win = NULL;
    }
996
997
998
999
1000
1001
}

static void
gtk_calendar_realize (GtkWidget *widget)
{
  GtkCalendar *calendar;
1002
  GtkCalendarPrivateData *private_data;
1003
1004
  GdkWindowAttr attributes;
  gint attributes_mask;
1005
  
1006
1007
  g_return_if_fail (widget != NULL);
  g_return_if_fail (GTK_IS_CALENDAR (widget));
1008
  
1009
  calendar = GTK_CALENDAR (widget);
1010
  private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1011
  
1012
1013
  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
  gtk_calendar_compute_days (calendar);
1014
  
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
  attributes.x = widget->allocation.x;
  attributes.y = widget->allocation.y;
  attributes.width = widget->allocation.width;
  attributes.height = widget->allocation.height;
  attributes.wclass = GDK_INPUT_OUTPUT;
  attributes.window_type = GDK_WINDOW_CHILD;
  attributes.event_mask =  (gtk_widget_get_events (widget) 
			    | GDK_EXPOSURE_MASK |GDK_KEY_PRESS_MASK);
  attributes.visual = gtk_widget_get_visual (widget);
  attributes.colormap = gtk_widget_get_colormap (widget);
1025
  
1026
1027
1028
  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
  widget->window = gdk_window_new (widget->parent->window,
				   &attributes, attributes_mask);
1029
  
1030
  widget->style = gtk_style_attach (widget->style, widget->window);
1031
  
1032
1033
  /* Header window ------------------------------------- */
  gtk_calendar_realize_header (widget);
1034
  /* Day names	window --------------------------------- */
1035
1036
1037
  gtk_calendar_realize_day_names (widget);
  /* Week number window -------------------------------- */
  gtk_calendar_realize_week_numbers (widget);
1038
  /* Main Window --------------------------------------	 */
1039
1040
1041
  attributes.event_mask =  (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK
			    | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
			    | GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK);
1042
  
1043
  if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1044
    attributes.x = private_data->week_width;
1045
1046
1047
  else
    attributes.x = 0;
  attributes.x += (widget->style->klass->xthickness + INNER_BORDER);
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
  attributes.y = (private_data->header_h + private_data->day_name_h 
		  + (widget->style->klass->ythickness + INNER_BORDER));
  attributes.width = (widget->allocation.width - attributes.x 
		      - (widget->style->klass->xthickness + INNER_BORDER));
  attributes.height = private_data->main_h;
  private_data->main_win = gdk_window_new (widget->window,
					   &attributes, attributes_mask);
  gdk_window_set_background (private_data->main_win, 
			     BACKGROUND_COLOR ( GTK_WIDGET ( calendar)));
  gdk_window_show (private_data->main_win);
  gdk_window_set_user_data (private_data->main_win, widget);
1059
1060
1061
  gdk_window_set_background (widget->window, BACKGROUND_COLOR (widget));
  gdk_window_show (widget->window);
  gdk_window_set_user_data (widget->window, widget);
1062
  
1063
1064
1065
1066
1067
1068
1069
1070
  /* Set widgets gc */
  calendar->gc = gdk_gc_new (widget->window);
}

static void
gtk_calendar_unrealize (GtkWidget *widget)
{
  GtkCalendar *calendar;
1071
  GtkCalendarPrivateData *private_data;
1072
  gint i;
1073
  
1074
1075
  g_return_if_fail (widget != NULL);
  g_return_if_fail (GTK_IS_CALENDAR (widget));
1076
  
1077
  calendar = GTK_CALENDAR (widget);
1078
  private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1079
  
1080
  if (private_data->header_win)
1081
    {
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
      for (i = 0; i < 4; i++)
	{
	  if (private_data->arrow_win[i])
	    {
	      gdk_window_set_user_data (private_data->arrow_win[i], NULL);
	      gdk_window_destroy (private_data->arrow_win[i]);
	      private_data->arrow_win[i] = NULL;
	    }
	}
      gdk_window_set_user_data (private_data->header_win, NULL);
      gdk_window_destroy (private_data->header_win);
      private_data->header_win = NULL;
1094
    }
1095
  
1096
  if (private_data->week_win)
1097
    {
1098
1099
1100
      gdk_window_set_user_data (private_data->week_win, NULL);
      gdk_window_destroy (private_data->week_win);
      private_data->week_win = NULL;      
1101
    }
1102
  
1103
  if (private_data->main_win)
1104
    {
1105
1106
1107
      gdk_window_set_user_data (private_data->main_win, NULL);
      gdk_window_destroy (private_data->main_win);
      private_data->main_win = NULL;      
1108
    }
1109
  
1110
1111
1112
1113
1114
  if (GTK_WIDGET_CLASS (parent_class)->unrealize)
    (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
}

static void
1115
gtk_calendar_size_request (GtkWidget	  *widget,
1116
1117
1118
			   GtkRequisition *requisition)
{
  GtkCalendar *calendar;
1119
1120
  GtkCalendarPrivateData *private_data;

1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
  gint height;
  gint i;
  gchar buffer[255];
  gint calendar_margin = CALENDAR_MARGIN;
  gint header_width, main_width;
  gint lbearing;
  gint rbearing;
  gint ascent;
  gint descent;
  gint width;
1131
  
1132
  calendar = GTK_CALENDAR (widget);
1133
  private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1134
  
1135
  /*
1136
   * Calculate the requisition	width for the widget.
1137
   */
1138
  
1139
  /* Header width */
1140
  
1141
1142
  if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)
    {
1143
      private_data->max_month_width = 0;
1144
      for (i = 0; i < 12; i++)
1145
1146
1147
1148
1149
1150
	{
	  private_data->max_month_width = MAX (private_data->max_month_width,
					       gdk_string_measure (HEADER_FONT (widget),
								   default_monthname[i]) + 8);
	}
      private_data->max_year_width = 0;
1151
1152
1153
      for (i=0; i<10; i++)
	{
	  sprintf (buffer, "%d%d%d%d", i,i,i,i);
1154
1155
1156
	  private_data->max_year_width = MAX (private_data->max_year_width,
					      gdk_string_measure (HEADER_FONT (widget),
								  buffer) + 8);
1157
1158
1159
1160
	}
    } 
  else 
    {
1161
1162
      private_data->max_month_width = 0;
      private_data->max_year_width = 0;
1163
    }
1164
  
1165
  if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1166
1167
    header_width = (private_data->max_month_width 
		    + private_data->max_year_width
1168
1169
		    + 3 * 3);
  else
1170
1171
1172
1173
    header_width = (private_data->max_month_width 
		    + private_data->max_year_width
		    + 4 * private_data->arrow_width + 3 * 3);

1174
  /* Mainwindow labels width */
1175
  
1176
  private_data->max_day_char_width = 0;
1177
1178
1179
  for (i = 0; i < 9; i++)
    {
      sprintf (buffer, "%d%d", i, i);
1180
      private_data->min_day_width = MAX (private_data->max_day_char_width,
1181
1182
1183
1184
				     gdk_string_measure (DAY_FONT (widget),
							 buffer));
    }
  /* We add one to max_day_char_width to be able to make the marked day "bold" */
1185
  private_data->max_day_char_width = private_data->min_day_width / 2 +1;
1186
  
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
  if (calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
    for (i = 0; i < 7; i++)
      {
	gdk_text_extents (LABEL_FONT (widget),
			  default_abbreviated_dayname[i],
			  strlen(default_abbreviated_dayname[i]),
			  &lbearing,
			  &rbearing,
			  &width,
			  &ascent,
			  &descent);
1198
1199
	private_data->min_day_width = MAX (private_data->min_day_width, width);
	private_data->max_label_char_ascent = MAX (private_data->max_label_char_ascent, 
1200
					       ascent);
1201
1202
	private_data->max_label_char_descent = MAX (private_data->max_label_char_descent, 
						    descent);
1203
      }
1204
  
1205
  private_data->max_week_char_width = 0;
1206
1207
1208
1209
  if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
    for (i = 0; i < 9; i++)
      {
	sprintf (buffer, "%d%d", i, i);
1210
	private_data->max_week_char_width = MAX (private_data->max_week_char_width,
1211
1212
					     gdk_string_measure (LABEL_FONT (widget), buffer) / 2);
      }