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 Groenlund
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 Lesser 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 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser 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.
26 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
27 * file for a list of people on the GTK+ Team. See the ChangeLog
28 * files for a list of changes. These files are distributed with
29 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
34 #ifdef HAVE_SYS_TIME_H
37 #ifdef HAVE__NL_TIME_FIRST_WEEKDAY
43 #include <glib/gprintf.h>
45 #undef GTK_DISABLE_DEPRECATED
46 #include "gtkcalendar.h"
47 #define GTK_DISABLE_DEPRECATED
52 #include "gtkmarshalers.h"
53 #include "gtkprivate.h"
55 #include "gdk/gdkkeysyms.h"
58 /***************************************************************************/
59 /* The following date routines are taken from the lib_date package. Keep
60 * them separate in case we want to update them if a newer lib_date comes
63 typedef unsigned int N_int;
64 typedef unsigned long N_long;
65 typedef signed long Z_long;
66 typedef enum { false = FALSE , true = TRUE } boolean;
68 #define and && /* logical (boolean) operators: lower case */
71 static const N_int month_length[2][13] =
73 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
74 { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
77 static const N_int days_in_months[2][14] =
79 { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
80 { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
83 static Z_long calc_days(N_int year, N_int mm, N_int dd);
84 static N_int day_of_week(N_int year, N_int mm, N_int dd);
85 static Z_long dates_difference(N_int year1, N_int mm1, N_int dd1,
86 N_int year2, N_int mm2, N_int dd2);
87 static N_int weeks_in_year(N_int year);
92 return((((year % 4) == 0) and ((year % 100) != 0)) or ((year % 400) == 0));
96 day_of_week(N_int year, N_int mm, N_int dd)
100 days = calc_days(year, mm, dd);
107 return( (N_int) days );
110 static N_int weeks_in_year(N_int year)
112 return(52 + ((day_of_week(year,1,1)==4) or (day_of_week(year,12,31)==4)));
116 check_date(N_int year, N_int mm, N_int dd)
118 if (year < 1) return(false);
119 if ((mm < 1) or (mm > 12)) return(false);
120 if ((dd < 1) or (dd > month_length[leap(year)][mm])) return(false);
125 week_number(N_int year, N_int mm, N_int dd)
129 first = day_of_week(year,1,1) - 1;
130 return( (N_int) ( (dates_difference(year,1,1, year,mm,dd) + first) / 7L ) +
135 year_to_days(N_int year)
137 return( year * 365L + (year / 4) - (year / 100) + (year / 400) );
142 calc_days(N_int year, N_int mm, N_int dd)
146 if (year < 1) return(0L);
147 if ((mm < 1) or (mm > 12)) return(0L);
148 if ((dd < 1) or (dd > month_length[(lp = leap(year))][mm])) return(0L);
149 return( year_to_days(--year) + days_in_months[lp][mm] + dd );
153 week_of_year(N_int *week, N_int *year, N_int mm, N_int dd)
155 if (check_date(*year,mm,dd))
157 *week = week_number(*year,mm,dd);
159 *week = weeks_in_year(--(*year));
160 else if (*week > weeks_in_year(*year))
171 dates_difference(N_int year1, N_int mm1, N_int dd1,
172 N_int year2, N_int mm2, N_int dd2)
174 return( calc_days(year2, mm2, dd2) - calc_days(year1, mm1, dd1) );
177 /*** END OF lib_date routines ********************************************/
179 /* Spacing around day/week headers and main area, inside those windows */
180 #define CALENDAR_MARGIN 0
181 /* Spacing around day/week headers and main area, outside those windows */
182 #define INNER_BORDER 4
183 /* Separation between day headers and main area */
184 #define CALENDAR_YSEP 4
185 /* Separation between week headers and main area */
186 #define CALENDAR_XSEP 4
188 #define DAY_XSEP 0 /* not really good for small calendar */
189 #define DAY_YSEP 0 /* not really good for small calendar */
192 #define HEADER_FG_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
193 #define HEADER_BG_COLOR(widget) (& (widget)->style->bg[GTK_WIDGET_STATE (widget)])
194 #define SELECTED_BG_COLOR(widget) (& (widget)->style->base[GTK_WIDGET_HAS_FOCUS (widget) ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE])
195 #define SELECTED_FG_COLOR(widget) (& (widget)->style->text[GTK_WIDGET_HAS_FOCUS (widget) ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE])
196 #define NORMAL_DAY_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
197 #define PREV_MONTH_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
198 #define NEXT_MONTH_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
199 #define MARKED_COLOR(widget) (& (widget)->style->fg[GTK_WIDGET_STATE (widget)])
200 #define BACKGROUND_COLOR(widget) (& (widget)->style->base[GTK_WIDGET_STATE (widget)])
201 #define HIGHLIGHT_BACK_COLOR(widget) (& (widget)->style->mid[GTK_WIDGET_STATE (widget)])
217 MONTH_CHANGED_SIGNAL,
219 DAY_SELECTED_DOUBLE_CLICK_SIGNAL,
235 PROP_NO_MONTH_CHANGE,
236 PROP_SHOW_WEEK_NUMBERS,
240 static guint gtk_calendar_signals[LAST_SIGNAL] = { 0 };
242 struct _GtkCalendarPrivate
244 GdkWindow *header_win;
245 GdkWindow *day_name_win;
248 GdkWindow *arrow_win[4];
254 guint arrow_state[4];
256 guint max_month_width;
257 guint max_year_width;
263 guint max_day_char_width;
264 guint max_day_char_ascent;
265 guint max_day_char_descent;
266 guint max_label_char_ascent;
267 guint max_label_char_descent;
268 guint max_week_char_width;
271 guint year_before : 1;
273 guint need_timer : 1;
276 guint drag_highlight : 1;
287 #define GTK_CALENDAR_GET_PRIVATE(widget) (GTK_CALENDAR (widget)->priv)
289 static void gtk_calendar_finalize (GObject *calendar);
290 static void gtk_calendar_destroy (GtkObject *calendar);
291 static void gtk_calendar_set_property (GObject *object,
295 static void gtk_calendar_get_property (GObject *object,
300 static void gtk_calendar_realize (GtkWidget *widget);
301 static void gtk_calendar_unrealize (GtkWidget *widget);
302 static void gtk_calendar_size_request (GtkWidget *widget,
303 GtkRequisition *requisition);
304 static void gtk_calendar_size_allocate (GtkWidget *widget,
305 GtkAllocation *allocation);
306 static gboolean gtk_calendar_expose (GtkWidget *widget,
307 GdkEventExpose *event);
308 static gboolean gtk_calendar_button_press (GtkWidget *widget,
309 GdkEventButton *event);
310 static gboolean gtk_calendar_button_release (GtkWidget *widget,
311 GdkEventButton *event);
312 static gboolean gtk_calendar_motion_notify (GtkWidget *widget,
313 GdkEventMotion *event);
314 static gboolean gtk_calendar_enter_notify (GtkWidget *widget,
315 GdkEventCrossing *event);
316 static gboolean gtk_calendar_leave_notify (GtkWidget *widget,
317 GdkEventCrossing *event);
318 static gboolean gtk_calendar_scroll (GtkWidget *widget,
319 GdkEventScroll *event);
320 static gboolean gtk_calendar_key_press (GtkWidget *widget,
322 static gboolean gtk_calendar_focus_out (GtkWidget *widget,
323 GdkEventFocus *event);
324 static void gtk_calendar_grab_notify (GtkWidget *widget,
325 gboolean was_grabbed);
326 static void gtk_calendar_state_changed (GtkWidget *widget,
327 GtkStateType previous_state);
328 static void gtk_calendar_style_set (GtkWidget *widget,
329 GtkStyle *previous_style);
331 static void gtk_calendar_drag_data_get (GtkWidget *widget,
332 GdkDragContext *context,
333 GtkSelectionData *selection_data,
336 static void gtk_calendar_drag_data_received (GtkWidget *widget,
337 GdkDragContext *context,
340 GtkSelectionData *selection_data,
343 static gboolean gtk_calendar_drag_motion (GtkWidget *widget,
344 GdkDragContext *context,
348 static void gtk_calendar_drag_leave (GtkWidget *widget,
349 GdkDragContext *context,
351 static gboolean gtk_calendar_drag_drop (GtkWidget *widget,
352 GdkDragContext *context,
357 static void calendar_start_spinning (GtkCalendar *calendar,
359 static void calendar_stop_spinning (GtkCalendar *calendar);
361 static void calendar_invalidate_day (GtkCalendar *widget,
364 static void calendar_invalidate_day_num (GtkCalendar *widget,
366 static void calendar_invalidate_arrow (GtkCalendar *widget,
369 static void calendar_compute_days (GtkCalendar *calendar);
371 static char *default_abbreviated_dayname[7];
372 static char *default_monthname[12];
374 G_DEFINE_TYPE (GtkCalendar, gtk_calendar, GTK_TYPE_WIDGET)
377 gtk_calendar_class_init (GtkCalendarClass *class)
379 GObjectClass *gobject_class;
380 GtkObjectClass *object_class;
381 GtkWidgetClass *widget_class;
383 gobject_class = (GObjectClass*) class;
384 object_class = (GtkObjectClass*) class;
385 widget_class = (GtkWidgetClass*) class;
387 gobject_class->set_property = gtk_calendar_set_property;
388 gobject_class->get_property = gtk_calendar_get_property;
389 gobject_class->finalize = gtk_calendar_finalize;
391 object_class->destroy = gtk_calendar_destroy;
393 widget_class->realize = gtk_calendar_realize;
394 widget_class->unrealize = gtk_calendar_unrealize;
395 widget_class->expose_event = gtk_calendar_expose;
396 widget_class->size_request = gtk_calendar_size_request;
397 widget_class->size_allocate = gtk_calendar_size_allocate;
398 widget_class->button_press_event = gtk_calendar_button_press;
399 widget_class->button_release_event = gtk_calendar_button_release;
400 widget_class->motion_notify_event = gtk_calendar_motion_notify;
401 widget_class->enter_notify_event = gtk_calendar_enter_notify;
402 widget_class->leave_notify_event = gtk_calendar_leave_notify;
403 widget_class->key_press_event = gtk_calendar_key_press;
404 widget_class->scroll_event = gtk_calendar_scroll;
405 widget_class->style_set = gtk_calendar_style_set;
406 widget_class->state_changed = gtk_calendar_state_changed;
407 widget_class->grab_notify = gtk_calendar_grab_notify;
408 widget_class->focus_out_event = gtk_calendar_focus_out;
410 widget_class->drag_data_get = gtk_calendar_drag_data_get;
411 widget_class->drag_motion = gtk_calendar_drag_motion;
412 widget_class->drag_leave = gtk_calendar_drag_leave;
413 widget_class->drag_drop = gtk_calendar_drag_drop;
414 widget_class->drag_data_received = gtk_calendar_drag_data_received;
416 g_object_class_install_property (gobject_class,
418 g_param_spec_int ("year",
420 P_("The selected year"),
422 GTK_PARAM_READWRITE));
423 g_object_class_install_property (gobject_class,
425 g_param_spec_int ("month",
427 P_("The selected month (as a number between 0 and 11)"),
429 GTK_PARAM_READWRITE));
430 g_object_class_install_property (gobject_class,
432 g_param_spec_int ("day",
434 P_("The selected day (as a number between 1 and 31, or 0 to unselect the currently selected day)"),
436 GTK_PARAM_READWRITE));
439 * GtkCalendar:show-heading:
441 * Determines whether a heading is displayed.
445 g_object_class_install_property (gobject_class,
447 g_param_spec_boolean ("show-heading",
449 P_("If TRUE, a heading is displayed"),
451 GTK_PARAM_READWRITE));
454 * GtkCalendar:show-day-names:
456 * Determines whether day names are displayed.
460 g_object_class_install_property (gobject_class,
462 g_param_spec_boolean ("show-day-names",
463 P_("Show Day Names"),
464 P_("If TRUE, day names are displayed"),
466 GTK_PARAM_READWRITE));
468 * GtkCalendar:no-month-change:
470 * Determines whether the selected month can be changed.
474 g_object_class_install_property (gobject_class,
475 PROP_NO_MONTH_CHANGE,
476 g_param_spec_boolean ("no-month-change",
477 P_("No Month Change"),
478 P_("If TRUE, the selected month cannot be changed"),
480 GTK_PARAM_READWRITE));
483 * GtkCalendar:show-week-numbers:
485 * Determines whether week numbers are displayed.
489 g_object_class_install_property (gobject_class,
490 PROP_SHOW_WEEK_NUMBERS,
491 g_param_spec_boolean ("show-week-numbers",
492 P_("Show Week Numbers"),
493 P_("If TRUE, week numbers are displayed"),
495 GTK_PARAM_READWRITE));
497 gtk_calendar_signals[MONTH_CHANGED_SIGNAL] =
498 g_signal_new (I_("month_changed"),
499 G_OBJECT_CLASS_TYPE (gobject_class),
501 G_STRUCT_OFFSET (GtkCalendarClass, month_changed),
503 _gtk_marshal_VOID__VOID,
505 gtk_calendar_signals[DAY_SELECTED_SIGNAL] =
506 g_signal_new (I_("day_selected"),
507 G_OBJECT_CLASS_TYPE (gobject_class),
509 G_STRUCT_OFFSET (GtkCalendarClass, day_selected),
511 _gtk_marshal_VOID__VOID,
513 gtk_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL] =
514 g_signal_new (I_("day_selected_double_click"),
515 G_OBJECT_CLASS_TYPE (gobject_class),
517 G_STRUCT_OFFSET (GtkCalendarClass, day_selected_double_click),
519 _gtk_marshal_VOID__VOID,
521 gtk_calendar_signals[PREV_MONTH_SIGNAL] =
522 g_signal_new (I_("prev_month"),
523 G_OBJECT_CLASS_TYPE (gobject_class),
525 G_STRUCT_OFFSET (GtkCalendarClass, prev_month),
527 _gtk_marshal_VOID__VOID,
529 gtk_calendar_signals[NEXT_MONTH_SIGNAL] =
530 g_signal_new (I_("next_month"),
531 G_OBJECT_CLASS_TYPE (gobject_class),
533 G_STRUCT_OFFSET (GtkCalendarClass, next_month),
535 _gtk_marshal_VOID__VOID,
537 gtk_calendar_signals[PREV_YEAR_SIGNAL] =
538 g_signal_new (I_("prev_year"),
539 G_OBJECT_CLASS_TYPE (gobject_class),
541 G_STRUCT_OFFSET (GtkCalendarClass, prev_year),
543 _gtk_marshal_VOID__VOID,
545 gtk_calendar_signals[NEXT_YEAR_SIGNAL] =
546 g_signal_new (I_("next_year"),
547 G_OBJECT_CLASS_TYPE (gobject_class),
549 G_STRUCT_OFFSET (GtkCalendarClass, next_year),
551 _gtk_marshal_VOID__VOID,
554 g_type_class_add_private (gobject_class, sizeof (GtkCalendarPrivate));
558 gtk_calendar_init (GtkCalendar *calendar)
560 GtkWidget *widget = GTK_WIDGET (calendar);
566 GtkCalendarPrivate *priv;
570 priv = calendar->priv = G_TYPE_INSTANCE_GET_PRIVATE (calendar,
574 GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
576 if (!default_abbreviated_dayname[0])
579 tmp_time= (i+3)*86400;
580 strftime ( buffer, sizeof (buffer), "%a", gmtime (&tmp_time));
581 default_abbreviated_dayname[i] = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
584 if (!default_monthname[0])
588 strftime ( buffer, sizeof (buffer), "%B", gmtime (&tmp_time));
589 default_monthname[i] = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
594 tm = localtime (&secs);
595 calendar->month = tm->tm_mon;
596 calendar->year = 1900 + tm->tm_year;
598 calendar_compute_days (calendar);
601 calendar->marked_date[i] = FALSE;
602 calendar->num_marked_dates = 0;
603 calendar->selected_day = tm->tm_mday;
605 calendar->display_flags = ( GTK_CALENDAR_SHOW_HEADING |
606 GTK_CALENDAR_SHOW_DAY_NAMES );
608 calendar->highlight_row = -1;
609 calendar->highlight_col = -1;
611 calendar->focus_row = -1;
612 calendar->focus_col = -1;
614 priv->max_year_width = 0;
615 priv->max_month_width = 0;
616 priv->max_day_char_width = 0;
617 priv->max_week_char_width = 0;
619 priv->max_day_char_ascent = 0;
620 priv->max_day_char_descent = 0;
621 priv->max_label_char_ascent = 0;
622 priv->max_label_char_descent = 0;
624 priv->arrow_width = 10;
626 priv->need_timer = 0;
628 priv->click_child = -1;
631 priv->drag_highlight = 0;
633 gtk_drag_dest_set (widget, 0, NULL, 0, GDK_ACTION_COPY);
634 gtk_drag_dest_add_text_targets (widget);
636 priv->year_before = 0;
638 /* Translate to calendar:YM if you want years to be displayed
639 * before months; otherwise translate to calendar:MY.
640 * Do *not* translate it to anything else, if it
641 * it isn't calendar:YM or calendar:MY it will not work.
643 * Note that this flipping is in top the text direction flipping,
644 * so if you have a default text direction of RTL and YM, then
645 * the year will appear on the right.
647 year_before = _("calendar:MY");
648 if (strcmp (year_before, "calendar:YM") == 0)
649 priv->year_before = 1;
650 else if (strcmp (year_before, "calendar:MY") != 0)
651 g_warning ("Whoever translated calendar:MY did so wrongly.\n");
653 #ifdef HAVE__NL_TIME_FIRST_WEEKDAY
654 week_start = nl_langinfo (_NL_TIME_FIRST_WEEKDAY);
655 priv->week_start = (*((unsigned char *) week_start) - 1) % 7;
657 /* Translate to calendar:week_start:0 if you want Sunday to be the
658 * first day of the week to calendar:week_start:1 if you want Monday
659 * to be the first day of the week, and so on.
661 week_start = _("calendar:week_start:0");
663 if (strncmp (week_start, "calendar:week_start:", 20) == 0)
664 priv->week_start = *(week_start + 20) - '0';
666 priv->week_start = -1;
668 if (priv->week_start < 0 || priv->week_start > 6)
670 g_warning ("Whoever translated calendar:week_start:0 did so wrongly.\n");
671 priv->week_start = 0;
677 /****************************************
678 * Utility Functions *
679 ****************************************/
682 calendar_set_month_next (GtkCalendar *calendar)
686 g_return_if_fail (GTK_IS_WIDGET (calendar));
688 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
692 if (calendar->month == 11)
700 calendar_compute_days (calendar);
701 g_signal_emit (calendar,
702 gtk_calendar_signals[NEXT_MONTH_SIGNAL],
704 g_signal_emit (calendar,
705 gtk_calendar_signals[MONTH_CHANGED_SIGNAL],
708 month_len = month_length[leap (calendar->year)][calendar->month + 1];
710 if (month_len < calendar->selected_day)
712 calendar->selected_day = 0;
713 gtk_calendar_select_day (calendar, month_len);
716 gtk_calendar_select_day (calendar, calendar->selected_day);
718 gtk_widget_queue_draw (GTK_WIDGET (calendar));
722 calendar_set_year_prev (GtkCalendar *calendar)
726 g_return_if_fail (GTK_IS_WIDGET (calendar));
729 calendar_compute_days (calendar);
730 g_signal_emit (calendar,
731 gtk_calendar_signals[PREV_YEAR_SIGNAL],
733 g_signal_emit (calendar,
734 gtk_calendar_signals[MONTH_CHANGED_SIGNAL],
737 month_len = month_length[leap (calendar->year)][calendar->month + 1];
739 if (month_len < calendar->selected_day)
741 calendar->selected_day = 0;
742 gtk_calendar_select_day (calendar, month_len);
745 gtk_calendar_select_day (calendar, calendar->selected_day);
747 gtk_widget_queue_draw (GTK_WIDGET (calendar));
751 calendar_set_year_next (GtkCalendar *calendar)
756 g_return_if_fail (GTK_IS_WIDGET (calendar));
758 widget = GTK_WIDGET (calendar);
761 calendar_compute_days (calendar);
762 g_signal_emit (calendar,
763 gtk_calendar_signals[NEXT_YEAR_SIGNAL],
765 g_signal_emit (calendar,
766 gtk_calendar_signals[MONTH_CHANGED_SIGNAL],
769 month_len = month_length[leap (calendar->year)][calendar->month + 1];
771 if (month_len < calendar->selected_day)
773 calendar->selected_day = 0;
774 gtk_calendar_select_day (calendar, month_len);
777 gtk_calendar_select_day (calendar, calendar->selected_day);
779 gtk_widget_queue_draw (GTK_WIDGET (calendar));
783 calendar_compute_days (GtkCalendar *calendar)
785 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (GTK_WIDGET (calendar));
789 gint ndays_in_prev_month;
795 g_return_if_fail (GTK_IS_CALENDAR (calendar));
797 year = calendar->year;
798 month = calendar->month + 1;
800 ndays_in_month = month_length[leap (year)][month];
802 first_day = day_of_week (year, month, 1);
803 first_day = (first_day + 7 - priv->week_start) % 7;
805 /* Compute days of previous month */
807 ndays_in_prev_month = month_length[leap (year)][month-1];
809 ndays_in_prev_month = month_length[leap (year)][12];
810 day = ndays_in_prev_month - first_day + 1;
815 for (col = 0; col < first_day; col++)
817 calendar->day[row][col] = day;
818 calendar->day_month[row][col] = MONTH_PREV;
823 /* Compute days of current month */
825 for (day = 1; day <= ndays_in_month; day++)
827 calendar->day[row][col] = day;
828 calendar->day_month[row][col] = MONTH_CURRENT;
838 /* Compute days of next month */
840 for (; row <= 5; row++)
842 for (; col <= 6; col++)
844 calendar->day[row][col] = day;
845 calendar->day_month[row][col] = MONTH_NEXT;
853 calendar_select_and_focus_day (GtkCalendar *calendar,
856 gint old_focus_row = calendar->focus_row;
857 gint old_focus_col = calendar->focus_col;
861 for (row = 0; row < 6; row ++)
862 for (col = 0; col < 7; col++)
864 if (calendar->day_month[row][col] == MONTH_CURRENT
865 && calendar->day[row][col] == day)
867 calendar->focus_row = row;
868 calendar->focus_col = col;
872 if (old_focus_row != -1 && old_focus_col != -1)
873 calendar_invalidate_day (calendar, old_focus_row, old_focus_col);
875 gtk_calendar_select_day (calendar, day);
879 /****************************************
880 * Layout computation utilities *
881 ****************************************/
884 calendar_row_height (GtkCalendar *calendar)
886 return (GTK_CALENDAR_GET_PRIVATE (calendar)->main_h - CALENDAR_MARGIN
887 - ((calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
888 ? CALENDAR_YSEP : CALENDAR_MARGIN)) / 6;
892 /* calendar_left_x_for_column: returns the x coordinate
893 * for the left of the column */
895 calendar_left_x_for_column (GtkCalendar *calendar,
901 if (gtk_widget_get_direction (GTK_WIDGET (calendar)) == GTK_TEXT_DIR_RTL)
904 width = GTK_CALENDAR_GET_PRIVATE (calendar)->day_width;
905 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
906 x_left = CALENDAR_XSEP + (width + DAY_XSEP) * column;
908 x_left = CALENDAR_MARGIN + (width + DAY_XSEP) * column;
913 /* column_from_x: returns the column 0-6 that the
914 * x pixel of the xwindow is in */
916 calendar_column_from_x (GtkCalendar *calendar,
920 gint x_left, x_right;
924 for (c = 0; c < 7; c++)
926 x_left = calendar_left_x_for_column (calendar, c);
927 x_right = x_left + GTK_CALENDAR_GET_PRIVATE (calendar)->day_width;
929 if (event_x >= x_left && event_x < x_right)
939 /* calendar_top_y_for_row: returns the y coordinate
940 * for the top of the row */
942 calendar_top_y_for_row (GtkCalendar *calendar,
946 return (GTK_CALENDAR_GET_PRIVATE (calendar)->main_h
947 - (CALENDAR_MARGIN + (6 - row)
948 * calendar_row_height (calendar)));
951 /* row_from_y: returns the row 0-5 that the
952 * y pixel of the xwindow is in */
954 calendar_row_from_y (GtkCalendar *calendar,
959 gint y_top, y_bottom;
961 height = calendar_row_height (calendar);
964 for (r = 0; r < 6; r++)
966 y_top = calendar_top_y_for_row (calendar, r);
967 y_bottom = y_top + height;
969 if (event_y >= y_top && event_y < y_bottom)
980 calendar_arrow_rectangle (GtkCalendar *calendar,
984 GtkWidget *widget = GTK_WIDGET (calendar);
985 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
988 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
989 year_left = priv->year_before;
991 year_left = !priv->year_before;
994 rect->width = priv->arrow_width;
995 rect->height = priv->header_h - 7;
999 case ARROW_MONTH_LEFT:
1001 rect->x = (widget->allocation.width - 2 * widget->style->xthickness
1002 - (3 + 2*priv->arrow_width
1003 + priv->max_month_width));
1007 case ARROW_MONTH_RIGHT:
1009 rect->x = (widget->allocation.width - 2 * widget->style->xthickness
1010 - 3 - priv->arrow_width);
1012 rect->x = (priv->arrow_width
1013 + priv->max_month_width);
1015 case ARROW_YEAR_LEFT:
1019 rect->x = (widget->allocation.width - 2 * widget->style->xthickness
1020 - (3 + 2*priv->arrow_width
1021 + priv->max_year_width));
1023 case ARROW_YEAR_RIGHT:
1025 rect->x = (priv->arrow_width
1026 + priv->max_year_width);
1028 rect->x = (widget->allocation.width - 2 * widget->style->xthickness
1029 - 3 - priv->arrow_width);
1035 calendar_day_rectangle (GtkCalendar *calendar,
1040 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
1042 rect->x = calendar_left_x_for_column (calendar, col);
1043 rect->y = calendar_top_y_for_row (calendar, row);
1044 rect->height = calendar_row_height (calendar);
1045 rect->width = priv->day_width;
1049 calendar_set_month_prev (GtkCalendar *calendar)
1053 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1056 if (calendar->month == 0)
1058 calendar->month = 11;
1064 month_len = month_length[leap (calendar->year)][calendar->month + 1];
1066 calendar_compute_days (calendar);
1068 g_signal_emit (calendar,
1069 gtk_calendar_signals[PREV_MONTH_SIGNAL],
1071 g_signal_emit (calendar,
1072 gtk_calendar_signals[MONTH_CHANGED_SIGNAL],
1075 if (month_len < calendar->selected_day)
1077 calendar->selected_day = 0;
1078 gtk_calendar_select_day (calendar, month_len);
1082 if (calendar->selected_day < 0)
1083 calendar->selected_day = calendar->selected_day + 1 + month_length[leap (calendar->year)][calendar->month + 1];
1084 gtk_calendar_select_day (calendar, calendar->selected_day);
1087 gtk_widget_queue_draw (GTK_WIDGET (calendar));
1091 /****************************************
1092 * Basic object methods *
1093 ****************************************/
1096 gtk_calendar_finalize (GObject *object)
1098 (* G_OBJECT_CLASS (gtk_calendar_parent_class)->finalize) (object);
1102 gtk_calendar_destroy (GtkObject *object)
1104 calendar_stop_spinning (GTK_CALENDAR (object));
1106 GTK_OBJECT_CLASS (gtk_calendar_parent_class)->destroy (object);
1111 calendar_set_display_option (GtkCalendar *calendar,
1112 GtkCalendarDisplayOptions flag,
1115 GtkCalendarDisplayOptions flags;
1117 flags = calendar->display_flags | flag;
1119 flags = calendar->display_flags & ~flag;
1120 gtk_calendar_display_options (calendar, flags);
1124 calendar_get_display_option (GtkCalendar *calendar,
1125 GtkCalendarDisplayOptions flag)
1127 return (calendar->display_flags & flag) != 0;
1131 gtk_calendar_set_property (GObject *object,
1133 const GValue *value,
1136 GtkCalendar *calendar;
1138 calendar = GTK_CALENDAR (object);
1143 gtk_calendar_select_month (calendar,
1145 g_value_get_int (value));
1148 gtk_calendar_select_month (calendar,
1149 g_value_get_int (value),
1153 gtk_calendar_select_day (calendar,
1154 g_value_get_int (value));
1156 case PROP_SHOW_HEADING:
1157 calendar_set_display_option (calendar,
1158 GTK_CALENDAR_SHOW_HEADING,
1159 g_value_get_boolean (value));
1161 case PROP_SHOW_DAY_NAMES:
1162 calendar_set_display_option (calendar,
1163 GTK_CALENDAR_SHOW_DAY_NAMES,
1164 g_value_get_boolean (value));
1166 case PROP_NO_MONTH_CHANGE:
1167 calendar_set_display_option (calendar,
1168 GTK_CALENDAR_NO_MONTH_CHANGE,
1169 g_value_get_boolean (value));
1171 case PROP_SHOW_WEEK_NUMBERS:
1172 calendar_set_display_option (calendar,
1173 GTK_CALENDAR_SHOW_WEEK_NUMBERS,
1174 g_value_get_boolean (value));
1177 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1183 gtk_calendar_get_property (GObject *object,
1188 GtkCalendar *calendar;
1190 calendar = GTK_CALENDAR (object);
1195 g_value_set_int (value, calendar->year);
1198 g_value_set_int (value, calendar->month);
1201 g_value_set_int (value, calendar->selected_day);
1203 case PROP_SHOW_HEADING:
1204 g_value_set_boolean (value, calendar_get_display_option (calendar,
1205 GTK_CALENDAR_SHOW_HEADING));
1207 case PROP_SHOW_DAY_NAMES:
1208 g_value_set_boolean (value, calendar_get_display_option (calendar,
1209 GTK_CALENDAR_SHOW_DAY_NAMES));
1211 case PROP_NO_MONTH_CHANGE:
1212 g_value_set_boolean (value, calendar_get_display_option (calendar,
1213 GTK_CALENDAR_NO_MONTH_CHANGE));
1215 case PROP_SHOW_WEEK_NUMBERS:
1216 g_value_set_boolean (value, calendar_get_display_option (calendar,
1217 GTK_CALENDAR_SHOW_WEEK_NUMBERS));
1220 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1226 /****************************************
1228 ****************************************/
1231 calendar_realize_arrows (GtkCalendar *calendar)
1233 GtkWidget *widget = GTK_WIDGET (calendar);
1234 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
1235 GdkWindowAttr attributes;
1236 gint attributes_mask;
1239 /* Arrow windows ------------------------------------- */
1240 if (! (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1241 && (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING))
1243 attributes.wclass = GDK_INPUT_OUTPUT;
1244 attributes.window_type = GDK_WINDOW_CHILD;
1245 attributes.visual = gtk_widget_get_visual (widget);
1246 attributes.colormap = gtk_widget_get_colormap (widget);
1247 attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK
1248 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
1249 | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
1250 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1251 for (i = 0; i < 4; i++)
1254 calendar_arrow_rectangle (calendar, i, &rect);
1256 attributes.x = rect.x;
1257 attributes.y = rect.y;
1258 attributes.width = rect.width;
1259 attributes.height = rect.height;
1260 priv->arrow_win[i] = gdk_window_new (priv->header_win,
1263 if (GTK_WIDGET_IS_SENSITIVE (widget))
1264 priv->arrow_state[i] = GTK_STATE_NORMAL;
1266 priv->arrow_state[i] = GTK_STATE_INSENSITIVE;
1267 gdk_window_set_background (priv->arrow_win[i],
1268 HEADER_BG_COLOR (GTK_WIDGET (calendar)));
1269 gdk_window_show (priv->arrow_win[i]);
1270 gdk_window_set_user_data (priv->arrow_win[i], widget);
1275 for (i = 0; i < 4; i++)
1276 priv->arrow_win[i] = NULL;
1281 calendar_realize_header (GtkCalendar *calendar)
1283 GtkWidget *widget = GTK_WIDGET (calendar);
1284 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
1285 GdkWindowAttr attributes;
1286 gint attributes_mask;
1288 /* Header window ------------------------------------- */
1289 if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)
1291 attributes.wclass = GDK_INPUT_OUTPUT;
1292 attributes.window_type = GDK_WINDOW_CHILD;
1293 attributes.visual = gtk_widget_get_visual (widget);
1294 attributes.colormap = gtk_widget_get_colormap (widget);
1295 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
1296 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1297 attributes.x = widget->style->xthickness;
1298 attributes.y = widget->style->ythickness;
1299 attributes.width = widget->allocation.width - 2 * attributes.x;
1300 attributes.height = priv->header_h - 2 * attributes.y;
1301 priv->header_win = gdk_window_new (widget->window,
1302 &attributes, attributes_mask);
1304 gdk_window_set_background (priv->header_win,
1305 HEADER_BG_COLOR (GTK_WIDGET (calendar)));
1306 gdk_window_show (priv->header_win);
1307 gdk_window_set_user_data (priv->header_win, widget);
1312 priv->header_win = NULL;
1314 calendar_realize_arrows (calendar);
1318 calendar_realize_day_names (GtkCalendar *calendar)
1320 GtkWidget *widget = GTK_WIDGET (calendar);
1321 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
1322 GdkWindowAttr attributes;
1323 gint attributes_mask;
1325 /* Day names window --------------------------------- */
1326 if ( calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
1328 attributes.wclass = GDK_INPUT_OUTPUT;
1329 attributes.window_type = GDK_WINDOW_CHILD;
1330 attributes.visual = gtk_widget_get_visual (widget);
1331 attributes.colormap = gtk_widget_get_colormap (widget);
1332 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
1333 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1334 attributes.x = (widget->style->xthickness + INNER_BORDER);
1335 attributes.y = priv->header_h + (widget->style->ythickness
1337 attributes.width = (widget->allocation.width
1338 - (widget->style->xthickness + INNER_BORDER)
1340 attributes.height = priv->day_name_h;
1341 priv->day_name_win = gdk_window_new (widget->window,
1344 gdk_window_set_background (priv->day_name_win,
1345 BACKGROUND_COLOR ( GTK_WIDGET ( calendar)));
1346 gdk_window_show (priv->day_name_win);
1347 gdk_window_set_user_data (priv->day_name_win, widget);
1351 priv->day_name_win = NULL;
1356 calendar_realize_week_numbers (GtkCalendar *calendar)
1358 GtkWidget *widget = GTK_WIDGET (calendar);
1359 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
1360 GdkWindowAttr attributes;
1361 gint attributes_mask;
1363 /* Week number window -------------------------------- */
1364 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1366 attributes.wclass = GDK_INPUT_OUTPUT;
1367 attributes.window_type = GDK_WINDOW_CHILD;
1368 attributes.visual = gtk_widget_get_visual (widget);
1369 attributes.colormap = gtk_widget_get_colormap (widget);
1370 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
1372 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1373 attributes.x = widget->style->xthickness + INNER_BORDER;
1374 attributes.y = (priv->header_h + priv->day_name_h
1375 + (widget->style->ythickness + INNER_BORDER));
1376 attributes.width = priv->week_width;
1377 attributes.height = priv->main_h;
1378 priv->week_win = gdk_window_new (widget->window,
1379 &attributes, attributes_mask);
1380 gdk_window_set_background (priv->week_win,
1381 BACKGROUND_COLOR (GTK_WIDGET (calendar)));
1382 gdk_window_show (priv->week_win);
1383 gdk_window_set_user_data (priv->week_win, widget);
1387 priv->week_win = NULL;
1392 gtk_calendar_realize (GtkWidget *widget)
1394 GtkCalendar *calendar = GTK_CALENDAR (widget);
1395 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
1396 GdkWindowAttr attributes;
1397 gint attributes_mask;
1399 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
1401 attributes.x = widget->allocation.x;
1402 attributes.y = widget->allocation.y;
1403 attributes.width = widget->allocation.width;
1404 attributes.height = widget->allocation.height;
1405 attributes.wclass = GDK_INPUT_OUTPUT;
1406 attributes.window_type = GDK_WINDOW_CHILD;
1407 attributes.event_mask = (gtk_widget_get_events (widget)
1408 | GDK_EXPOSURE_MASK |GDK_KEY_PRESS_MASK | GDK_SCROLL_MASK);
1409 attributes.visual = gtk_widget_get_visual (widget);
1410 attributes.colormap = gtk_widget_get_colormap (widget);
1412 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1413 widget->window = gdk_window_new (widget->parent->window,
1414 &attributes, attributes_mask);
1416 widget->style = gtk_style_attach (widget->style, widget->window);
1418 /* Header window ------------------------------------- */
1419 calendar_realize_header (calendar);
1420 /* Day names window --------------------------------- */
1421 calendar_realize_day_names (calendar);
1422 /* Week number window -------------------------------- */
1423 calendar_realize_week_numbers (calendar);
1424 /* Main Window -------------------------------------- */
1425 attributes.event_mask = (gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK
1426 | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
1427 | GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK);
1429 attributes.x = priv->week_width + (widget->style->ythickness + INNER_BORDER);
1430 attributes.y = (priv->header_h + priv->day_name_h
1431 + (widget->style->ythickness + INNER_BORDER));
1432 attributes.width = (widget->allocation.width - attributes.x
1433 - (widget->style->xthickness + INNER_BORDER));
1434 attributes.height = priv->main_h;
1435 priv->main_win = gdk_window_new (widget->window,
1436 &attributes, attributes_mask);
1437 gdk_window_set_background (priv->main_win,
1438 BACKGROUND_COLOR ( GTK_WIDGET ( calendar)));
1439 gdk_window_show (priv->main_win);
1440 gdk_window_set_user_data (priv->main_win, widget);
1441 gdk_window_set_background (widget->window, BACKGROUND_COLOR (widget));
1442 gdk_window_show (widget->window);
1443 gdk_window_set_user_data (widget->window, widget);
1447 gtk_calendar_unrealize (GtkWidget *widget)
1449 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
1452 if (priv->header_win)
1454 for (i = 0; i < 4; i++)
1456 if (priv->arrow_win[i])
1458 gdk_window_set_user_data (priv->arrow_win[i], NULL);
1459 gdk_window_destroy (priv->arrow_win[i]);
1460 priv->arrow_win[i] = NULL;
1463 gdk_window_set_user_data (priv->header_win, NULL);
1464 gdk_window_destroy (priv->header_win);
1465 priv->header_win = NULL;
1470 gdk_window_set_user_data (priv->week_win, NULL);
1471 gdk_window_destroy (priv->week_win);
1472 priv->week_win = NULL;
1477 gdk_window_set_user_data (priv->main_win, NULL);
1478 gdk_window_destroy (priv->main_win);
1479 priv->main_win = NULL;
1481 if (priv->day_name_win)
1483 gdk_window_set_user_data (priv->day_name_win, NULL);
1484 gdk_window_destroy (priv->day_name_win);
1485 priv->day_name_win = NULL;
1488 if (GTK_WIDGET_CLASS (gtk_calendar_parent_class)->unrealize)
1489 (* GTK_WIDGET_CLASS (gtk_calendar_parent_class)->unrealize) (widget);
1493 /****************************************
1494 * Size Request and Allocate *
1495 ****************************************/
1498 gtk_calendar_size_request (GtkWidget *widget,
1499 GtkRequisition *requisition)
1501 GtkCalendar *calendar = GTK_CALENDAR (widget);
1502 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
1503 PangoLayout *layout;
1504 PangoRectangle logical_rect;
1509 gint calendar_margin = CALENDAR_MARGIN;
1510 gint header_width, main_width;
1511 gint max_header_height = 0;
1515 gtk_widget_style_get (GTK_WIDGET (widget),
1516 "focus-line-width", &focus_width,
1517 "focus-padding", &focus_padding,
1520 layout = gtk_widget_create_pango_layout (widget, NULL);
1523 * Calculate the requisition width for the widget.
1528 if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)
1530 priv->max_month_width = 0;
1531 for (i = 0; i < 12; i++)
1533 pango_layout_set_text (layout, default_monthname[i], -1);
1534 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1535 priv->max_month_width = MAX (priv->max_month_width,
1536 logical_rect.width + 8);
1537 max_header_height = MAX (max_header_height, logical_rect.height);
1540 priv->max_year_width = 0;
1541 /* Translators: This is a text measurement template.
1542 * Translate it to the widest year text.
1544 * Don't include the prefix "year measurement template|"
1545 * in the translation.
1547 * If you don't understand this, leave it as "2000"
1549 pango_layout_set_text (layout, Q_("year measurement template|2000"), -1);
1550 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1551 priv->max_year_width = MAX (priv->max_year_width,
1552 logical_rect.width + 8);
1553 max_header_height = MAX (max_header_height, logical_rect.height);
1557 priv->max_month_width = 0;
1558 priv->max_year_width = 0;
1561 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1562 header_width = (priv->max_month_width
1563 + priv->max_year_width
1566 header_width = (priv->max_month_width
1567 + priv->max_year_width
1568 + 4 * priv->arrow_width + 3 * 3);
1570 /* Mainwindow labels width */
1572 priv->max_day_char_width = 0;
1573 priv->min_day_width = 0;
1574 priv->max_label_char_ascent = 0;
1575 priv->max_label_char_descent = 0;
1577 for (i = 0; i < 9; i++)
1579 g_snprintf (buffer, sizeof (buffer), "%d%d", i, i);
1580 pango_layout_set_text (layout, buffer, -1);
1581 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1582 priv->min_day_width = MAX (priv->min_day_width,
1583 logical_rect.width);
1585 priv->max_day_char_ascent = MAX (priv->max_label_char_ascent,
1586 PANGO_ASCENT (logical_rect));
1587 priv->max_day_char_descent = MAX (priv->max_label_char_descent,
1588 PANGO_DESCENT (logical_rect));
1590 /* We add one to max_day_char_width to be able to make the marked day "bold" */
1591 priv->max_day_char_width = priv->min_day_width / 2 + 1;
1593 if (calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
1594 for (i = 0; i < 7; i++)
1596 pango_layout_set_text (layout, default_abbreviated_dayname[i], -1);
1597 pango_layout_line_get_pixel_extents (pango_layout_get_lines (layout)->data, NULL, &logical_rect);
1599 priv->min_day_width = MAX (priv->min_day_width, logical_rect.width);
1600 priv->max_label_char_ascent = MAX (priv->max_label_char_ascent,
1601 PANGO_ASCENT (logical_rect));
1602 priv->max_label_char_descent = MAX (priv->max_label_char_descent,
1603 PANGO_DESCENT (logical_rect));
1606 priv->max_week_char_width = 0;
1607 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1608 for (i = 0; i < 9; i++)
1610 g_snprintf (buffer, sizeof (buffer), "%d%d", i, i);
1611 pango_layout_set_text (layout, buffer, -1);
1612 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1613 priv->max_week_char_width = MAX (priv->max_week_char_width,
1614 logical_rect.width / 2);
1617 main_width = (7 * (priv->min_day_width + (focus_padding + focus_width) * 2) + (DAY_XSEP * 6) + CALENDAR_MARGIN * 2
1618 + (priv->max_week_char_width
1619 ? priv->max_week_char_width * 2 + (focus_padding + focus_width) * 2 + CALENDAR_XSEP * 2
1623 requisition->width = MAX (header_width, main_width + INNER_BORDER * 2) + widget->style->xthickness * 2;
1626 * Calculate the requisition height for the widget.
1629 if (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING)
1631 priv->header_h = (max_header_height + CALENDAR_YSEP * 2);
1638 if (calendar->display_flags & GTK_CALENDAR_SHOW_DAY_NAMES)
1640 priv->day_name_h = (priv->max_label_char_ascent
1641 + priv->max_label_char_descent
1642 + 2 * (focus_padding + focus_width) + calendar_margin);
1643 calendar_margin = CALENDAR_YSEP;
1647 priv->day_name_h = 0;
1650 priv->main_h = (CALENDAR_MARGIN + calendar_margin
1651 + 6 * (priv->max_day_char_ascent
1652 + priv->max_day_char_descent
1653 + 2 * (focus_padding + focus_width))
1656 height = (priv->header_h + priv->day_name_h
1659 requisition->height = height + (widget->style->ythickness + INNER_BORDER) * 2;
1661 g_object_unref (layout);
1665 gtk_calendar_size_allocate (GtkWidget *widget,
1666 GtkAllocation *allocation)
1668 GtkCalendar *calendar = GTK_CALENDAR (widget);
1669 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
1670 gint xthickness = widget->style->xthickness;
1671 gint ythickness = widget->style->xthickness;
1675 widget->allocation = *allocation;
1677 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1678 year_left = priv->year_before;
1680 year_left = !priv->year_before;
1682 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1684 priv->day_width = (priv->min_day_width
1685 * ((allocation->width - (xthickness + INNER_BORDER) * 2
1686 - (CALENDAR_MARGIN * 2) - (DAY_XSEP * 6) - CALENDAR_XSEP * 2))
1687 / (7 * priv->min_day_width + priv->max_week_char_width * 2));
1688 priv->week_width = ((allocation->width - (xthickness + INNER_BORDER) * 2
1689 - (CALENDAR_MARGIN * 2) - (DAY_XSEP * 6) - CALENDAR_XSEP * 2 )
1690 - priv->day_width * 7 + CALENDAR_MARGIN + CALENDAR_XSEP);
1694 priv->day_width = (allocation->width
1695 - (xthickness + INNER_BORDER) * 2
1696 - (CALENDAR_MARGIN * 2)
1697 - (DAY_XSEP * 6))/7;
1698 priv->week_width = 0;
1701 if (GTK_WIDGET_REALIZED (widget))
1703 gdk_window_move_resize (widget->window,
1704 allocation->x, allocation->y,
1705 allocation->width, allocation->height);
1706 if (priv->header_win)
1707 gdk_window_move_resize (priv->header_win,
1708 xthickness, ythickness,
1709 allocation->width - 2 * xthickness, priv->header_h);
1711 for (i = 0 ; i < 4 ; i++)
1713 if (priv->arrow_win[i])
1716 calendar_arrow_rectangle (calendar, i, &rect);
1718 gdk_window_move_resize (priv->arrow_win[i],
1719 rect.x, rect.y, rect.width, rect.height);
1723 if (priv->day_name_win)
1724 gdk_window_move_resize (priv->day_name_win,
1725 xthickness + INNER_BORDER,
1726 priv->header_h + (widget->style->ythickness + INNER_BORDER),
1727 allocation->width - (xthickness + INNER_BORDER) * 2,
1729 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1732 gdk_window_move_resize (priv->week_win,
1733 (xthickness + INNER_BORDER),
1734 priv->header_h + priv->day_name_h
1735 + (widget->style->ythickness + INNER_BORDER),
1738 gdk_window_move_resize (priv->main_win,
1739 priv->week_width + (xthickness + INNER_BORDER),
1740 priv->header_h + priv->day_name_h
1741 + (widget->style->ythickness + INNER_BORDER),
1744 - (xthickness + INNER_BORDER) * 2,
1749 gdk_window_move_resize (priv->main_win,
1750 (xthickness + INNER_BORDER),
1751 priv->header_h + priv->day_name_h
1752 + (widget->style->ythickness + INNER_BORDER),
1755 - (xthickness + INNER_BORDER) * 2,
1758 gdk_window_move_resize (priv->week_win,
1761 - (xthickness + INNER_BORDER),
1762 priv->header_h + priv->day_name_h
1763 + (widget->style->ythickness + INNER_BORDER),
1771 /****************************************
1773 ****************************************/
1776 calendar_paint_header (GtkCalendar *calendar)
1778 GtkWidget *widget = GTK_WIDGET (calendar);
1779 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
1783 gint header_width, cal_height;
1784 gint max_month_width;
1785 gint max_year_width;
1786 PangoLayout *layout;
1787 PangoRectangle logical_rect;
1793 if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
1794 year_left = priv->year_before;
1796 year_left = !priv->year_before;
1798 cr = gdk_cairo_create (priv->header_win);
1800 header_width = widget->allocation.width - 2 * widget->style->xthickness;
1801 cal_height = widget->allocation.height;
1803 max_month_width = priv->max_month_width;
1804 max_year_width = priv->max_year_width;
1806 gtk_paint_shadow (widget->style, priv->header_win,
1807 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1808 NULL, widget, "calendar",
1809 0, 0, header_width, priv->header_h);
1811 tmp_time = 1; /* Jan 1 1970, 00:00:01 UTC */
1812 tm = gmtime (&tmp_time);
1813 tm->tm_year = calendar->year - 1900;
1815 /* Translators: This dictates how the year is displayed in
1816 * gtkcalendar widget. See strftime() manual for the format.
1817 * Use only ASCII in the translation.
1819 * Also look for the msgid "year measurement template|2000".
1820 * Translate that entry to a year with the widest output of this
1823 * Don't include the prefix "calendar year format|" in the
1824 * translation. "%Y" is appropriate for most locales.
1826 strftime (buffer, sizeof (buffer), Q_("calendar year format|%Y"), tm);
1827 str = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
1828 layout = gtk_widget_create_pango_layout (widget, str);
1831 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1834 y = (priv->header_h - logical_rect.height) / 2;
1836 /* Draw year and its arrows */
1838 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1840 x = 3 + (max_year_width - logical_rect.width)/2;
1842 x = header_width - (3 + max_year_width
1843 - (max_year_width - logical_rect.width)/2);
1846 x = 3 + priv->arrow_width + (max_year_width - logical_rect.width)/2;
1848 x = header_width - (3 + priv->arrow_width + max_year_width
1849 - (max_year_width - logical_rect.width)/2);
1852 gdk_cairo_set_source_color (cr, HEADER_FG_COLOR (GTK_WIDGET (calendar)));
1853 cairo_move_to (cr, x, y);
1854 pango_cairo_show_layout (cr, layout);
1857 g_snprintf (buffer, sizeof (buffer), "%s", default_monthname[calendar->month]);
1858 pango_layout_set_text (layout, buffer, -1);
1859 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1861 if (calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
1863 x = header_width - (3 + max_month_width
1864 - (max_month_width - logical_rect.width)/2);
1866 x = 3 + (max_month_width - logical_rect.width) / 2;
1869 x = header_width - (3 + priv->arrow_width + max_month_width
1870 - (max_month_width - logical_rect.width)/2);
1872 x = 3 + priv->arrow_width + (max_month_width - logical_rect.width)/2;
1874 cairo_move_to (cr, x, y);
1875 pango_cairo_show_layout (cr, layout);
1877 g_object_unref (layout);
1882 calendar_paint_day_names (GtkCalendar *calendar)
1884 GtkWidget *widget = GTK_WIDGET (calendar);
1885 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
1889 int day_width, cal_width;
1892 PangoLayout *layout;
1893 PangoRectangle logical_rect;
1897 cr = gdk_cairo_create (priv->day_name_win);
1899 gtk_widget_style_get (GTK_WIDGET (widget),
1900 "focus-line-width", &focus_width,
1901 "focus-padding", &focus_padding,
1904 day_width = priv->day_width;
1905 cal_width = widget->allocation.width;
1906 cal_height = widget->allocation.height;
1907 day_wid_sep = day_width + DAY_XSEP;
1910 * Draw rectangles as inverted background for the labels.
1913 gdk_cairo_set_source_color (cr, SELECTED_BG_COLOR (widget));
1914 cairo_rectangle (cr,
1915 CALENDAR_MARGIN, CALENDAR_MARGIN,
1916 cal_width-CALENDAR_MARGIN * 2,
1917 priv->day_name_h - CALENDAR_MARGIN);
1920 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1922 cairo_rectangle (cr,
1924 priv->day_name_h - CALENDAR_YSEP,
1925 priv->week_width - CALENDAR_YSEP - CALENDAR_MARGIN,
1934 layout = gtk_widget_create_pango_layout (widget, NULL);
1936 gdk_cairo_set_source_color (cr, SELECTED_FG_COLOR (widget));
1937 for (i = 0; i < 7; i++)
1939 if (gtk_widget_get_direction (GTK_WIDGET (calendar)) == GTK_TEXT_DIR_RTL)
1943 day = (day + priv->week_start) % 7;
1944 g_snprintf (buffer, sizeof (buffer), "%s", default_abbreviated_dayname[day]);
1946 pango_layout_set_text (layout, buffer, -1);
1947 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1951 + (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ?
1952 (priv->week_width + (priv->week_width ? CALENDAR_XSEP : 0))
1955 + (day_width - logical_rect.width)/2),
1956 CALENDAR_MARGIN + focus_width + focus_padding + logical_rect.y);
1957 pango_cairo_show_layout (cr, layout);
1960 g_object_unref (layout);
1965 calendar_paint_week_numbers (GtkCalendar *calendar)
1967 GtkWidget *widget = GTK_WIDGET (calendar);
1968 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
1970 gint row, week = 0, year;
1973 gint y_loc, day_height;
1974 PangoLayout *layout;
1975 PangoRectangle logical_rect;
1979 cr = gdk_cairo_create (priv->week_win);
1981 gtk_widget_style_get (GTK_WIDGET (widget),
1982 "focus-line-width", &focus_width,
1983 "focus-padding", &focus_padding,
1987 * Draw a rectangle as inverted background for the labels.
1990 gdk_cairo_set_source_color (cr, SELECTED_BG_COLOR (widget));
1991 if (priv->day_name_win)
1992 cairo_rectangle (cr,
1995 priv->week_width - CALENDAR_MARGIN,
1996 priv->main_h - CALENDAR_MARGIN);
1998 cairo_rectangle (cr,
2001 priv->week_width - CALENDAR_MARGIN,
2002 priv->main_h - 2 * CALENDAR_MARGIN);
2009 layout = gtk_widget_create_pango_layout (widget, NULL);
2011 gdk_cairo_set_source_color (cr, SELECTED_FG_COLOR (widget));
2012 day_height = calendar_row_height (calendar);
2013 for (row = 0; row < 6; row++)
2017 year = calendar->year;
2018 if (calendar->day[row][6] < 15 && row > 3 && calendar->month == 11)
2021 result = week_of_year (&week, &year,
2022 ((calendar->day[row][6] < 15 && row > 3 ? 1 : 0)
2023 + calendar->month) % 12 + 1, calendar->day[row][6]);
2024 g_return_if_fail (result);
2026 g_snprintf (buffer, sizeof (buffer), "%d", week);
2027 pango_layout_set_text (layout, buffer, -1);
2028 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
2030 y_loc = calendar_top_y_for_row (calendar, row) + (day_height - logical_rect.height) / 2;
2032 x_loc = (priv->week_width
2033 - logical_rect.width
2034 - CALENDAR_XSEP - focus_padding - focus_width);
2036 cairo_move_to (cr, x_loc, y_loc);
2037 pango_cairo_show_layout (cr, layout);
2040 g_object_unref (layout);
2045 calendar_invalidate_day_num (GtkCalendar *calendar,
2048 gint r, c, row, col;
2052 for (r = 0; r < 6; r++)
2053 for (c = 0; c < 7; c++)
2054 if (calendar->day_month[r][c] == MONTH_CURRENT &&
2055 calendar->day[r][c] == day)
2061 g_return_if_fail (row != -1);
2062 g_return_if_fail (col != -1);
2064 calendar_invalidate_day (calendar, row, col);
2068 calendar_invalidate_day (GtkCalendar *calendar,
2072 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
2076 GdkRectangle day_rect;
2078 calendar_day_rectangle (calendar, row, col, &day_rect);
2079 gdk_window_invalidate_rect (priv->main_win, &day_rect, FALSE);
2084 calendar_paint_day (GtkCalendar *calendar,
2088 GtkWidget *widget = GTK_WIDGET (calendar);
2089 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
2091 GdkColor *text_color;
2095 GdkRectangle day_rect;
2097 PangoLayout *layout;
2098 PangoRectangle logical_rect;
2100 g_return_if_fail (row < 6);
2101 g_return_if_fail (col < 7);
2103 cr = gdk_cairo_create (priv->main_win);
2105 day = calendar->day[row][col];
2107 calendar_day_rectangle (calendar, row, col, &day_rect);
2109 if (calendar->day_month[row][col] == MONTH_PREV)
2111 text_color = PREV_MONTH_COLOR (widget);
2113 else if (calendar->day_month[row][col] == MONTH_NEXT)
2115 text_color = NEXT_MONTH_COLOR (widget);
2120 if (calendar->highlight_row == row && calendar->highlight_col == col)
2122 cairo_set_source_color (cr, HIGHLIGHT_BG_COLOR (widget));
2123 gdk_cairo_rectangle (cr, &day_rect);
2127 if (calendar->selected_day == day)
2129 gdk_cairo_set_source_color (cr, SELECTED_BG_COLOR (widget));
2130 gdk_cairo_rectangle (cr, &day_rect);
2133 if (calendar->selected_day == day)
2134 text_color = SELECTED_FG_COLOR (widget);
2135 else if (calendar->marked_date[day-1])
2136 text_color = MARKED_COLOR (widget);
2138 text_color = NORMAL_DAY_COLOR (widget);
2141 g_snprintf (buffer, sizeof (buffer), "%d", day);
2142 layout = gtk_widget_create_pango_layout (widget, buffer);
2143 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
2145 x_loc = day_rect.x + day_rect.width / 2 + priv->max_day_char_width;
2146 x_loc -= logical_rect.width;
2147 y_loc = day_rect.y + (day_rect.height - logical_rect.height) / 2;
2149 gdk_cairo_set_source_color (cr, text_color);
2150 cairo_move_to (cr, x_loc, y_loc);
2151 pango_cairo_show_layout (cr, layout);
2153 if (calendar->marked_date[day-1]
2154 && calendar->day_month[row][col] == MONTH_CURRENT)
2156 cairo_move_to (cr, x_loc - 1, y_loc);
2157 pango_cairo_show_layout (cr, layout);
2160 if (GTK_WIDGET_HAS_FOCUS (calendar)
2161 && calendar->focus_row == row && calendar->focus_col == col)
2165 if (calendar->selected_day == day)
2166 state = GTK_WIDGET_HAS_FOCUS (widget) ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE;
2168 state = GTK_STATE_NORMAL;
2170 gtk_paint_focus (widget->style,
2172 (calendar->selected_day == day)
2173 ? GTK_STATE_SELECTED : GTK_STATE_NORMAL,
2174 NULL, widget, "calendar-day",
2175 day_rect.x, day_rect.y,
2176 day_rect.width, day_rect.height);
2179 g_object_unref (layout);
2184 calendar_paint_main (GtkCalendar *calendar)
2188 for (col = 0; col < 7; col++)
2189 for (row = 0; row < 6; row++)
2190 calendar_paint_day (calendar, row, col);
2194 calendar_invalidate_arrow (GtkCalendar *calendar,
2197 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
2200 window = priv->arrow_win[arrow];
2202 gdk_window_invalidate_rect (window, NULL, FALSE);
2206 calendar_paint_arrow (GtkCalendar *calendar,
2209 GtkWidget *widget = GTK_WIDGET (calendar);
2210 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2213 window = priv->arrow_win[arrow];
2216 cairo_t *cr = gdk_cairo_create (window);
2220 state = priv->arrow_state[arrow];
2222 gdk_cairo_set_source_color (cr, &widget->style->bg[state]);
2226 gdk_drawable_get_size (window, &width, &height);
2227 if (arrow == ARROW_MONTH_LEFT || arrow == ARROW_YEAR_LEFT)
2228 gtk_paint_arrow (widget->style, window, state,
2229 GTK_SHADOW_OUT, NULL, widget, "calendar",
2230 GTK_ARROW_LEFT, TRUE,
2231 width/2 - 3, height/2 - 4, 8, 8);
2233 gtk_paint_arrow (widget->style, window, state,
2234 GTK_SHADOW_OUT, NULL, widget, "calendar",
2235 GTK_ARROW_RIGHT, TRUE,
2236 width/2 - 2, height/2 - 4, 8, 8);
2241 gtk_calendar_expose (GtkWidget *widget,
2242 GdkEventExpose *event)
2244 GtkCalendar *calendar = GTK_CALENDAR (widget);
2245 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2248 if (GTK_WIDGET_DRAWABLE (widget))
2250 if (event->window == priv->main_win)
2251 calendar_paint_main (calendar);
2253 if (event->window == priv->header_win)
2254 calendar_paint_header (calendar);
2256 for (i = 0; i < 4; i++)
2257 if (event->window == priv->arrow_win[i])
2258 calendar_paint_arrow (calendar, i);
2260 if (event->window == priv->day_name_win)
2261 calendar_paint_day_names (calendar);
2263 if (event->window == priv->week_win)
2264 calendar_paint_week_numbers (calendar);
2265 if (event->window == widget->window)
2267 gtk_paint_shadow (widget->style, widget->window, GTK_WIDGET_STATE (widget),
2268 GTK_SHADOW_IN, NULL, widget, "calendar",
2269 0, 0, widget->allocation.width, widget->allocation.height);
2277 /****************************************
2279 ****************************************/
2281 #define CALENDAR_INITIAL_TIMER_DELAY 200
2282 #define CALENDAR_TIMER_DELAY 20
2285 calendar_arrow_action (GtkCalendar *calendar,
2290 case ARROW_YEAR_LEFT:
2291 calendar_set_year_prev (calendar);
2293 case ARROW_YEAR_RIGHT:
2294 calendar_set_year_next (calendar);
2296 case ARROW_MONTH_LEFT:
2297 calendar_set_month_prev (calendar);
2299 case ARROW_MONTH_RIGHT:
2300 calendar_set_month_next (calendar);
2308 calendar_timer (gpointer data)
2310 GtkCalendar *calendar = data;
2311 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
2312 gboolean retval = FALSE;
2314 GDK_THREADS_ENTER ();
2318 calendar_arrow_action (calendar, priv->click_child);
2320 if (priv->need_timer)
2322 priv->need_timer = FALSE;
2323 priv->timer = g_timeout_add (CALENDAR_TIMER_DELAY,
2324 (GSourceFunc) calendar_timer,
2325 (gpointer) calendar);
2331 GDK_THREADS_LEAVE ();
2337 calendar_start_spinning (GtkCalendar *calendar,
2340 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
2342 priv->click_child = click_child;
2346 priv->need_timer = TRUE;
2347 priv->timer = g_timeout_add (CALENDAR_INITIAL_TIMER_DELAY,
2354 calendar_stop_spinning (GtkCalendar *calendar)
2356 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
2360 g_source_remove (priv->timer);
2362 priv->need_timer = FALSE;
2367 calendar_main_button_press (GtkCalendar *calendar,
2368 GdkEventButton *event)
2370 GtkWidget *widget = GTK_WIDGET (calendar);
2371 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
2377 x = (gint) (event->x);
2378 y = (gint) (event->y);
2380 row = calendar_row_from_y (calendar, y);
2381 col = calendar_column_from_x (calendar, x);
2383 /* If row or column isn't found, just return. */
2384 if (row == -1 || col == -1)
2387 day_month = calendar->day_month[row][col];
2389 if (event->type == GDK_BUTTON_PRESS)
2391 day = calendar->day[row][col];
2393 if (day_month == MONTH_PREV)
2394 calendar_set_month_prev (calendar);
2395 else if (day_month == MONTH_NEXT)
2396 calendar_set_month_next (calendar);
2398 if (!GTK_WIDGET_HAS_FOCUS (widget))
2399 gtk_widget_grab_focus (widget);
2401 if (event->button == 1)
2404 priv->drag_start_x = x;
2405 priv->drag_start_y = y;
2408 calendar_select_and_focus_day (calendar, day);
2410 else if (event->type == GDK_2BUTTON_PRESS)
2413 if (day_month == MONTH_CURRENT)
2414 g_signal_emit (calendar,
2415 gtk_calendar_signals[DAY_SELECTED_DOUBLE_CLICK_SIGNAL],
2421 gtk_calendar_button_press (GtkWidget *widget,
2422 GdkEventButton *event)
2424 GtkCalendar *calendar = GTK_CALENDAR (widget);
2425 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2428 if (event->window == priv->main_win)
2429 calendar_main_button_press (calendar, event);
2431 if (!GTK_WIDGET_HAS_FOCUS (widget))
2432 gtk_widget_grab_focus (widget);
2434 for (arrow = ARROW_YEAR_LEFT; arrow <= ARROW_MONTH_RIGHT; arrow++)
2436 if (event->window == priv->arrow_win[arrow])
2439 /* only call the action on single click, not double */
2440 if (event->type == GDK_BUTTON_PRESS)
2442 if (event->button == 1)
2443 calendar_start_spinning (calendar, arrow);
2445 calendar_arrow_action (calendar, arrow);
2456 gtk_calendar_button_release (GtkWidget *widget,
2457 GdkEventButton *event)
2459 GtkCalendar *calendar = GTK_CALENDAR (widget);
2460 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2462 if (event->button == 1)
2464 calendar_stop_spinning (calendar);
2474 gtk_calendar_motion_notify (GtkWidget *widget,
2475 GdkEventMotion *event)
2477 GtkCalendar *calendar = GTK_CALENDAR (widget);
2478 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2479 gint event_x, event_y;
2481 gint old_row, old_col;
2483 event_x = (gint) (event->x);
2484 event_y = (gint) (event->y);
2486 if (event->window == priv->main_win)
2491 if (gtk_drag_check_threshold (widget,
2492 priv->drag_start_x, priv->drag_start_y,
2493 event->x, event->y))
2495 GdkDragContext *context;
2496 GtkTargetList *target_list = gtk_target_list_new (NULL, 0);
2497 gtk_target_list_add_text_targets (target_list, 0);
2498 context = gtk_drag_begin (widget, target_list, GDK_ACTION_COPY,
2499 1, (GdkEvent *)event);
2504 gtk_target_list_unref (target_list);
2505 gtk_drag_set_icon_default (context);
2510 row = calendar_row_from_y (calendar, event_y);
2511 col = calendar_column_from_x (calendar, event_x);
2513 if (row != calendar->highlight_row || calendar->highlight_col != col)
2515 old_row = calendar->highlight_row;
2516 old_col = calendar->highlight_col;
2517 if (old_row > -1 && old_col > -1)
2519 calendar->highlight_row = -1;
2520 calendar->highlight_col = -1;
2521 calendar_invalidate_day (calendar, old_row, old_col);
2524 calendar->highlight_row = row;
2525 calendar->highlight_col = col;
2527 if (row > -1 && col > -1)
2528 calendar_invalidate_day (calendar, row, col);
2536 gtk_calendar_enter_notify (GtkWidget *widget,
2537 GdkEventCrossing *event)
2539 GtkCalendar *calendar = GTK_CALENDAR (widget);
2540 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2542 if (event->window == priv->arrow_win[ARROW_MONTH_LEFT])
2544 priv->arrow_state[ARROW_MONTH_LEFT] = GTK_STATE_PRELIGHT;
2545 calendar_invalidate_arrow (calendar, ARROW_MONTH_LEFT);
2548 if (event->window == priv->arrow_win[ARROW_MONTH_RIGHT])
2550 priv->arrow_state[ARROW_MONTH_RIGHT] = GTK_STATE_PRELIGHT;
2551 calendar_invalidate_arrow (calendar, ARROW_MONTH_RIGHT);
2554 if (event->window == priv->arrow_win[ARROW_YEAR_LEFT])
2556 priv->arrow_state[ARROW_YEAR_LEFT] = GTK_STATE_PRELIGHT;
2557 calendar_invalidate_arrow (calendar, ARROW_YEAR_LEFT);
2560 if (event->window == priv->arrow_win[ARROW_YEAR_RIGHT])
2562 priv->arrow_state[ARROW_YEAR_RIGHT] = GTK_STATE_PRELIGHT;
2563 calendar_invalidate_arrow (calendar, ARROW_YEAR_RIGHT);
2570 gtk_calendar_leave_notify (GtkWidget *widget,
2571 GdkEventCrossing *event)
2573 GtkCalendar *calendar = GTK_CALENDAR (widget);
2574 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2578 if (event->window == priv->main_win)
2580 row = calendar->highlight_row;
2581 col = calendar->highlight_col;
2582 calendar->highlight_row = -1;
2583 calendar->highlight_col = -1;
2584 if (row > -1 && col > -1)
2585 calendar_invalidate_day (calendar, row, col);
2588 if (event->window == priv->arrow_win[ARROW_MONTH_LEFT])
2590 priv->arrow_state[ARROW_MONTH_LEFT] = GTK_STATE_NORMAL;
2591 calendar_invalidate_arrow (calendar, ARROW_MONTH_LEFT);
2594 if (event->window == priv->arrow_win[ARROW_MONTH_RIGHT])
2596 priv->arrow_state[ARROW_MONTH_RIGHT] = GTK_STATE_NORMAL;
2597 calendar_invalidate_arrow (calendar, ARROW_MONTH_RIGHT);
2600 if (event->window == priv->arrow_win[ARROW_YEAR_LEFT])
2602 priv->arrow_state[ARROW_YEAR_LEFT] = GTK_STATE_NORMAL;
2603 calendar_invalidate_arrow (calendar, ARROW_YEAR_LEFT);
2606 if (event->window == priv->arrow_win[ARROW_YEAR_RIGHT])
2608 priv->arrow_state[ARROW_YEAR_RIGHT] = GTK_STATE_NORMAL;
2609 calendar_invalidate_arrow (calendar, ARROW_YEAR_RIGHT);
2616 gtk_calendar_scroll (GtkWidget *widget,
2617 GdkEventScroll *event)
2619 GtkCalendar *calendar = GTK_CALENDAR (widget);
2621 if (event->direction == GDK_SCROLL_UP)
2623 if (!GTK_WIDGET_HAS_FOCUS (widget))
2624 gtk_widget_grab_focus (widget);
2625 calendar_set_month_prev (calendar);
2627 else if (event->direction == GDK_SCROLL_DOWN)
2629 if (!GTK_WIDGET_HAS_FOCUS (widget))
2630 gtk_widget_grab_focus (widget);
2631 calendar_set_month_next (calendar);
2640 /****************************************
2642 ****************************************/
2645 move_focus (GtkCalendar *calendar,
2648 GtkTextDirection text_dir = gtk_widget_get_direction (GTK_WIDGET (calendar));
2650 if ((text_dir == GTK_TEXT_DIR_LTR && direction == -1) ||
2651 (text_dir == GTK_TEXT_DIR_RTL && direction == 1))
2653 if (calendar->focus_col > 0)
2654 calendar->focus_col--;
2655 else if (calendar->focus_row > 0)
2657 calendar->focus_col = 6;
2658 calendar->focus_row--;
2663 if (calendar->focus_col < 6)
2664 calendar->focus_col++;
2665 else if (calendar->focus_row < 5)
2667 calendar->focus_col = 0;
2668 calendar->focus_row++;
2674 gtk_calendar_key_press (GtkWidget *widget,
2677 GtkCalendar *calendar;
2683 calendar = GTK_CALENDAR (widget);
2686 old_focus_row = calendar->focus_row;
2687 old_focus_col = calendar->focus_col;
2689 switch (event->keyval)
2694 if (event->state & GDK_CONTROL_MASK)
2695 calendar_set_month_prev (calendar);
2698 move_focus (calendar, -1);
2699 calendar_invalidate_day (calendar, old_focus_row, old_focus_col);
2700 calendar_invalidate_day (calendar, calendar->focus_row,
2701 calendar->focus_col);
2707 if (event->state & GDK_CONTROL_MASK)
2708 calendar_set_month_next (calendar);
2711 move_focus (calendar, 1);
2712 calendar_invalidate_day (calendar, old_focus_row, old_focus_col);
2713 calendar_invalidate_day (calendar, calendar->focus_row,
2714 calendar->focus_col);
2720 if (event->state & GDK_CONTROL_MASK)
2721 calendar_set_year_prev (calendar);
2724 if (calendar->focus_row > 0)
2725 calendar->focus_row--;
2726 calendar_invalidate_day (calendar, old_focus_row, old_focus_col);
2727 calendar_invalidate_day (calendar, calendar->focus_row,
2728 calendar->focus_col);
2734 if (event->state & GDK_CONTROL_MASK)
2735 calendar_set_year_next (calendar);
2738 if (calendar->focus_row < 5)
2739 calendar->focus_row++;
2740 calendar_invalidate_day (calendar, old_focus_row, old_focus_col);
2741 calendar_invalidate_day (calendar, calendar->focus_row,
2742 calendar->focus_col);
2747 row = calendar->focus_row;
2748 col = calendar->focus_col;
2749 day = calendar->day[row][col];
2751 if (row > -1 && col > -1)
2755 if (calendar->day_month[row][col] == MONTH_PREV)
2756 calendar_set_month_prev (calendar);
2757 else if (calendar->day_month[row][col] == MONTH_NEXT)
2758 calendar_set_month_next (calendar);
2760 calendar_select_and_focus_day (calendar, day);
2768 /****************************************
2769 * Misc widget methods *
2770 ****************************************/
2773 calendar_set_background (GtkWidget *widget)
2775 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2778 if (GTK_WIDGET_REALIZED (widget))
2780 for (i = 0; i < 4; i++)
2782 if (priv->arrow_win[i])
2783 gdk_window_set_background (priv->arrow_win[i],
2784 HEADER_BG_COLOR (widget));
2786 if (priv->header_win)
2787 gdk_window_set_background (priv->header_win,
2788 HEADER_BG_COLOR (widget));
2789 if (priv->day_name_win)
2790 gdk_window_set_background (priv->day_name_win,
2791 BACKGROUND_COLOR (widget));
2793 gdk_window_set_background (priv->week_win,
2794 BACKGROUND_COLOR (widget));
2796 gdk_window_set_background (priv->main_win,
2797 BACKGROUND_COLOR (widget));
2799 gdk_window_set_background (widget->window,
2800 BACKGROUND_COLOR (widget));
2805 gtk_calendar_style_set (GtkWidget *widget,
2806 GtkStyle *previous_style)
2808 if (previous_style && GTK_WIDGET_REALIZED (widget))
2809 calendar_set_background (widget);
2813 gtk_calendar_state_changed (GtkWidget *widget,
2814 GtkStateType previous_state)
2816 GtkCalendar *calendar = GTK_CALENDAR (widget);
2817 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2820 if (!GTK_WIDGET_IS_SENSITIVE (widget))
2823 calendar_stop_spinning (calendar);
2826 for (i = 0; i < 4; i++)
2827 if (GTK_WIDGET_IS_SENSITIVE (widget))
2828 priv->arrow_state[i] = GTK_STATE_NORMAL;
2830 priv->arrow_state[i] = GTK_STATE_INSENSITIVE;
2832 calendar_set_background (widget);
2836 gtk_calendar_grab_notify (GtkWidget *widget,
2837 gboolean was_grabbed)
2840 calendar_stop_spinning (GTK_CALENDAR (widget));
2844 gtk_calendar_focus_out (GtkWidget *widget,
2845 GdkEventFocus *event)
2847 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2849 calendar_stop_spinning (GTK_CALENDAR (widget));
2857 /****************************************
2859 ****************************************/
2862 gtk_calendar_drag_data_get (GtkWidget *widget,
2863 GdkDragContext *context,
2864 GtkSelectionData *selection_data,
2868 GtkCalendar *calendar = GTK_CALENDAR (widget);
2873 date = g_date_new_dmy (calendar->selected_day, calendar->month + 1, calendar->year);
2874 len = g_date_strftime (str, 127, "%x", date);
2875 gtk_selection_data_set_text (selection_data, str, len);
2880 /* Get/set whether drag_motion requested the drag data and
2881 * drag_data_received should thus not actually insert the data,
2882 * since the data doesn't result from a drop.
2885 set_status_pending (GdkDragContext *context,
2886 GdkDragAction suggested_action)
2888 g_object_set_data (G_OBJECT (context),
2889 I_("gtk-calendar-status-pending"),
2890 GINT_TO_POINTER (suggested_action));
2893 static GdkDragAction
2894 get_status_pending (GdkDragContext *context)
2896 return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context),
2897 "gtk-calendar-status-pending"));
2901 gtk_calendar_drag_leave (GtkWidget *widget,
2902 GdkDragContext *context,
2905 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2907 priv->drag_highlight = 0;
2908 gtk_drag_unhighlight (widget);
2913 gtk_calendar_drag_motion (GtkWidget *widget,
2914 GdkDragContext *context,
2919 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (widget);
2922 if (!priv->drag_highlight)
2924 priv->drag_highlight = 1;
2925 gtk_drag_highlight (widget);
2928 target = gtk_drag_dest_find_target (widget, context, NULL);
2929 if (target == GDK_NONE)
2930 gdk_drag_status (context, 0, time);
2933 set_status_pending (context, context->suggested_action);
2934 gtk_drag_get_data (widget, context, target, time);
2941 gtk_calendar_drag_drop (GtkWidget *widget,
2942 GdkDragContext *context,
2949 target = gtk_drag_dest_find_target (widget, context, NULL);
2950 if (target != GDK_NONE)
2952 gtk_drag_get_data (widget, context,
2962 gtk_calendar_drag_data_received (GtkWidget *widget,
2963 GdkDragContext *context,
2966 GtkSelectionData *selection_data,
2970 GtkCalendar *calendar = GTK_CALENDAR (widget);
2971 guint day, month, year;
2974 GdkDragAction suggested_action;
2976 suggested_action = get_status_pending (context);
2978 if (suggested_action)
2980 set_status_pending (context, 0);
2982 /* We are getting this data due to a request in drag_motion,
2983 * rather than due to a request in drag_drop, so we are just
2984 * supposed to call drag_status, not actually paste in the
2987 str = gtk_selection_data_get_text (selection_data);
2990 date = g_date_new ();
2991 g_date_set_parse (date, str);
2992 if (!g_date_valid (date))
2993 suggested_action = 0;
2998 suggested_action = 0;
3000 gdk_drag_status (context, suggested_action, time);
3005 date = g_date_new ();
3006 str = gtk_selection_data_get_text (selection_data);
3009 g_date_set_parse (date, str);
3013 if (!g_date_valid (date))
3015 g_warning ("Received invalid date data\n");
3017 gtk_drag_finish (context, FALSE, FALSE, time);
3021 day = g_date_get_day (date);
3022 month = g_date_get_month (date);
3023 year = g_date_get_year (date);
3026 gtk_drag_finish (context, TRUE, FALSE, time);
3029 g_object_freeze_notify (G_OBJECT (calendar));
3030 if (!(calendar->display_flags & GTK_CALENDAR_NO_MONTH_CHANGE)
3031 && (calendar->display_flags & GTK_CALENDAR_SHOW_HEADING))
3032 gtk_calendar_select_month (calendar, month - 1, year);
3033 gtk_calendar_select_day (calendar, day);
3034 g_object_thaw_notify (G_OBJECT (calendar));
3038 /****************************************
3040 ****************************************/
3045 * Creates a new calendar, with the current date being selected.
3047 * Return value: a newly #GtkCalendar widget
3050 gtk_calendar_new (void)
3052 return g_object_new (GTK_TYPE_CALENDAR, NULL);
3056 * gtk_calendar_display_options:
3057 * @calendar: a #GtkCalendar.
3058 * @flags: the display options to set.
3060 * Sets display options (whether to display the heading and the month headings).
3062 * Deprecated: Use gtk_calendar_set_display_options() instead
3065 gtk_calendar_display_options (GtkCalendar *calendar,
3066 GtkCalendarDisplayOptions flags)
3068 gtk_calendar_set_display_options (calendar, flags);
3072 * gtk_calendar_get_display_options:
3073 * @calendar: a #GtkCalendar
3075 * Returns the current display options of @calendar.
3077 * Return value: the display options.
3081 GtkCalendarDisplayOptions
3082 gtk_calendar_get_display_options (GtkCalendar *calendar)
3084 g_return_val_if_fail (GTK_IS_CALENDAR (calendar), 0);
3086 return calendar->display_flags;
3090 * gtk_calendar_set_display_options:
3091 * @calendar: a #GtkCalendar
3092 * @flags: the display options to set
3094 * Sets display options (whether to display the heading and the month
3100 gtk_calendar_set_display_options (GtkCalendar *calendar,
3101 GtkCalendarDisplayOptions flags)
3103 GtkWidget *widget = GTK_WIDGET (calendar);
3104 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
3107 GtkCalendarDisplayOptions old_flags;
3109 g_return_if_fail (GTK_IS_CALENDAR (calendar));
3111 old_flags = calendar->display_flags;
3113 if (GTK_WIDGET_REALIZED (widget))
3115 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_NO_MONTH_CHANGE)
3118 if (! (flags & GTK_CALENDAR_NO_MONTH_CHANGE)
3119 && (priv->header_win))
3121 calendar->display_flags &= ~GTK_CALENDAR_NO_MONTH_CHANGE;
3122 calendar_realize_arrows (calendar);
3126 for (i = 0; i < 4; i++)
3128 if (priv->arrow_win[i])
3130 gdk_window_set_user_data (priv->arrow_win[i],
3132 gdk_window_destroy (priv->arrow_win[i]);
3133 priv->arrow_win[i] = NULL;
3139 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_HEADING)
3143 if (flags & GTK_CALENDAR_SHOW_HEADING)
3145 calendar->display_flags |= GTK_CALENDAR_SHOW_HEADING;
3146 calendar_realize_header (calendar);
3150 for (i = 0; i < 4; i++)
3152 if (priv->arrow_win[i])
3154 gdk_window_set_user_data (priv->arrow_win[i],
3156 gdk_window_destroy (priv->arrow_win[i]);
3157 priv->arrow_win[i] = NULL;
3160 gdk_window_set_user_data (priv->header_win, NULL);
3161 gdk_window_destroy (priv->header_win);
3162 priv->header_win = NULL;
3167 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_DAY_NAMES)
3171 if (flags & GTK_CALENDAR_SHOW_DAY_NAMES)
3173 calendar->display_flags |= GTK_CALENDAR_SHOW_DAY_NAMES;
3174 calendar_realize_day_names (calendar);
3178 gdk_window_set_user_data (priv->day_name_win, NULL);
3179 gdk_window_destroy (priv->day_name_win);
3180 priv->day_name_win = NULL;
3184 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
3188 if (flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
3190 calendar->display_flags |= GTK_CALENDAR_SHOW_WEEK_NUMBERS;
3191 calendar_realize_week_numbers (calendar);
3195 gdk_window_set_user_data (priv->week_win, NULL);
3196 gdk_window_destroy (priv->week_win);
3197 priv->week_win = NULL;
3201 if ((flags ^ calendar->display_flags) & GTK_CALENDAR_WEEK_START_MONDAY)
3202 g_warning ("GTK_CALENDAR_WEEK_START_MONDAY is ignored; the first day of the week is determined from the locale");
3204 calendar->display_flags = flags;
3206 gtk_widget_queue_resize (GTK_WIDGET (calendar));
3210 calendar->display_flags = flags;
3212 g_object_freeze_notify (G_OBJECT (calendar));
3213 if ((old_flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_HEADING)
3214 g_object_notify (G_OBJECT (calendar), "show-heading");
3215 if ((old_flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_DAY_NAMES)
3216 g_object_notify (G_OBJECT (calendar), "show-day-names");
3217 if ((old_flags ^ calendar->display_flags) & GTK_CALENDAR_NO_MONTH_CHANGE)
3218 g_object_notify (G_OBJECT (calendar), "no-month-change");
3219 if ((old_flags ^ calendar->display_flags) & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
3220 g_object_notify (G_OBJECT (calendar), "show-week-numbers");
3221 g_object_thaw_notify (G_OBJECT (calendar));
3225 * gtk_calendar_select_month:
3226 * @calendar: a #GtkCalendar
3227 * @month: a month number between 0 and 11.
3228 * @year: the year the month is in.
3230 * Shifts the calendar to a different month.
3232 * Return value: %TRUE, always
3235 gtk_calendar_select_month (GtkCalendar *calendar,
3239 g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE);
3240 g_return_val_if_fail (month <= 11, FALSE);
3242 calendar->month = month;
3243 calendar->year = year;
3245 calendar_compute_days (calendar);
3247 gtk_widget_queue_draw (GTK_WIDGET (calendar));
3249 g_object_freeze_notify (G_OBJECT (calendar));
3250 g_object_notify (G_OBJECT (calendar), "month");
3251 g_object_notify (G_OBJECT (calendar), "year");
3252 g_object_thaw_notify (G_OBJECT (calendar));
3254 g_signal_emit (calendar,
3255 gtk_calendar_signals[MONTH_CHANGED_SIGNAL],
3261 * gtk_calendar_select_day:
3262 * @calendar: a #GtkCalendar.
3263 * @day: the day number between 1 and 31, or 0 to unselect
3264 * the currently selected day.
3266 * Selects a day from the current month.
3269 gtk_calendar_select_day (GtkCalendar *calendar,
3272 g_return_if_fail (GTK_IS_CALENDAR (calendar));
3273 g_return_if_fail (day <= 31);
3275 /* Deselect the old day */
3276 if (calendar->selected_day > 0)
3280 selected_day = calendar->selected_day;
3281 calendar->selected_day = 0;
3282 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
3283 calendar_invalidate_day_num (calendar, selected_day);
3286 calendar->selected_day = day;
3288 /* Select the new day */
3291 if (GTK_WIDGET_DRAWABLE (GTK_WIDGET (calendar)))
3292 calendar_invalidate_day_num (calendar, day);
3295 g_object_notify (G_OBJECT (calendar), "day");
3297 g_signal_emit (calendar,
3298 gtk_calendar_signals[DAY_SELECTED_SIGNAL],
3303 * gtk_calendar_clear_marks:
3304 * @calendar: a #GtkCalendar
3306 * Remove all visual markers.
3309 gtk_calendar_clear_marks (GtkCalendar *calendar)
3313 g_return_if_fail (GTK_IS_CALENDAR (calendar));
3315 for (day = 0; day < 31; day++)
3317 calendar->marked_date[day] = FALSE;
3320 calendar->num_marked_dates = 0;
3322 gtk_widget_queue_draw (GTK_WIDGET (calendar));
3326 * gtk_calendar_mark_day:
3327 * @calendar: a #GtkCalendar
3328 * @day: the day number to mark between 1 and 31.
3330 * Places a visual marker on a particular day.
3332 * Return value: %TRUE, always
3335 gtk_calendar_mark_day (GtkCalendar *calendar,
3338 g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE);
3340 if (day >= 1 && day <= 31 && calendar->marked_date[day-1] == FALSE)
3342 calendar->marked_date[day - 1] = TRUE;
3343 calendar->num_marked_dates++;
3344 calendar_invalidate_day_num (calendar, day);
3351 * gtk_calendar_unmark_day:
3352 * @calendar: a #GtkCalendar.
3353 * @day: the day number to unmark between 1 and 31.
3355 * Removes the visual marker from a particular day.
3357 * Return value: %TRUE, always
3360 gtk_calendar_unmark_day (GtkCalendar *calendar,
3363 g_return_val_if_fail (GTK_IS_CALENDAR (calendar), FALSE);
3365 if (day >= 1 && day <= 31 && calendar->marked_date[day-1] == TRUE)
3367 calendar->marked_date[day - 1] = FALSE;
3368 calendar->num_marked_dates--;
3369 calendar_invalidate_day_num (calendar, day);
3376 * gtk_calendar_get_date:
3377 * @calendar: a #GtkCalendar
3378 * @year: location to store the year number, or %NULL
3379 * @month: location to store the month number (between 0 and 11), or %NULL
3380 * @day: location to store the day number (between 1 and 31), or %NULL
3382 * Obtains the selected date from a #GtkCalendar.
3385 gtk_calendar_get_date (GtkCalendar *calendar,
3390 g_return_if_fail (GTK_IS_CALENDAR (calendar));
3393 *year = calendar->year;
3396 *month = calendar->month;
3399 *day = calendar->selected_day;
3403 * gtk_calendar_freeze:
3404 * @calendar: a #GtkCalendar
3406 * Does nothing. Previously locked the display of the calendar until
3407 * it was thawed with gtk_calendar_thaw().
3410 gtk_calendar_freeze (GtkCalendar *calendar)
3412 g_return_if_fail (GTK_IS_CALENDAR (calendar));
3416 * gtk_calendar_thaw:
3417 * @calendar: a #GtkCalendar
3419 * Does nothing. Previously defrosted a calendar; all the changes made
3420 * since the last gtk_calendar_freeze() were displayed.
3423 gtk_calendar_thaw (GtkCalendar *calendar)
3425 g_return_if_fail (GTK_IS_CALENDAR (calendar));
3428 #define __GTK_CALENDAR_C__
3429 #include "gtkaliasdef.c"