1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
5 * Copyright (C) 1998 Cesar Miquel, Shawn T. Amundson and Mattias Grönlund
8 * Copyright (c) 1995, 1996, 1997, 1998 by Steffen Beyer
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the Free
22 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include "gtkcalendar.h"
31 #include "gdk/gdkkeysyms.h"
33 /***************************************************************************/
34 /* The following date routines are taken from the lib_date package. Keep
35 * them seperate in case we want to update them if a newer lib_date comes
38 typedef unsigned int N_int;
39 typedef unsigned long N_long;
40 typedef signed long Z_long;
41 typedef enum { false = FALSE , true = TRUE } boolean;
43 #define and && /* logical (boolean) operators: lower case */
46 static const N_int month_length[2][13] =
48 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
49 { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
52 static const N_int days_in_months[2][14] =
54 { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
55 { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
58 static Z_long calc_days(N_int year, N_int mm, N_int dd);
59 static N_int day_of_week(N_int year, N_int mm, N_int dd);
60 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 static N_int weeks_in_year(N_int year);
67 return((((year % 4) == 0) and ((year % 100) != 0)) or ((year % 400) == 0));
71 day_of_week(N_int year, N_int mm, N_int dd)
75 days = calc_days(year, mm, dd);
82 return( (N_int) days );
85 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)));
91 check_date(N_int year, N_int mm, N_int dd)
93 if (year < 1) return(false);
94 if ((mm < 1) or (mm > 12)) return(false);
95 if ((dd < 1) or (dd > month_length[leap(year)][mm])) return(false);
100 week_number(N_int year, N_int mm, N_int dd)
104 first = day_of_week(year,1,1) - 1;
105 return( (N_int) ( (dates_difference(year,1,1, year,mm,dd) + first) / 7L ) +
110 year_to_days(N_int year)
112 return( year * 365L + (year / 4) - (year / 100) + (year / 400) );
117 calc_days(N_int year, N_int mm, N_int dd)
121 if (year < 1) return(0L);
122 if ((mm < 1) or (mm > 12)) return(0L);
123 if ((dd < 1) or (dd > month_length[(lp = leap(year))][mm])) return(0L);
124 return( year_to_days(--year) + days_in_months[lp][mm] + dd );
128 week_of_year(N_int *week, N_int *year, N_int mm, N_int dd)
130 if (check_date(*year,mm,dd))
132 *week = week_number(*year,mm,dd);
134 *week = weeks_in_year(--(*year));
135 else if (*week > weeks_in_year(*year))
146 dates_difference(N_int year1, N_int mm1, N_int dd1,
147 N_int year2, N_int mm2, N_int dd2)
149 return( calc_days(year2, mm2, dd2) - calc_days(year1, mm1, dd1) );
152 /** END OF lib_date routines ************************************************/
154 #define CALENDAR_MARGIN 0
155 #define CALENDAR_YSEP 4
156 #define CALENDAR_XSEP 4
157 #define INNER_BORDER 4
161 #define DAY_XSEP 0 /* not really good for small calendar */
162 #define DAY_YSEP 0 /* not really good for small calendar */
165 #define HEADER_FG_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
166 #define HEADER_BG_COLOR(widget) (& (widget)->style->bg[GTK_WIDGET_STATE (widget)])
167 #define DAY_NAME_COLOR(widget) (& (widget)->style->bg[GTK_STATE_SELECTED])
168 #define NORMAL_DAY_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
169 #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 #define PREV_MONTH_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
172 #define NEXT_MONTH_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
173 #define MARKED_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
174 #define FOREGROUND_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
175 #define BACKGROUND_COLOR(widget) (& (widget)->style->base[GTK_WIDGET_STATE (widget)])
176 #define HIGHLIGHT_BACK_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
178 #define HEADER_FONT(widget) ((widget)->style->font)
179 #define LABEL_FONT(widget) ((widget)->style->font)
180 #define DAY_FONT(widget) ((widget)->style->font)
196 MONTH_CHANGED_SIGNAL,
198 DAY_SELECTED_DOUBLE_CLICK_SIGNAL,
206 static gint gtk_calendar_signals[LAST_SIGNAL] = { 0 };
208 static GtkWidgetClass *parent_class = NULL;
210 typedef struct _GtkCalendarPrivateData GtkCalendarPrivateData;
211 struct _GtkCalendarPrivateData
213 GdkWindow *header_win;
214 GdkWindow *day_name_win;
217 GdkWindow *arrow_win[4];
223 guint arrow_state[4];
225 guint max_month_width;
226 guint max_year_width;
232 guint max_day_char_width;
233 guint max_day_char_ascent;
234 guint max_day_char_descent;
235 guint max_label_char_ascent;
236 guint max_label_char_descent;
237 guint max_week_char_width;
242 guint dirty_header : 1;
243 guint dirty_day_names : 1;
244 guint dirty_main : 1;
245 guint dirty_week : 1;
248 #define GTK_CALENDAR_PRIVATE_DATA(widget) (((GtkCalendarPrivateData*)(GTK_CALENDAR (widget)->private_data)))
250 typedef void (*GtkCalendarSignalDate) (GtkObject *object, guint arg1, guint arg2, guint arg3, gpointer data);
252 static void gtk_calendar_class_init (GtkCalendarClass *class);
253 static void gtk_calendar_init (GtkCalendar *calendar);
254 static void gtk_calendar_realize (GtkWidget *widget);
255 static void gtk_calendar_unrealize (GtkWidget *widget);
256 static void gtk_calendar_draw_focus (GtkWidget *widget);
257 static void gtk_calendar_size_request (GtkWidget *widget,
258 GtkRequisition *requisition);
259 static void gtk_calendar_size_allocate (GtkWidget *widget,
260 GtkAllocation *allocation);
261 static gint gtk_calendar_expose (GtkWidget *widget,
262 GdkEventExpose *event);
263 static gint gtk_calendar_button_press (GtkWidget *widget,
264 GdkEventButton *event);
265 static void gtk_calendar_main_button (GtkWidget *widget,
266 GdkEventButton *event);
267 static gint gtk_calendar_motion_notify (GtkWidget *widget,
268 GdkEventMotion *event);
269 static gint gtk_calendar_enter_notify (GtkWidget *widget,
270 GdkEventCrossing *event);
271 static gint gtk_calendar_leave_notify (GtkWidget *widget,
272 GdkEventCrossing *event);
273 static gint gtk_calendar_key_press (GtkWidget *widget,
275 static gint gtk_calendar_focus_in (GtkWidget *widget,
276 GdkEventFocus *event);
277 static gint gtk_calendar_focus_out (GtkWidget *widget,
278 GdkEventFocus *event);
279 static void gtk_calendar_state_changed (GtkWidget *widget,
280 GtkStateType previous_state);
281 static void gtk_calendar_style_set (GtkWidget *widget,
282 GtkStyle *previous_style);
283 static void gtk_calendar_paint_header (GtkWidget *widget);
284 static void gtk_calendar_paint_day_names (GtkWidget *widget);
285 static void gtk_calendar_paint_week_numbers (GtkWidget *widget);
286 static void gtk_calendar_paint_main (GtkWidget *widget);
289 static void gtk_calendar_paint (GtkWidget *widget,
291 static void gtk_calendar_paint_arrow (GtkWidget *widget,
293 static void gtk_calendar_paint_day_num (GtkWidget *widget,
295 static void gtk_calendar_paint_day (GtkWidget *widget,
298 static void gtk_calendar_draw (GtkWidget *widget,
300 static void gtk_calendar_compute_days (GtkCalendar *calendar);
301 static gint left_x_for_column (GtkCalendar *calendar,
303 static gint top_y_for_row (GtkCalendar *calendar,
306 static char *default_abbreviated_dayname[7];
307 static char *default_monthname[12];
310 gtk_calendar_get_type (void)
312 static GtkType calendar_type = 0;
316 static const GtkTypeInfo calendar_info =
319 sizeof (GtkCalendar),
320 sizeof (GtkCalendarClass),
321 (GtkClassInitFunc) gtk_calendar_class_init,
322 (GtkObjectInitFunc) gtk_calendar_init,
323 (GtkArgSetFunc) NULL,
324 (GtkArgGetFunc) NULL,
327 calendar_type = gtk_type_unique (GTK_TYPE_WIDGET, &calendar_info);
330 return calendar_type;
334 gtk_calendar_class_init (GtkCalendarClass *class)
336 GtkObjectClass *object_class;
337 GtkWidgetClass *widget_class;
339 object_class = (GtkObjectClass*) class;
340 widget_class = (GtkWidgetClass*) class;
342 parent_class = gtk_type_class (GTK_TYPE_WIDGET);
344 widget_class->realize = gtk_calendar_realize;
345 widget_class->unrealize = gtk_calendar_unrealize;
346 widget_class->expose_event = gtk_calendar_expose;
347 widget_class->draw = gtk_calendar_draw;
348 widget_class->draw_focus = gtk_calendar_draw_focus;
349 widget_class->size_request = gtk_calendar_size_request;
350 widget_class->size_allocate = gtk_calendar_size_allocate;
351 widget_class->button_press_event = gtk_calendar_button_press;
352 widget_class->motion_notify_event = gtk_calendar_motion_notify;
353 widget_class->enter_notify_event = gtk_calendar_enter_notify;
354 widget_class->leave_notify_event = gtk_calendar_leave_notify;
355 widget_class->key_press_event = gtk_calendar_key_press;
356 widget_class->focus_in_event = gtk_calendar_focus_in;
357 widget_class->focus_out_event = gtk_calendar_focus_out;
358 widget_class->style_set = gtk_calendar_style_set;
359 widget_class->state_changed = gtk_calendar_state_changed;
361 gtk_calendar_signals[MONTH_CHANGED_SIGNAL] =
362 gtk_signal_new ("month_changed",
363 GTK_RUN_FIRST, object_class->type,
364 GTK_SIGNAL_OFFSET (GtkCalendarClass, month_changed),
365 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
366 gtk_calendar_signals[DAY_SELECTED_SIGNAL] =
367 gtk_signal_new ("day_selected",
368 GTK_RUN_FIRST, object_class->type,
369 GTK_SIGNAL_OFFSET (GtkCalendarClass, day_selected),
370 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
371 gtk_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL] =
372 gtk_signal_new ("day_selected_double_click",
373 GTK_RUN_FIRST, object_class->type,
374 GTK_SIGNAL_OFFSET (GtkCalendarClass, day_selected_double_click),
375 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
376 gtk_calendar_signals[PREV_MONTH_SIGNAL] =
377 gtk_signal_new ("prev_month",
378 GTK_RUN_FIRST, object_class->type,
379 GTK_SIGNAL_OFFSET (GtkCalendarClass, prev_month),
380 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
381 gtk_calendar_signals[NEXT_MONTH_SIGNAL] =
382 gtk_signal_new ("next_month",
383 GTK_RUN_FIRST, object_class->type,
384 GTK_SIGNAL_OFFSET (GtkCalendarClass, next_month),
385 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
386 gtk_calendar_signals[PREV_YEAR_SIGNAL] =
387 gtk_signal_new ("prev_year",
388 GTK_RUN_FIRST, object_class->type,
389 GTK_SIGNAL_OFFSET (GtkCalendarClass, prev_year),
390 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
391 gtk_calendar_signals[NEXT_YEAR_SIGNAL] =
392 gtk_signal_new ("next_year",
393 GTK_RUN_FIRST, object_class->type,
394 GTK_SIGNAL_OFFSET (GtkCalendarClass, next_year),
395 gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
397 gtk_object_class_add_signals (object_class, gtk_calendar_signals, LAST_SIGNAL);
399 class->month_changed = NULL;
400 class->day_selected = NULL;
401 class->day_selected_double_click = NULL;
402 class->prev_month = NULL;
403 class->next_month = NULL;
404 class->prev_year = NULL;
405 class->next_year = NULL;
409 gtk_calendar_init (GtkCalendar *calendar)
417 GtkCalendarPrivateData *private_data;
419 widget = GTK_WIDGET (calendar);
420 GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
422 calendar->private_data = (gpointer) malloc (sizeof (GtkCalendarPrivateData));
423 private_data = GTK_CALENDAR_PRIVATE_DATA (calendar);
425 if (!default_abbreviated_dayname[0])
428 tmp_time= (i+3)*86400;
429 strftime ( buffer, sizeof (buffer), "%a", gmtime (&tmp_time));
430 default_abbreviated_dayname[i] = g_strdup (buffer);
433 if (!default_monthname[0])
437 strftime ( buffer, sizeof (buffer), "%B", gmtime (&tmp_time));
438 default_monthname[i] = g_strdup (buffer);
443 tm = localtime (&secs);
444 calendar->month = tm->tm_mon;
445 calendar->year = 1900 + tm->tm_year;
448 calendar->marked_date[i] = FALSE;
449 calendar->selected_day = 1;
451 calendar->display_flags = ( GTK_CALENDAR_SHOW_HEADING |
452 GTK_CALENDAR_SHOW_DAY_NAMES );
454 calendar->highlight_row = -1;
455 calendar->highlight_col = -1;
457 calendar->focus_row = -1;
458 calendar->focus_col = -1;
459 calendar->xor_gc = NULL;
461 private_data->max_year_width = 0;
462 private_data->max_month_width = 0;
463 private_data->max_day_char_width = 0;
464 private_data->max_week_char_width = 0;
466 private_data->max_day_char_ascent = 0;
467 private_data->max_day_char_descent = 0;
468 private_data->max_label_char_ascent = 0;
469 private_data->max_label_char_descent = 0;
471 private_data->arrow_width = 10;
473 private_data->freeze_count = 0;
475 private_data->dirty_header = 0;
476 private_data->dirty_day_names = 0;
477 private_data->dirty_week = 0;
478 private_data->dirty_main = 0;
482 gtk_calendar_new (void)
484 return GTK_WIDGET (gtk_type_new (GTK_TYPE_CALENDAR));
487 /* column_from_x: returns the column 0-6 that the
488 * x pixel of the xwindow is in */
490 column_from_x (GtkCalendar *calendar,
494 gint x_left, x_right;
498 for (c = 0; c < 7; c++)
500 x_left = left_x_for_column (calendar, c);
501 x_right = x_left + GTK_CALENDAR_PRIVATE_DATA (calendar)->day_width;
503 if (event_x > x_left && event_x < x_right)
514 row_height (GtkCalendar *calendar)
516 return (GTK_CALENDAR_PRIVATE_DATA (calendar)->main_h - CALENDAR_MARGIN
517 - ((calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
518 ? CALENDAR_YSEP : CALENDAR_MARGIN)) / 6;
522 /* row_from_y: returns the row 0-5 that the
523 * y pixel of the xwindow is in */
525 row_from_y (GtkCalendar *calendar,
530 gint y_top, y_bottom;
532 height = row_height (calendar);
535 for (r = 0; r < 6; r++)
537 y_top = top_y_for_row (calendar, r);
538 y_bottom = y_top + height;
540 if (event_y > y_top && event_y < y_bottom)
550 /* left_x_for_column: returns the x coordinate
551 * for the left of the column */
553 left_x_for_column (GtkCalendar *calendar,
559 width = GTK_CALENDAR_PRIVATE_DATA (calendar)->day_width;
560 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
561 x_left = DAY_XSEP + (width + DAY_XSEP) * column;
563 x_left = CALENDAR_MARGIN + (width + DAY_XSEP) * column;
568 /* top_y_for_row: returns the y coordinate
569 * for the top of the row */
571 top_y_for_row (GtkCalendar *calendar,
575 return (GTK_CALENDAR_PRIVATE_DATA (calendar)->main_h
576 - (CALENDAR_MARGIN + (6 - row)
577 * row_height (calendar)));
580 /* This function should be done by the toolkit, but we don't like the
581 * GTK arrows because they don't look good on this widget */
583 draw_arrow_right (GdkWindow *window,
591 for (i = 0; i <= size / 2; i++)
593 gdk_draw_line (window, gc,
601 /* This function should be done by the toolkit, but we don't like the
602 * GTK arrows because they don't look good on this widget */
604 draw_arrow_left (GdkWindow *window,
612 for (i = 0; i <= size / 2; i++)
614 gdk_draw_line (window, gc,
623 gtk_calendar_set_month_prev (GtkCalendar *calendar)
627 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
630 if (calendar->month == 0)
632 calendar->month = 11;
638 month_len = month_length[leap (calendar->year)][calendar->month + 1];
640 gtk_calendar_freeze (calendar);
641 gtk_calendar_compute_days (calendar);
643 gtk_signal_emit (GTK_OBJECT (calendar),
644 gtk_calendar_signals[PREV_MONTH_SIGNAL]);
645 gtk_signal_emit (GTK_OBJECT (calendar),
646 gtk_calendar_signals[MONTH_CHANGED_SIGNAL]);
648 if (month_len < calendar->selected_day)
650 calendar->selected_day = 0;
651 gtk_calendar_select_day (calendar, month_len);
655 if (calendar->selected_day < 0)
656 calendar->selected_day = calendar->selected_day + 1 + month_length[leap (calendar->year)][calendar->month + 1];
658 gtk_calendar_select_day (calendar, calendar->selected_day);
661 gtk_calendar_select_day (calendar, calendar->selected_day);
662 gtk_calendar_paint (GTK_WIDGET (calendar), NULL);
663 gtk_calendar_thaw (calendar);
668 gtk_calendar_set_month_next (GtkCalendar *calendar)
672 g_return_if_fail (calendar != NULL);
673 g_return_if_fail (GTK_IS_WIDGET (calendar));
675 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
679 if (calendar->month == 11)
687 gtk_calendar_freeze (calendar);
688 gtk_calendar_compute_days (calendar);
689 gtk_signal_emit (GTK_OBJECT (calendar),
690 gtk_calendar_signals[NEXT_MONTH_SIGNAL]);
691 gtk_signal_emit (GTK_OBJECT (calendar),
692 gtk_calendar_signals[MONTH_CHANGED_SIGNAL]);
694 month_len = month_length[leap (calendar->year)][calendar->month + 1];
696 if (month_len < calendar->selected_day)
698 calendar->selected_day = 0;
699 gtk_calendar_select_day (calendar, month_len);
702 gtk_calendar_select_day (calendar, calendar->selected_day);
704 gtk_calendar_paint (GTK_WIDGET(calendar), NULL);
705 gtk_calendar_thaw (calendar);
709 gtk_calendar_set_year_prev (GtkCalendar *calendar)
713 g_return_if_fail (calendar != NULL);
714 g_return_if_fail (GTK_IS_WIDGET (calendar));
717 gtk_calendar_freeze (calendar);
718 gtk_calendar_compute_days (calendar);
719 gtk_signal_emit (GTK_OBJECT (calendar),
720 gtk_calendar_signals[PREV_YEAR_SIGNAL]);
721 gtk_signal_emit (GTK_OBJECT (calendar),
722 gtk_calendar_signals[MONTH_CHANGED_SIGNAL]);
724 month_len = month_length[leap (calendar->year)][calendar->month + 1];
726 if (month_len < calendar->selected_day)
728 calendar->selected_day = 0;
729 gtk_calendar_select_day (calendar, month_len);
732 gtk_calendar_select_day (calendar, calendar->selected_day);
734 gtk_calendar_paint (GTK_WIDGET (calendar), NULL);
735 gtk_calendar_thaw (calendar);
739 gtk_calendar_set_year_next (GtkCalendar *calendar)
744 g_return_if_fail (calendar != NULL);
745 g_return_if_fail (GTK_IS_WIDGET (calendar));
747 widget = GTK_WIDGET (calendar);
749 gtk_calendar_freeze (calendar);
752 gtk_calendar_compute_days (calendar);
753 gtk_signal_emit (GTK_OBJECT (calendar),
754 gtk_calendar_signals[NEXT_YEAR_SIGNAL]);
755 gtk_signal_emit (GTK_OBJECT (calendar),
756 gtk_calendar_signals[MONTH_CHANGED_SIGNAL]);
758 month_len = month_length[leap (calendar->year)][calendar->month + 1];
760 if (month_len < calendar->selected_day)
762 calendar->selected_day = 0;
763 gtk_calendar_select_day (calendar, month_len);
766 gtk_calendar_select_day (calendar, calendar->selected_day);
768 gtk_calendar_paint (GTK_WIDGET (calendar), NULL);
769 gtk_calendar_thaw (calendar);
773 gtk_calendar_main_button (GtkWidget *widget,
774 GdkEventButton *event)
776 GtkCalendar *calendar;
780 gint old_focus_row, old_focus_col;
782 calendar = GTK_CALENDAR (widget);
784 x = (gint) (event->x);
785 y = (gint) (event->y);
787 row = row_from_y (calendar, y);
788 col = column_from_x (calendar, x);
790 day_month = calendar->day_month[row][col];
792 if (day_month == MONTH_CURRENT)
794 if (event->type == GDK_2BUTTON_PRESS)
795 gtk_signal_emit (GTK_OBJECT (calendar),
796 gtk_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL]);
799 if (!GTK_WIDGET_HAS_FOCUS (widget))
800 gtk_widget_grab_focus (widget);
801 old_focus_row = calendar->focus_row;
802 old_focus_col = calendar->focus_col;
803 calendar->focus_row = row;
804 calendar->focus_col = col;
805 gtk_calendar_paint_day (widget, old_focus_row, old_focus_col);
806 gtk_calendar_select_day (calendar, calendar->day[row][col]);
809 else if (day_month == MONTH_PREV)
810 gtk_calendar_set_month_prev (calendar);
811 else if (day_month == MONTH_NEXT)
812 gtk_calendar_set_month_next (calendar);
816 gtk_calendar_realize_arrows (GtkWidget *widget)
818 GtkCalendar *calendar;
819 GtkCalendarPrivateData *private_data;
820 GdkWindowAttr attributes;
821 gint attributes_mask;
824 g_return_if_fail (widget != NULL);
825 g_return_if_fail (GTK_IS_CALENDAR (widget));
827 calendar = GTK_CALENDAR (widget);
828 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
830 /* Arrow windows ------------------------------------- */
831 if (! (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
832 && (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING))
834 attributes.wclass = GDK_INPUT_OUTPUT;
835 attributes.window_type = GDK_WINDOW_CHILD;
836 attributes.visual = gtk_widget_get_visual (widget);
837 attributes.colormap = gtk_widget_get_colormap (widget);
838 attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK
839 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
840 | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
841 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
843 attributes.width = private_data->arrow_width;
844 attributes.height = private_data->header_h - 7;
845 for (i = 0; i < 4; i++)
849 case ARROW_MONTH_LEFT:
852 case ARROW_MONTH_RIGHT:
853 attributes.x = (private_data->arrow_width
854 + private_data->max_month_width);
856 case ARROW_YEAR_LEFT:
857 attributes.x = (widget->allocation.width - 4
858 - (3 + 2*private_data->arrow_width
859 + private_data->max_year_width));
861 case ARROW_YEAR_RIGHT:
862 attributes.x = (widget->allocation.width - 4
863 - 3 - private_data->arrow_width);
866 private_data->arrow_win[i] = gdk_window_new (private_data->header_win,
869 private_data->arrow_state[i] = GTK_STATE_NORMAL;
870 gdk_window_set_background (private_data->arrow_win[i],
871 HEADER_BG_COLOR (GTK_WIDGET (calendar)));
872 gdk_window_show (private_data->arrow_win[i]);
873 gdk_window_set_user_data (private_data->arrow_win[i], widget);
878 for (i = 0; i < 4; i++)
879 private_data->arrow_win[i] = NULL;
884 gtk_calendar_realize_header (GtkWidget *widget)
886 GtkCalendar *calendar;
887 GtkCalendarPrivateData *private_data;
888 GdkWindowAttr attributes;
889 gint attributes_mask;
891 g_return_if_fail (widget != NULL);
892 g_return_if_fail (GTK_IS_CALENDAR (widget));
894 calendar = GTK_CALENDAR (widget);
895 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
897 /* Header window ------------------------------------- */
898 if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)
900 attributes.wclass = GDK_INPUT_OUTPUT;
901 attributes.window_type = GDK_WINDOW_CHILD;
902 attributes.visual = gtk_widget_get_visual (widget);
903 attributes.colormap = gtk_widget_get_colormap (widget);
904 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
905 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
908 attributes.width = widget->allocation.width - 4;
909 attributes.height = private_data->header_h;
910 private_data->header_win = gdk_window_new (widget->window,
911 &attributes, attributes_mask);
913 gdk_window_set_background (private_data->header_win,
914 HEADER_BG_COLOR (GTK_WIDGET (calendar)));
915 gdk_window_show (private_data->header_win);
916 gdk_window_set_user_data (private_data->header_win, widget);
921 private_data->header_win = NULL;
923 gtk_calendar_realize_arrows (widget);
927 gtk_calendar_realize_day_names (GtkWidget *widget)
929 GtkCalendar *calendar;
930 GtkCalendarPrivateData *private_data;
931 GdkWindowAttr attributes;
932 gint attributes_mask;
934 g_return_if_fail (widget != NULL);
935 g_return_if_fail (GTK_IS_CALENDAR (widget));
937 calendar = GTK_CALENDAR (widget);
938 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
940 /* Day names window --------------------------------- */
941 if ( calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
943 attributes.wclass = GDK_INPUT_OUTPUT;
944 attributes.window_type = GDK_WINDOW_CHILD;
945 attributes.visual = gtk_widget_get_visual (widget);
946 attributes.colormap = gtk_widget_get_colormap (widget);
947 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
948 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
949 attributes.x = (widget->style->klass->xthickness + INNER_BORDER);
950 attributes.y = private_data->header_h + (widget->style->klass->ythickness
952 attributes.width = (widget->allocation.width
953 - (widget->style->klass->xthickness + INNER_BORDER)
955 attributes.height = private_data->day_name_h;
956 private_data->day_name_win = gdk_window_new (widget->window,
959 gdk_window_set_background (private_data->day_name_win,
960 BACKGROUND_COLOR ( GTK_WIDGET ( calendar)));
961 gdk_window_show (private_data->day_name_win);
962 gdk_window_set_user_data (private_data->day_name_win, widget);
966 private_data->day_name_win = NULL;
971 gtk_calendar_realize_week_numbers (GtkWidget *widget)
973 GtkCalendar *calendar;
974 GtkCalendarPrivateData *private_data;
975 GdkWindowAttr attributes;
976 gint attributes_mask;
978 g_return_if_fail (widget != NULL);
979 g_return_if_fail (GTK_IS_CALENDAR (widget));
981 calendar = GTK_CALENDAR (widget);
982 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
984 /* Week number window -------------------------------- */
985 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
987 attributes.wclass = GDK_INPUT_OUTPUT;
988 attributes.window_type = GDK_WINDOW_CHILD;
989 attributes.visual = gtk_widget_get_visual (widget);
990 attributes.colormap = gtk_widget_get_colormap (widget);
991 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
993 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
994 attributes.x = + (widget->style->klass->xthickness + INNER_BORDER);
995 attributes.y = (private_data->header_h + private_data->day_name_h
996 + (widget->style->klass->ythickness + INNER_BORDER));
997 attributes.width = private_data->week_width;
998 attributes.height = private_data->main_h;
999 private_data->week_win = gdk_window_new (widget->window,
1000 &attributes, attributes_mask);
1001 gdk_window_set_background (private_data->week_win,
1002 BACKGROUND_COLOR (GTK_WIDGET (calendar)));
1003 gdk_window_show (private_data->week_win);
1004 gdk_window_set_user_data (private_data->week_win, widget);
1008 private_data->week_win = NULL;
1013 gtk_calendar_realize (GtkWidget *widget)
1015 GtkCalendar *calendar;
1016 GtkCalendarPrivateData *private_data;
1017 GdkWindowAttr attributes;
1018 gint attributes_mask;
1021 g_return_if_fail (widget != NULL);
1022 g_return_if_fail (GTK_IS_CALENDAR (widget));
1024 calendar = GTK_CALENDAR (widget);
1025 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1027 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
1028 gtk_calendar_compute_days (calendar);
1030 attributes.x = widget->allocation.x;
1031 attributes.y = widget->allocation.y;
1032 attributes.width = widget->allocation.width;
1033 attributes.height = widget->allocation.height;
1034 attributes.wclass = GDK_INPUT_OUTPUT;
1035 attributes.window_type = GDK_WINDOW_CHILD;
1036 attributes.event_mask = (gtk_widget_get_events (widget)
1037 | GDK_EXPOSURE_MASK |GDK_KEY_PRESS_MASK);
1038 attributes.visual = gtk_widget_get_visual (widget);
1039 attributes.colormap = gtk_widget_get_colormap (widget);
1041 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1042 widget->window = gdk_window_new (widget->parent->window,
1043 &attributes, attributes_mask);
1045 widget->style = gtk_style_attach (widget->style, widget->window);
1047 /* Header window ------------------------------------- */
1048 gtk_calendar_realize_header (widget);
1049 /* Day names window --------------------------------- */
1050 gtk_calendar_realize_day_names (widget);
1051 /* Week number window -------------------------------- */
1052 gtk_calendar_realize_week_numbers (widget);
1053 /* Main Window -------------------------------------- */
1054 attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK
1055 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
1056 | GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK);
1058 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1059 attributes.x = private_data->week_width;
1062 attributes.x += (widget->style->klass->xthickness + INNER_BORDER);
1063 attributes.y = (private_data->header_h + private_data->day_name_h
1064 + (widget->style->klass->ythickness + INNER_BORDER));
1065 attributes.width = (widget->allocation.width - attributes.x
1066 - (widget->style->klass->xthickness + INNER_BORDER));
1067 attributes.height = private_data->main_h;
1068 private_data->main_win = gdk_window_new (widget->window,
1069 &attributes, attributes_mask);
1070 gdk_window_set_background (private_data->main_win,
1071 BACKGROUND_COLOR ( GTK_WIDGET ( calendar)));
1072 gdk_window_show (private_data->main_win);
1073 gdk_window_set_user_data (private_data->main_win, widget);
1074 gdk_window_set_background (widget->window, BACKGROUND_COLOR (widget));
1075 gdk_window_show (widget->window);
1076 gdk_window_set_user_data (widget->window, widget);
1078 /* Set widgets gc */
1079 calendar->gc = gdk_gc_new (widget->window);
1081 values.foreground = widget->style->white;
1082 values.function = GDK_XOR;
1083 calendar->xor_gc = gdk_gc_new_with_values (widget->window,
1090 gtk_calendar_unrealize (GtkWidget *widget)
1092 GtkCalendar *calendar;
1093 GtkCalendarPrivateData *private_data;
1096 g_return_if_fail (widget != NULL);
1097 g_return_if_fail (GTK_IS_CALENDAR (widget));
1099 calendar = GTK_CALENDAR (widget);
1100 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1102 if (private_data->header_win)
1104 for (i = 0; i < 4; i++)
1106 if (private_data->arrow_win[i])
1108 gdk_window_set_user_data (private_data->arrow_win[i], NULL);
1109 gdk_window_destroy (private_data->arrow_win[i]);
1110 private_data->arrow_win[i] = NULL;
1113 gdk_window_set_user_data (private_data->header_win, NULL);
1114 gdk_window_destroy (private_data->header_win);
1115 private_data->header_win = NULL;
1118 if (private_data->week_win)
1120 gdk_window_set_user_data (private_data->week_win, NULL);
1121 gdk_window_destroy (private_data->week_win);
1122 private_data->week_win = NULL;
1125 if (private_data->main_win)
1127 gdk_window_set_user_data (private_data->main_win, NULL);
1128 gdk_window_destroy (private_data->main_win);
1129 private_data->main_win = NULL;
1132 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1133 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1137 gtk_calendar_size_request (GtkWidget *widget,
1138 GtkRequisition *requisition)
1140 GtkCalendar *calendar;
1141 GtkCalendarPrivateData *private_data;
1146 gint calendar_margin = CALENDAR_MARGIN;
1147 gint header_width, main_width;
1154 calendar = GTK_CALENDAR (widget);
1155 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1158 * Calculate the requisition width for the widget.
1163 if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)
1165 private_data->max_month_width = 0;
1166 for (i = 0; i < 12; i++)
1168 private_data->max_month_width = MAX (private_data->max_month_width,
1169 gdk_string_measure (HEADER_FONT (widget),
1170 default_monthname[i]) + 8);
1172 private_data->max_year_width = 0;
1173 for (i=0; i<10; i++)
1175 sprintf (buffer, "%d%d%d%d", i,i,i,i);
1176 private_data->max_year_width = MAX (private_data->max_year_width,
1177 gdk_string_measure (HEADER_FONT (widget),
1183 private_data->max_month_width = 0;
1184 private_data->max_year_width = 0;
1187 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1188 header_width = (private_data->max_month_width
1189 + private_data->max_year_width
1192 header_width = (private_data->max_month_width
1193 + private_data->max_year_width
1194 + 4 * private_data->arrow_width + 3 * 3);
1196 /* Mainwindow labels width */
1198 private_data->max_day_char_width = 0;
1199 for (i = 0; i < 9; i++)
1201 sprintf (buffer, "%d%d", i, i);
1202 private_data->min_day_width = MAX (private_data->max_day_char_width,
1203 gdk_string_measure (DAY_FONT (widget),
1206 /* We add one to max_day_char_width to be able to make the marked day "bold" */
1207 private_data->max_day_char_width = private_data->min_day_width / 2 +1;
1209 if (calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
1210 for (i = 0; i < 7; i++)
1212 gdk_text_extents (LABEL_FONT (widget),
1213 default_abbreviated_dayname[i],
1214 strlen(default_abbreviated_dayname[i]),
1220 private_data->min_day_width = MAX (private_data->min_day_width, width);
1221 private_data->max_label_char_ascent = MAX (private_data->max_label_char_ascent,
1223 private_data->max_label_char_descent = MAX (private_data->max_label_char_descent,
1227 private_data->max_week_char_width = 0;
1228 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1229 for (i = 0; i < 9; i++)
1231 sprintf (buffer, "%d%d", i, i);
1232 private_data->max_week_char_width = MAX (private_data->max_week_char_width,
1233 gdk_string_measure (LABEL_FONT (widget), buffer) / 2);
1236 main_width = (7 * (private_data->min_day_width + DAY_XPAD * 2) + (DAY_XSEP * 6) + CALENDAR_MARGIN * 2
1237 + (private_data->max_week_char_width
1238 ? private_data->max_week_char_width * 2 + DAY_XPAD * 2 + CALENDAR_XSEP * 2
1242 requisition->width = MAX (header_width+4, main_width + (widget->style->klass->xthickness + INNER_BORDER) *2);
1245 * Calculate the requisition height for the widget.
1248 if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)
1250 private_data->header_h = (HEADER_FONT (widget)->ascent
1251 + HEADER_FONT (widget)->descent
1252 + CALENDAR_YSEP * 2);
1256 private_data->header_h = 0;
1259 if (calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
1261 private_data->day_name_h = (private_data->max_label_char_ascent
1262 + private_data->max_label_char_descent
1263 + 2 * DAY_YPAD + calendar_margin);
1264 calendar_margin = CALENDAR_YSEP;
1268 private_data->day_name_h = 0;
1271 gdk_text_extents (DAY_FONT (widget),
1277 &private_data->max_day_char_ascent,
1278 &private_data->max_day_char_descent);
1280 private_data->main_h = (CALENDAR_MARGIN + calendar_margin
1281 + 6 * (private_data->max_day_char_ascent
1282 + private_data->max_day_char_descent
1287 * If we display weeknumbers we need some extra space
1290 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1292 private_data->main_h = MAX (private_data->main_h,
1293 (CALENDAR_MARGIN + calendar_margin
1294 + 6 * (private_data->max_day_char_ascent
1295 + private_data->max_day_char_descent
1300 height = (private_data->header_h + private_data->day_name_h
1301 + private_data->main_h);
1303 requisition->height = height + (widget->style->klass->ythickness + INNER_BORDER) * 2;
1307 gtk_calendar_size_allocate (GtkWidget *widget,
1308 GtkAllocation *allocation)
1310 GtkCalendar *calendar;
1311 GtkCalendarPrivateData *private_data;
1313 g_return_if_fail (widget != NULL);
1314 g_return_if_fail (GTK_IS_CALENDAR (widget));
1315 g_return_if_fail (allocation != NULL);
1317 widget->allocation = *allocation;
1319 calendar = GTK_CALENDAR (widget);
1320 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1322 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1324 private_data->day_width = (private_data->min_day_width
1325 * ((allocation->width - (widget->style->klass->xthickness + INNER_BORDER) * 2
1326 - (CALENDAR_MARGIN * 2) - (DAY_XSEP * 7) - CALENDAR_XSEP * 2))
1327 / (7 * private_data->min_day_width + private_data->max_week_char_width * 2));
1328 private_data->week_width = ((allocation->width - (widget->style->klass->xthickness + INNER_BORDER) * 2
1329 - (CALENDAR_MARGIN * 2) - (DAY_XSEP * 7) - CALENDAR_XSEP * 2 )
1330 - private_data->day_width * 7 + CALENDAR_MARGIN + CALENDAR_XSEP);
1334 private_data->day_width = (allocation->width
1335 - (widget->style->klass->xthickness + INNER_BORDER) * 2
1336 - (CALENDAR_MARGIN * 2)
1337 - (DAY_XSEP * 7))/7;
1338 private_data->week_width = 0;
1341 if (GTK_WIDGET_REALIZED (widget))
1343 gdk_window_move_resize (widget->window,
1344 allocation->x, allocation->y,
1345 allocation->width, allocation->height);
1346 if (private_data->header_win)
1347 gdk_window_move_resize (private_data->header_win,
1349 allocation->width-4, private_data->header_h);
1350 if (private_data->arrow_win[ARROW_MONTH_LEFT])
1351 gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_LEFT],
1353 private_data->arrow_width,
1354 private_data->header_h - 7);
1355 if (private_data->arrow_win[ARROW_MONTH_RIGHT])
1356 gdk_window_move_resize (private_data->arrow_win[ARROW_MONTH_RIGHT],
1357 (private_data->arrow_width
1358 + private_data->max_month_width),
1360 private_data->arrow_width,
1361 private_data->header_h - 7);
1362 if (private_data->arrow_win[ARROW_YEAR_LEFT])
1363 gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_LEFT],
1364 (allocation->width - 4
1365 - (3 + 2*private_data->arrow_width
1366 + private_data->max_year_width)),
1368 private_data->arrow_width,
1369 private_data->header_h - 7);
1370 if (private_data->arrow_win[ARROW_YEAR_RIGHT])
1371 gdk_window_move_resize (private_data->arrow_win[ARROW_YEAR_RIGHT],
1372 (allocation->width - 4
1373 - 3 - private_data->arrow_width),
1375 private_data->arrow_width,
1376 private_data->header_h - 7);
1377 if (private_data->day_name_win)
1378 gdk_window_move_resize (private_data->day_name_win,
1379 widget->style->klass->xthickness + INNER_BORDER,
1380 private_data->header_h + (widget->style->klass->ythickness + INNER_BORDER),
1381 allocation->width - (widget->style->klass->xthickness + INNER_BORDER) * 2,
1382 private_data->day_name_h);
1383 if (private_data->week_win)
1384 gdk_window_move_resize (private_data->week_win,
1385 (widget->style->klass->xthickness + INNER_BORDER),
1386 private_data->header_h + private_data->day_name_h
1387 + (widget->style->klass->ythickness + INNER_BORDER),
1388 private_data->week_width,
1389 private_data->main_h);
1390 gdk_window_move_resize (private_data->main_win,
1391 (private_data->week_width ? private_data->week_width + CALENDAR_XSEP :0)
1392 + (widget->style->klass->xthickness + INNER_BORDER),
1393 private_data->header_h + private_data->day_name_h
1394 + (widget->style->klass->ythickness + INNER_BORDER),
1396 - (private_data->week_width ? private_data->week_width + CALENDAR_XSEP :0)
1397 - (widget->style->klass->xthickness + INNER_BORDER) * 2,
1398 private_data->main_h);
1403 gtk_calendar_draw_focus (GtkWidget *widget)
1405 GtkCalendar *calendar;
1406 GtkCalendarPrivateData *private_data;
1410 g_return_if_fail (widget != NULL);
1411 g_return_if_fail (GTK_IS_CALENDAR (widget));
1413 calendar = GTK_CALENDAR (widget);
1414 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1416 if (GTK_WIDGET_DRAWABLE (widget))
1420 gdk_window_get_size (widget->window, &width, &height);
1421 gdk_window_clear (widget->window);
1423 gdk_draw_rectangle (widget->window,
1424 widget->style->base_gc[GTK_WIDGET_STATE (widget)],
1425 FALSE, x + 2, y + 2, width - 5, height - 5);
1427 gtk_draw_shadow (widget->style, widget->window,
1428 GTK_STATE_NORMAL, GTK_SHADOW_IN,
1429 x, y, width, height);
1435 gtk_calendar_expose (GtkWidget *widget,
1436 GdkEventExpose *event)
1438 GtkCalendar *calendar;
1439 GtkCalendarPrivateData *private_data;
1441 g_return_val_if_fail (widget != NULL, FALSE);
1442 g_return_val_if_fail (GTK_IS_CALENDAR (widget), FALSE);
1443 g_return_val_if_fail (event != NULL, FALSE);
1445 calendar = GTK_CALENDAR (widget);
1446 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1448 if (GTK_WIDGET_DRAWABLE (widget))
1450 if (event->window == private_data->main_win)
1451 gtk_calendar_paint_main (widget);
1453 if (event->window == private_data->header_win)
1454 gtk_calendar_paint_header (widget);
1456 if (event->window == private_data->day_name_win)
1457 gtk_calendar_paint_day_names (widget);
1459 if (event->window == private_data->week_win)
1460 gtk_calendar_paint_week_numbers (widget);
1461 if (event->window == widget->window)
1462 gtk_widget_draw_focus (widget);
1469 gtk_calendar_draw (GtkWidget *widget,
1472 g_return_if_fail (widget != NULL);
1473 g_return_if_fail (GTK_IS_CALENDAR (widget));
1474 g_return_if_fail (area != NULL);
1476 if (GTK_WIDGET_DRAWABLE (widget))
1477 gtk_calendar_paint (widget, area);
1482 gtk_calendar_paint (GtkWidget *widget,
1485 GtkCalendar *calendar;
1486 GtkCalendarPrivateData *private_data;
1488 g_return_if_fail (widget != NULL);
1489 g_return_if_fail (widget->window != NULL);
1490 g_return_if_fail (GTK_IS_CALENDAR (widget));
1492 calendar = GTK_CALENDAR (widget);
1493 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1495 if (private_data->main_win != NULL)
1496 gtk_calendar_paint_main (widget);
1498 if (private_data->header_win != NULL)
1499 gtk_calendar_paint_header (widget);
1501 if (private_data->day_name_win != NULL)
1502 gtk_calendar_paint_day_names (widget);
1504 if (private_data->week_win != NULL)
1505 gtk_calendar_paint_week_numbers (widget);
1507 gtk_widget_draw_focus (widget);
1511 gtk_calendar_paint_header (GtkWidget *widget)
1513 GtkCalendar *calendar;
1517 gint header_width, cal_height;
1519 gint max_month_width;
1520 gint max_year_width;
1521 GtkCalendarPrivateData *private_data;
1523 calendar = GTK_CALENDAR (widget);
1524 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1526 if (private_data->freeze_count)
1528 private_data->dirty_header = 1;
1531 private_data->dirty_header = 0;
1535 gdk_window_clear (private_data->header_win);
1537 header_width = widget->allocation.width - 4;
1538 cal_height = widget->allocation.height;
1540 max_month_width = private_data->max_month_width;
1541 max_year_width = private_data->max_year_width;
1543 gdk_gc_set_foreground (gc, BACKGROUND_COLOR (GTK_WIDGET (calendar)));
1544 gtk_draw_shadow (widget->style, private_data->header_win,
1545 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1546 0, 0, header_width, private_data->header_h);
1550 y = private_data->header_h - (private_data->header_h
1551 - HEADER_FONT (widget)->ascent
1552 + HEADER_FONT (widget)->descent) / 2;
1553 y_arrow = (private_data->header_h - 9) / 2;
1555 /* Draw year and its arrows */
1556 sprintf (buffer, "%d", calendar->year);
1557 str_width = gdk_string_measure (HEADER_FONT (widget), buffer);
1558 gdk_gc_set_foreground (gc, HEADER_FG_COLOR (GTK_WIDGET (calendar)));
1559 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1560 gdk_draw_string (private_data->header_win, HEADER_FONT (widget), gc,
1561 header_width - (3 + max_year_width
1562 - (max_year_width - str_width)/2),
1565 gdk_draw_string (private_data->header_win, HEADER_FONT (widget), gc,
1566 header_width - (3 + private_data->arrow_width + max_year_width
1567 - (max_year_width - str_width)/2),
1571 sprintf (buffer, "%s", default_monthname[calendar->month]);
1572 str_width = gdk_string_measure (HEADER_FONT (widget), buffer);
1573 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1574 gdk_draw_string (private_data->header_win, HEADER_FONT (widget), gc,
1575 3 + (max_month_width - str_width) / 2,
1578 gdk_draw_string (private_data->header_win, HEADER_FONT (widget), gc,
1579 3 + private_data->arrow_width + (max_month_width - str_width)/2,
1582 y += CALENDAR_YSEP + HEADER_FONT (widget)->descent;
1584 gdk_gc_set_foreground (gc, BACKGROUND_COLOR (GTK_WIDGET (calendar)));
1586 gtk_calendar_paint_arrow (widget, ARROW_MONTH_LEFT);
1587 gtk_calendar_paint_arrow (widget, ARROW_MONTH_RIGHT);
1588 gtk_calendar_paint_arrow (widget, ARROW_YEAR_LEFT);
1589 gtk_calendar_paint_arrow (widget, ARROW_YEAR_RIGHT);
1594 gtk_calendar_paint_day_names (GtkWidget *widget)
1596 GtkCalendar *calendar;
1600 int day_width, cal_width;
1604 GtkCalendarPrivateData *private_data;
1606 g_return_if_fail (widget != NULL);
1607 g_return_if_fail (GTK_IS_CALENDAR (widget));
1608 calendar = GTK_CALENDAR (widget);
1609 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1613 * Handle freeze/thaw functionality
1616 if (private_data->freeze_count)
1618 private_data->dirty_day_names = 1;
1621 private_data->dirty_day_names = 0;
1627 gdk_window_clear (private_data->day_name_win);
1629 day_width = private_data->day_width;
1630 cal_width = widget->allocation.width;
1631 cal_height = widget->allocation.height;
1632 day_wid_sep = day_width + DAY_XSEP;
1635 * Draw rectangles as inverted background for the labels.
1638 gdk_gc_set_foreground (gc, &widget->style->bg[GTK_STATE_SELECTED]);
1639 gdk_draw_rectangle (private_data->day_name_win, gc, TRUE,
1640 CALENDAR_MARGIN, CALENDAR_MARGIN,
1641 cal_width-CALENDAR_MARGIN * 2,
1642 private_data->day_name_h - CALENDAR_MARGIN);
1644 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1645 gdk_draw_rectangle (private_data->day_name_win, gc, TRUE,
1647 private_data->day_name_h - CALENDAR_YSEP,
1648 private_data->week_width - CALENDAR_YSEP - CALENDAR_MARGIN,
1654 gdk_gc_set_foreground (gc, &widget->style->fg[GTK_STATE_SELECTED]);
1655 for (i = 0; i < 7; i++)
1658 if (calendar->display_flags & GTK_CALENDAR_WEEK_START_MONDAY)
1660 sprintf (buffer, "%s", default_abbreviated_dayname[day]);
1661 str_width = gdk_string_measure (LABEL_FONT (widget), buffer);
1662 gdk_draw_string (private_data->day_name_win, LABEL_FONT (widget),
1664 ((private_data->week_width ? CALENDAR_XSEP : CALENDAR_MARGIN)
1666 + private_data->week_width
1667 + (day_width - str_width)/2),
1668 CALENDAR_MARGIN + DAY_YPAD
1669 + private_data->max_label_char_ascent, buffer);
1674 gtk_calendar_paint_week_numbers (GtkWidget *widget)
1676 GtkCalendar *calendar;
1678 gint row, week = 0, year;
1681 gint y_baseline, day_height;
1682 GtkCalendarPrivateData *private_data;
1684 g_return_if_fail (widget != NULL);
1685 g_return_if_fail (widget->window != NULL);
1686 g_return_if_fail (GTK_IS_CALENDAR (widget));
1687 calendar = GTK_CALENDAR (widget);
1688 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1692 * Handle freeze/thaw functionality
1695 if (private_data->freeze_count)
1697 private_data->dirty_week = 1;
1700 private_data->dirty_week = 0;
1706 gdk_window_clear (private_data->week_win);
1709 * Draw a rectangle as inverted background for the labels.
1712 gdk_gc_set_foreground (gc, &widget->style->bg[GTK_STATE_SELECTED]);
1713 if (private_data->day_name_win)
1714 gdk_draw_rectangle (private_data->week_win, gc, TRUE,
1717 private_data->week_width - CALENDAR_MARGIN - CALENDAR_XSEP,
1718 private_data->main_h - CALENDAR_MARGIN);
1720 gdk_draw_rectangle (private_data->week_win, gc, TRUE,
1723 private_data->week_width - CALENDAR_MARGIN - CALENDAR_XSEP,
1724 private_data->main_h - 2 * CALENDAR_MARGIN);
1730 gdk_gc_set_foreground (gc, &widget->style->fg[GTK_STATE_SELECTED]);
1731 day_height = row_height (calendar);
1732 for (row = 0; row < 6; row++)
1734 year = calendar->year;
1735 if (calendar->day[row][6] < 15 && row > 3 && calendar->month == 11)
1737 y_baseline = (top_y_for_row (calendar, row)
1738 + (day_height + LABEL_FONT (widget)->ascent
1739 - LABEL_FONT (widget)->descent)/2);
1740 g_return_if_fail (week_of_year (&week, &year,
1741 ((calendar->day[row][6] < 15 && row > 3 ? 1 : 0)
1742 + calendar->month) % 12 + 1, calendar->day[row][6]));
1743 x_loc= (private_data->week_width - (private_data->week_width - CALENDAR_XSEP
1744 - DAY_XPAD * 2 - CALENDAR_MARGIN ) / 2
1745 - private_data->max_week_char_width
1746 - CALENDAR_XSEP - DAY_XPAD);
1750 sprintf (buffer, "%d", week/10);
1751 gdk_draw_string (private_data->week_win, LABEL_FONT (widget), gc,
1752 x_loc, y_baseline , buffer);
1755 sprintf (buffer, "%d", week%10);
1756 gdk_draw_string (private_data->week_win, LABEL_FONT (widget), gc,
1757 x_loc + private_data->max_week_char_width, y_baseline , buffer);
1762 gtk_calendar_paint_day_num (GtkWidget *widget,
1765 GtkCalendar *calendar;
1766 gint r, c, row, col;
1768 g_return_if_fail (widget != NULL);
1769 g_return_if_fail (GTK_IS_CALENDAR (widget));
1771 calendar = GTK_CALENDAR (widget);
1775 for (r = 0; r < 6; r++)
1776 for (c = 0; c < 7; c++)
1777 if (calendar->day_month[r][c] == MONTH_CURRENT &&
1778 calendar->day[r][c] == day)
1784 g_return_if_fail (row != -1);
1785 g_return_if_fail (col != -1);
1787 gtk_calendar_paint_day (widget, row, col);
1791 gtk_calendar_paint_day (GtkWidget *widget,
1795 GtkCalendar *calendar;
1805 GtkCalendarPrivateData *private_data;
1807 g_return_if_fail (widget != NULL);
1808 g_return_if_fail (GTK_IS_CALENDAR (widget));
1809 g_return_if_fail (row < 6);
1810 g_return_if_fail (col < 7);
1811 calendar = GTK_CALENDAR (widget);
1812 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1815 * Handle freeze/thaw functionality
1818 if (private_data->freeze_count)
1820 private_data->dirty_main = 1;
1824 day_height = row_height (calendar);
1826 day_xspace = private_data->day_width - private_data->max_day_char_width*2;
1828 day = calendar->day[row][col];
1830 x_left = left_x_for_column (calendar, col);
1831 x_loc = x_left + private_data->day_width / 2 + private_data->max_day_char_width;
1833 y_top = top_y_for_row (calendar, row);
1834 y_baseline = y_top + (day_height + private_data->max_day_char_ascent)/2;
1836 gdk_window_clear_area (private_data->main_win, x_left, y_top,
1837 private_data->day_width, day_height);
1841 if (calendar->day_month[row][col] == MONTH_PREV)
1843 gdk_gc_set_foreground (gc, PREV_MONTH_COLOR (GTK_WIDGET (calendar)));
1845 else if (calendar->day_month[row][col] == MONTH_NEXT)
1847 gdk_gc_set_foreground (gc, NEXT_MONTH_COLOR (GTK_WIDGET (calendar)));
1852 if (calendar->highlight_row == row && calendar->highlight_col == col)
1854 gdk_gc_set_foreground (gc, HIGHLIGHT_BACK_COLOR (GTK_WIDGET (calendar)));
1855 gdk_draw_rectangle (private_data->main_win, gc, TRUE, x_left, y_top,
1856 private_data->day_width, day_height);
1859 if (calendar->selected_day == day)
1861 gdk_gc_set_foreground (gc, & (GTK_WIDGET (calendar)->style->bg[GTK_STATE_SELECTED]));
1862 gdk_draw_rectangle (private_data->main_win, gc, TRUE, x_left, y_top,
1863 private_data->day_width, day_height);
1866 if (calendar->marked_date[day-1])
1867 gdk_gc_set_foreground (gc, MARKED_COLOR (GTK_WIDGET (calendar)));
1869 gdk_gc_set_foreground (gc, NORMAL_DAY_COLOR (GTK_WIDGET (calendar)));
1871 if (calendar->selected_day == day)
1872 gdk_gc_set_foreground (gc, & (GTK_WIDGET (calendar)->style->fg[GTK_STATE_SELECTED]));
1874 gdk_gc_set_foreground (gc, & (GTK_WIDGET (calendar)->style->fg[GTK_WIDGET_STATE (calendar)]));
1878 sprintf (buffer, "%d", day);
1879 x_loc -= gdk_string_measure (DAY_FONT (widget), buffer);
1880 sprintf (buffer, "%d", day);
1881 gdk_draw_string (private_data->main_win,
1882 DAY_FONT (widget), gc,
1883 x_loc, y_baseline, buffer);
1884 if (calendar->marked_date[day-1]
1885 && calendar->day_month[row][col] == MONTH_CURRENT)
1886 gdk_draw_string (private_data->main_win,
1887 DAY_FONT (widget), gc,
1888 x_loc-1, y_baseline, buffer);
1890 if (GTK_WIDGET_HAS_FOCUS (calendar)
1891 && calendar->focus_row == row && calendar->focus_col == col)
1893 gdk_draw_rectangle (private_data->main_win, calendar->xor_gc,
1894 FALSE, x_left, y_top,
1895 private_data->day_width-1, day_height-1);
1902 gtk_calendar_paint_main (GtkWidget *widget)
1904 GtkCalendar *calendar;
1905 GtkCalendarPrivateData *private_data;
1908 g_return_if_fail (widget != NULL);
1909 g_return_if_fail (widget->window != NULL);
1910 g_return_if_fail (GTK_IS_CALENDAR (widget));
1912 calendar = GTK_CALENDAR (widget);
1913 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
1915 if (private_data->freeze_count)
1917 private_data->dirty_main = 1;
1920 private_data->dirty_main = 0;
1921 gdk_window_clear (private_data->main_win);
1923 /* gtk_calendar_compute_days (calendar); */ /* REMOVE later */
1925 for (col = 0; col < 7; col++)
1926 for (row = 0; row < 6; row++)
1927 gtk_calendar_paint_day (widget, row, col);
1931 gtk_calendar_compute_days (GtkCalendar *calendar)
1935 gint ndays_in_month;
1936 gint ndays_in_prev_month;
1942 g_return_if_fail (calendar != NULL);
1943 g_return_if_fail (GTK_IS_CALENDAR (calendar));
1945 year = calendar->year;
1946 month = calendar->month + 1;
1948 ndays_in_month = month_length[leap (year)][month];
1950 first_day = day_of_week (year, month, 1);
1952 if (calendar->display_flags & GTK_CALENDAR_WEEK_START_MONDAY)
1958 /* Compute days of previous month */
1960 ndays_in_prev_month = month_length[leap (year)][month-1];
1962 ndays_in_prev_month = month_length[leap (year)][12];
1963 day = ndays_in_prev_month - first_day + 1;
1968 for (col = 0; col < first_day; col++)
1970 calendar->day[row][col] = day;
1971 calendar->day_month[row][col] = MONTH_PREV;
1976 /* Compute days of current month */
1978 for (day = 1; day <= ndays_in_month; day++)
1980 calendar->day[row][col] = day;
1981 calendar->day_month[row][col] = MONTH_CURRENT;
1991 /* Compute days of next month */
1993 for (; row <= 5; row++)
1995 for (; col <= 6; col++)
1997 calendar->day[row][col] = day;
1998 calendar->day_month[row][col] = MONTH_NEXT;
2005 /* ----------------------------------------------------------------------
2006 NAME: gtk_calendar_display_options
2007 DESCRIPTION: Set display options (whether to display the
2008 heading and the month headings)
2010 flags is can be an XOR of:
2011 GTK_CALENDAR_SHOW_HEADING
2012 GTK_CALENDAR_SHOW_DAY_NAMES
2013 GTK_CALENDAR_NO_MONTH_CHANGE
2014 GTK_CALENDAR_SHOW_WEEK_NUMBERS
2015 GTK_CALENDAR_WEEK_START_MONDAY
2016 ---------------------------------------------------------------------- */
2019 gtk_calendar_display_options (GtkCalendar *calendar,
2020 GtkCalendarDisplayOptions flags)
2022 GtkCalendarPrivateData *private_data;
2027 g_return_if_fail (calendar != NULL);
2028 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2030 widget = GTK_WIDGET (calendar);
2031 private_data = GTK_CALENDAR_PRIVATE_DATA (calendar);
2033 if (GTK_WIDGET_REALIZED (widget))
2035 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_NO_MONTH_CHANGE)
2038 if (! (flags & GTK_CALENDAR_NO_MONTH_CHANGE)
2039 && (private_data->header_win))
2041 calendar->display_flags &= ~GTK_CALENDAR_NO_MONTH_CHANGE;
2042 gtk_calendar_realize_arrows (widget);
2046 for (i = 0; i < 4; i++)
2048 if (private_data->arrow_win[i])
2050 gdk_window_set_user_data (private_data->arrow_win[i],
2052 gdk_window_destroy (private_data->arrow_win[i]);
2053 private_data->arrow_win[i] = NULL;
2059 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_HEADING)
2063 if (flags & GTK_CALENDAR_SHOW_HEADING)
2065 calendar->display_flags |= GTK_CALENDAR_SHOW_HEADING;
2066 gtk_calendar_realize_header (widget);
2070 for (i = 0; i < 4; i++)
2072 if (private_data->arrow_win[i])
2074 gdk_window_set_user_data (private_data->arrow_win[i],
2076 gdk_window_destroy (private_data->arrow_win[i]);
2077 private_data->arrow_win[i] = NULL;
2080 gdk_window_set_user_data (private_data->header_win, NULL);
2081 gdk_window_destroy (private_data->header_win);
2082 private_data->header_win = NULL;
2087 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_DAY_NAMES)
2091 if (flags & GTK_CALENDAR_SHOW_DAY_NAMES)
2093 calendar->display_flags |= GTK_CALENDAR_SHOW_DAY_NAMES;
2094 gtk_calendar_realize_day_names (widget);
2098 gdk_window_set_user_data (private_data->day_name_win, NULL);
2099 gdk_window_destroy (private_data->day_name_win);
2100 private_data->day_name_win = NULL;
2104 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
2108 if (flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
2110 calendar->display_flags |= GTK_CALENDAR_SHOW_WEEK_NUMBERS;
2111 gtk_calendar_realize_week_numbers (widget);
2115 gdk_window_set_user_data (private_data->week_win, NULL);
2116 gdk_window_destroy (private_data->week_win);
2117 private_data->week_win = NULL;
2121 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_WEEK_START_MONDAY)
2123 if (calendar->display_flags & GTK_CALENDAR_WEEK_START_MONDAY)
2124 calendar->display_flags &= ~GTK_CALENDAR_WEEK_START_MONDAY;
2126 calendar->display_flags |= GTK_CALENDAR_WEEK_START_MONDAY;
2128 gtk_calendar_compute_days (calendar);
2129 gtk_calendar_paint_main (GTK_WIDGET (calendar));
2130 if (private_data->day_name_win)
2131 gtk_calendar_paint_day_names (GTK_WIDGET (calendar));
2134 calendar->display_flags = flags;
2136 gtk_widget_queue_resize (GTK_WIDGET (calendar));
2140 calendar->display_flags = flags;
2145 gtk_calendar_select_month (GtkCalendar *calendar,
2149 g_return_val_if_fail (calendar != NULL, FALSE);
2150 g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE);
2151 g_return_val_if_fail (month <= 11, FALSE);
2153 calendar->month = month;
2154 calendar->year = year;
2156 gtk_calendar_compute_days (calendar);
2158 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
2159 gtk_calendar_paint (GTK_WIDGET (calendar), NULL);
2161 gtk_signal_emit (GTK_OBJECT (calendar),
2162 gtk_calendar_signals[MONTH_CHANGED_SIGNAL]);
2167 gtk_calendar_select_day (GtkCalendar *calendar,
2170 g_return_if_fail (calendar != NULL);
2171 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2172 g_return_if_fail (day <= 31);
2174 /* gtk_calendar_compute_days (calendar); */
2176 /* Deselect the old day */
2177 if (calendar->selected_day > 0)
2181 selected_day = calendar->selected_day;
2182 calendar->selected_day = 0;
2183 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
2184 gtk_calendar_paint_day_num (GTK_WIDGET (calendar), selected_day);
2187 calendar->selected_day = day;
2189 /* Deselect the new day */
2192 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
2193 gtk_calendar_paint_day_num (GTK_WIDGET (calendar), day);
2196 gtk_signal_emit (GTK_OBJECT (calendar),
2197 gtk_calendar_signals[DAY_SELECTED_SIGNAL]);
2201 gtk_calendar_clear_marks (GtkCalendar *calendar)
2205 g_return_if_fail (calendar != NULL);
2206 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2208 for (day = 0; day < 31; day++)
2210 calendar->marked_date[day] = FALSE;
2213 if (GTK_WIDGET_DRAWABLE (calendar))
2215 gtk_calendar_paint_main (GTK_WIDGET (calendar));
2220 gtk_calendar_mark_day (GtkCalendar *calendar,
2223 g_return_val_if_fail (calendar != NULL, FALSE);
2224 g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE);
2226 if (day >= 1 && day <= 31)
2227 calendar->marked_date[day - 1] = TRUE;
2229 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
2231 gtk_calendar_paint_main (GTK_WIDGET (calendar));
2238 gtk_calendar_unmark_day (GtkCalendar *calendar,
2241 g_return_val_if_fail (calendar != NULL, FALSE);
2242 g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE);
2244 if (day >= 1 && day <= 31)
2245 calendar->marked_date[day - 1] = FALSE;
2247 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
2249 gtk_calendar_paint_main (GTK_WIDGET (calendar));
2256 gtk_calendar_get_date (GtkCalendar *calendar,
2261 g_return_if_fail (calendar != NULL);
2262 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2265 *year = calendar->year;
2268 *month = calendar->month;
2271 *day = calendar->selected_day;
2275 gtk_calendar_button_press (GtkWidget *widget,
2276 GdkEventButton *event)
2278 GtkCalendar *calendar;
2279 GtkCalendarPrivateData *private_data;
2282 g_return_val_if_fail (widget != NULL, FALSE);
2283 g_return_val_if_fail (GTK_IS_CALENDAR (widget), FALSE);
2284 g_return_val_if_fail (event != NULL, FALSE);
2286 calendar = GTK_CALENDAR (widget);
2287 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2289 x = (gint) (event->x);
2290 y = (gint) (event->y);
2292 if (event->window == private_data->arrow_win[ARROW_MONTH_LEFT])
2293 gtk_calendar_set_month_prev (calendar);
2295 if (event->window == private_data->arrow_win[ARROW_MONTH_RIGHT])
2296 gtk_calendar_set_month_next (calendar);
2298 if (event->window == private_data->arrow_win[ARROW_YEAR_LEFT])
2299 gtk_calendar_set_year_prev (calendar);
2301 if (event->window == private_data->arrow_win[ARROW_YEAR_RIGHT])
2302 gtk_calendar_set_year_next (calendar);
2304 if (event->window == private_data->main_win)
2305 gtk_calendar_main_button (widget, event);
2311 gtk_calendar_motion_notify (GtkWidget *widget,
2312 GdkEventMotion *event)
2314 GtkCalendar *calendar;
2315 GtkCalendarPrivateData *private_data;
2316 gint event_x, event_y;
2318 gint old_row, old_col;
2320 calendar = GTK_CALENDAR (widget);
2321 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2322 event_x = (gint) (event->x);
2323 event_y = (gint) (event->y);
2325 if (event->window == private_data->main_win)
2328 row = row_from_y (calendar, event_y);
2329 col = column_from_x (calendar, event_x);
2331 if (row != calendar->highlight_row || calendar->highlight_col != col)
2333 old_row = calendar->highlight_row;
2334 old_col = calendar->highlight_col;
2335 if (old_row > -1 && old_col > -1)
2337 calendar->highlight_row = -1;
2338 calendar->highlight_col = -1;
2339 gtk_calendar_paint_day (widget, old_row, old_col);
2342 calendar->highlight_row = row;
2343 calendar->highlight_col = col;
2345 if (row > -1 && col > -1)
2346 gtk_calendar_paint_day (widget, row, col);
2353 gtk_calendar_enter_notify (GtkWidget *widget,
2354 GdkEventCrossing *event)
2356 GtkCalendar *calendar;
2357 GtkCalendarPrivateData *private_data;
2359 g_return_val_if_fail (widget != NULL, FALSE);
2360 g_return_val_if_fail (event != NULL, FALSE);
2362 calendar = GTK_CALENDAR (widget);
2363 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2365 if (event->window == private_data->arrow_win[ARROW_MONTH_LEFT])
2367 private_data->arrow_state[ARROW_MONTH_LEFT] = GTK_STATE_PRELIGHT;
2368 gtk_calendar_paint_arrow (widget, ARROW_MONTH_LEFT);
2371 if (event->window == private_data->arrow_win[ARROW_MONTH_RIGHT])
2373 private_data->arrow_state[ARROW_MONTH_RIGHT] = GTK_STATE_PRELIGHT;
2374 gtk_calendar_paint_arrow (widget, ARROW_MONTH_RIGHT);
2377 if (event->window == private_data->arrow_win[ARROW_YEAR_LEFT])
2379 private_data->arrow_state[ARROW_YEAR_LEFT] = GTK_STATE_PRELIGHT;
2380 gtk_calendar_paint_arrow (widget, ARROW_YEAR_LEFT);
2383 if (event->window == private_data->arrow_win[ARROW_YEAR_RIGHT])
2385 private_data->arrow_state[ARROW_YEAR_RIGHT] = GTK_STATE_PRELIGHT;
2386 gtk_calendar_paint_arrow (widget, ARROW_YEAR_RIGHT);
2393 gtk_calendar_leave_notify (GtkWidget *widget,
2394 GdkEventCrossing *event)
2396 GtkCalendar *calendar;
2397 GtkCalendarPrivateData *private_data;
2401 g_return_val_if_fail (widget != NULL, FALSE);
2402 g_return_val_if_fail (event != NULL, FALSE);
2404 calendar = GTK_CALENDAR (widget);
2405 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2407 if (event->window == private_data->main_win)
2409 row = calendar->highlight_row;
2410 col = calendar->highlight_col;
2411 calendar->highlight_row = -1;
2412 calendar->highlight_col = -1;
2413 if (row > -1 && col > -1)
2414 gtk_calendar_paint_day (widget, row, col);
2417 if (event->window == private_data->arrow_win[ARROW_MONTH_LEFT])
2419 private_data->arrow_state[ARROW_MONTH_LEFT] = GTK_STATE_NORMAL;
2420 gtk_calendar_paint_arrow (widget, ARROW_MONTH_LEFT);
2423 if (event->window == private_data->arrow_win[ARROW_MONTH_RIGHT])
2425 private_data->arrow_state[ARROW_MONTH_RIGHT] = GTK_STATE_NORMAL;
2426 gtk_calendar_paint_arrow (widget, ARROW_MONTH_RIGHT);
2429 if (event->window == private_data->arrow_win[ARROW_YEAR_LEFT])
2431 private_data->arrow_state[ARROW_YEAR_LEFT] = GTK_STATE_NORMAL;
2432 gtk_calendar_paint_arrow (widget, ARROW_YEAR_LEFT);
2435 if (event->window == private_data->arrow_win[ARROW_YEAR_RIGHT])
2437 private_data->arrow_state[ARROW_YEAR_RIGHT] = GTK_STATE_NORMAL;
2438 gtk_calendar_paint_arrow (widget, ARROW_YEAR_RIGHT);
2445 gtk_calendar_paint_arrow (GtkWidget *widget,
2448 GtkCalendarPrivateData *private_data;
2451 GtkCalendar *calendar;
2455 g_return_if_fail (widget != NULL);
2457 calendar = GTK_CALENDAR (widget);
2458 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2460 if (private_data->freeze_count)
2462 private_data->dirty_header = 1;
2465 window = private_data->arrow_win[arrow];
2468 state = private_data->arrow_state[arrow];
2471 gdk_window_clear (window);
2472 gdk_window_set_background (window, &(widget)->style->bg[state]);
2473 gdk_window_get_size (window, &width, &height);
2474 gdk_window_clear_area (window,
2478 gdk_gc_set_foreground (gc, & (widget)->style->fg[state]);
2480 if (arrow == ARROW_MONTH_LEFT || arrow == ARROW_YEAR_LEFT)
2481 draw_arrow_left (window, gc, width/2 - 3, height/2 - 4, 8);
2483 draw_arrow_right (window, gc, width/2 - 2, height/2 - 4, 8);
2489 gtk_calendar_freeze (GtkCalendar *calendar)
2491 g_return_if_fail (calendar != NULL);
2492 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2494 GTK_CALENDAR_PRIVATE_DATA (calendar)->freeze_count++;
2498 gtk_calendar_thaw (GtkCalendar *calendar)
2500 GtkCalendarPrivateData *private_data;
2502 g_return_if_fail (calendar != NULL);
2503 g_return_if_fail (GTK_IS_CALENDAR (calendar));
2505 private_data = GTK_CALENDAR_PRIVATE_DATA (calendar);
2507 if (private_data->freeze_count)
2508 if (!(--private_data->freeze_count))
2510 if (private_data->dirty_header)
2511 if (GTK_WIDGET_DRAWABLE (calendar))
2512 gtk_calendar_paint_header (GTK_WIDGET (calendar));
2514 if (private_data->dirty_day_names)
2515 if (GTK_WIDGET_DRAWABLE (calendar))
2516 gtk_calendar_paint_day_names (GTK_WIDGET (calendar));
2518 if (private_data->dirty_week)
2519 if (GTK_WIDGET_DRAWABLE (calendar))
2520 gtk_calendar_paint_week_numbers (GTK_WIDGET (calendar));
2522 if (private_data->dirty_main)
2523 if (GTK_WIDGET_DRAWABLE (calendar))
2524 gtk_calendar_paint_main (GTK_WIDGET (calendar));
2529 gtk_calendar_set_background (GtkWidget *widget)
2531 GtkCalendar *calendar;
2532 GtkCalendarPrivateData *private_data;
2535 g_return_if_fail (widget != NULL);
2536 g_return_if_fail (GTK_IS_CALENDAR (widget));
2538 calendar = GTK_CALENDAR (widget);
2539 private_data = GTK_CALENDAR_PRIVATE_DATA (widget);
2541 if (GTK_WIDGET_REALIZED (widget))
2543 for (i = 0; i < 4; i++)
2545 if (private_data->arrow_win[i])
2546 gdk_window_set_background (private_data->arrow_win[i],
2547 HEADER_BG_COLOR (widget));
2549 if (private_data->header_win)
2550 gdk_window_set_background (private_data->header_win,
2551 HEADER_BG_COLOR (widget));
2552 if (private_data->day_name_win)
2553 gdk_window_set_background (private_data->day_name_win,
2554 BACKGROUND_COLOR (widget));
2555 if (private_data->week_win)
2556 gdk_window_set_background (private_data->week_win,
2557 BACKGROUND_COLOR (widget));
2558 if (private_data->main_win)
2559 gdk_window_set_background (private_data->main_win,
2560 BACKGROUND_COLOR (widget));
2562 gdk_window_set_background (widget->window,
2563 BACKGROUND_COLOR (widget));
2565 if (GTK_WIDGET_DRAWABLE (widget))
2566 gdk_window_clear (widget->window);
2570 gtk_calendar_style_set (GtkWidget *widget,
2571 GtkStyle *previous_style)
2573 g_return_if_fail (widget != NULL);
2574 g_return_if_fail (GTK_IS_CALENDAR (widget));
2576 if (previous_style && GTK_WIDGET_REALIZED (widget))
2577 gtk_calendar_set_background(widget);
2581 gtk_calendar_state_changed (GtkWidget *widget,
2582 GtkStateType previous_state)
2584 g_return_if_fail (widget != NULL);
2585 g_return_if_fail (GTK_IS_CALENDAR (widget));
2587 gtk_calendar_set_background (widget);
2591 gtk_calendar_focus_in (GtkWidget *widget,
2592 GdkEventFocus *event)
2594 GtkCalendar *calendar;
2596 g_return_val_if_fail (widget != NULL, FALSE);
2597 g_return_val_if_fail (GTK_IS_CALENDAR (widget), FALSE);
2598 g_return_val_if_fail (event != NULL, FALSE);
2600 calendar = GTK_CALENDAR (widget);
2602 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
2603 gtk_widget_draw_focus (widget);
2604 gtk_calendar_paint_day (widget, calendar->focus_row, calendar->focus_col);
2610 gtk_calendar_focus_out (GtkWidget *widget,
2611 GdkEventFocus *event)
2613 GtkCalendar *calendar;
2615 g_return_val_if_fail (widget != NULL, FALSE);
2616 g_return_val_if_fail (GTK_IS_CALENDAR (widget), FALSE);
2617 g_return_val_if_fail (event != NULL, FALSE);
2619 calendar = GTK_CALENDAR (widget);
2621 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
2622 gtk_widget_draw_focus (widget);
2623 gtk_calendar_paint_day (widget, calendar->focus_row, calendar->focus_col);
2629 gtk_calendar_key_press (GtkWidget *widget,
2632 GtkCalendar *calendar;
2638 g_return_val_if_fail (widget != NULL, FALSE);
2639 g_return_val_if_fail (GTK_IS_CALENDAR (widget), FALSE);
2640 g_return_val_if_fail (event != NULL, FALSE);
2642 calendar = GTK_CALENDAR (widget);
2645 old_focus_row = calendar->focus_row;
2646 old_focus_col = calendar->focus_col;
2648 switch (event->keyval)
2652 if (event->state & GDK_CONTROL_MASK)
2654 gtk_calendar_set_month_prev (calendar);
2658 if (calendar->focus_col > 0)
2660 calendar->focus_col--;
2662 else if (calendar->focus_row > 0)
2664 calendar->focus_col = 6;
2665 calendar->focus_row--;
2667 gtk_calendar_paint_day (widget, old_focus_row, old_focus_col);
2668 gtk_calendar_paint_day (widget, calendar->focus_row,
2669 calendar->focus_col);
2674 if (event->state & GDK_CONTROL_MASK)
2676 gtk_calendar_set_month_next (calendar);
2680 if (calendar->focus_col < 6)
2682 calendar->focus_col++;
2684 else if (calendar->focus_row < 5)
2686 calendar->focus_col = 0;
2687 calendar->focus_row++;
2689 gtk_calendar_paint_day (widget, old_focus_row, old_focus_col);
2690 gtk_calendar_paint_day (widget, calendar->focus_row,
2691 calendar->focus_col);
2696 if (event->state & GDK_CONTROL_MASK)
2698 gtk_calendar_set_year_prev (calendar);
2702 if (calendar->focus_row > 0)
2704 calendar->focus_row--;
2706 gtk_calendar_paint_day (widget, old_focus_row, old_focus_col);
2707 gtk_calendar_paint_day (widget, calendar->focus_row,
2708 calendar->focus_col);
2713 if (event->state & GDK_CONTROL_MASK)
2715 gtk_calendar_set_year_next (calendar);
2719 if (calendar->focus_row < 5)
2721 calendar->focus_row++;
2723 gtk_calendar_paint_day (widget, old_focus_row, old_focus_col);
2724 gtk_calendar_paint_day (widget, calendar->focus_row,
2725 calendar->focus_col);
2729 row = calendar->focus_row;
2730 col = calendar->focus_col;
2731 day = calendar->day[row][col];
2733 if (row > -1 && col > -1)
2735 gtk_calendar_freeze (calendar);
2737 if (calendar->day_month[row][col] == MONTH_PREV)
2739 gtk_calendar_set_month_prev (calendar);
2741 else if (calendar->day_month[row][col] == MONTH_NEXT)
2743 gtk_calendar_set_month_next (calendar);
2746 gtk_calendar_select_day (calendar, day);
2748 for (row = 0; row < 6; row ++)
2749 for (col = 0; col < 7; col++)
2751 if (calendar->day_month[row][col] == MONTH_CURRENT
2752 && calendar->day[row][col] == day)
2754 calendar->focus_row = row;
2755 calendar->focus_col = col;
2758 gtk_calendar_thaw (calendar);